Index: vendor/NetBSD/bmake/20201101/ChangeLog =================================================================== --- vendor/NetBSD/bmake/20201101/ChangeLog (nonexistent) +++ vendor/NetBSD/bmake/20201101/ChangeLog (revision 367461) @@ -0,0 +1,2999 @@ +2020-11-01 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201101 + Merge with NetBSD make, pick up + o negate NoExecute to GNode_ShouldExecute + o job.c: rename JobMatchShell to FindShellByName + extract EscapeShellDblQuot from JobPrintCommand + extract ParseRunOptions from JobPrintCommand + o var.c: extract ApplyModifiersIndirect from ApplyModifiers + treat malformed :range, :ts and :[...] as errors + add tests for the variable modifiers :[words] and :range + +2020-10-31 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201031 + Merge with NetBSD make, pick up + o format #include directives consistently + o do not look up local variables like .TARGET anywhere else + o main.c: Main_SetObjdir is first called for curdir which may be + readonly + reduce the scope where recursive expressions are detected + remove redundant :tl from getBoolean + clean up mkTempFile + o meta.c: simplify memory allocation in meta_create and meta_oodate + o parse.c: extract loadedfile_mmap from loadfile + o trace.c: document possible undefined behavior with .CURDIR + o var.c: make parsing of the :gmtime and :localtime modifiers stricter + rename ismeta to is_shell_metachar + remove debug logging for the :Q variable modifier + rename VarIsDynamic to VarnameIsDynamic + use consistent parameter order in varname parsing functions + extract ParseVarnameLong from Var_Parse + extract ParseVarnameShort from Var_Parse + fix type of ParseModifierPart parameter delim + extract IsEscapedModifierPart from ParseModifierPart + clean up ModifyWords + add test for combining the :@ and :? variable modifiers + +2020-10-30 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201030 + Merge with NetBSD make, pick up + o change char * to void * in Var_Value + o make iterating over HashTable simpler + o rename VAR_CMD to VAR_CMDLINE + o cond.c: clean up is_separator + fix parse error in string literal in conditional + o main.c: do not use objdir that is not writable + in lint mode, exit with error status on errors + o parse.c: clean up StrContainsWord + fix out-of-bounds pointer in ParseTrackInput + o var.c: rename Str_SYSVMatch and its parameters + remove unsatisfiable conditions in Var_Set_with_flags + document where the variable name is expanded + fix documentation for VARP_SUB_ONE + rename VAR_EXPORTED_YES to VAR_EXPORTED_SOME + document VAR_READONLY + prevent appending to read-only variables + extract MayExport from Var_Export1 + remove redundant evaluations in VarFind + replace VarFindFlags with a simple Boolean + rename FIND_CMD to FIND_CMDLINE, to match VAR_CMDLINE + +2020-10-28 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201028 + Merge with NetBSD make, pick up + o rename defIncPath to defSysIncPath + o initialize all CmdOpts fields + o lst.c: inline Vector_Get + o main.c: refactor main extract + InitMaxJobs,InitObjdir,InitVarMake,InitRandom, + ReadMakefiles,CleanUp,InitVpath,ReadBuiltinRules, + InitDefIncPath,CmdOpts_Init,UnlimitFiles + o parse.c: merge curFile into includes + rename predecessor to order_pred + sort ParseSpecial alphabetically + remove unused, undocumented .NOEXPORT + rename ParseSpecial enum values consistently + rename some fields of struct IFile + +2020-10-26 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201026 + Merge with NetBSD make, pick up + o group the command line options and arguments into a struct + o rename GNode.cmgn to youngestChild + o rename hash functions to identify the type name + o negate OP_NOP and rename it to GNode_IsTarget + o add GNode_Path to access the path of a GNode + o remove macros MIN and MAX + o remove unused Lst_Find and Lst_FindFrom + o arch.c: and make Arch_FindLib simpler + clean up code layout + make Arch_ParseArchive simpler + o cond.c: inline CondFindStrMatch into FuncMake + o dir.c: replace Dir_CopyDir with Dir_CopyDirSearchPath + omit trailing space in debug output for expanding file patterns + refactor DirMatchFiles + document that the SearchPath of Dir_FindFile may be NULL + remove UNCONST from Dir_Expand + inline DirFindName + o for.c: clean up code for handling .for loops + o hash.c: print hash in debug log with fixed width + clean up hash table functions + reduce amount of string hashing + o job.c: refactor JobDeleteTarget + use proper enum constants for aborting + convert result of JobStart from macros to enum + convert abort reason macros to enum + rework Job_CheckCommands to reduce indentation + rename Shell fields + add field names in declaration of DEFSHELL_CUSTOM + convert JobState and JobFlags to enum types + move handling of the "..." command to JobPrintCommands + o lst.c: clean up + refactor LstNodeNew + remove Lst_Open, Lst_Next, Lst_Close + remove code for circular lists from Lst_Next + o main.c: do not attempt to read .MAKE.DEPENFILE if set to + /dev/null or anything starting with "no" + convert macros for debug flags into enum + o make.c: inline Lst_Copy in Make_ExpandUse + o meta.c: inline Lst_Find in meta_oodate + make Lst_RemoveIf simpler in meta_oodate + o parse.c: convert error level for Parse_Error to an enum + o suff.c: properly terminate debug output with newline + add more details to DEBUG_SRC log + replace Dir_CopyDir with Dir_CopyDirSearchPath + don't modify GNode name while rebuilding the suffix graph + o var.c: reduce duplicate code in VarFind + +2020-10-22 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201022 + Merge with NetBSD make, pick up + o more refactoring and simplification to reduce code size + o var.c: extract CanonicalVarname from VarFind + o make.c: extract UpdateImplicitParentsVars from Make_Update + o main.c: extract PrintVar from doPrintVars + extract HandlePWD from main + o lst.c: inline simple Lst getters + remove unused Lst_ForEach + o job.c: move struct Shell from job.h to job.c + o more unit tests + +2020-10-19 Simon J Gerraty + + * configure.in: remove inappropriate use of AC_INCLUDES_DEFAULT + +2020-10-18 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201018 + Merge with NetBSD make, pick up + o remove USE_IOVEC + o rename some Hash_* apis to Hash* + o replace execError with execDie + o rename Lst_Init to Lst_New + o add tags to enum types + o rename Stack to Vector + o parse.c: more refactoring + o unit-tests: make some tests use line buffered stdout + o unit-tests/Makefile: in meta mode do not make all tests depend on + Makefile, it isn't necessary. + +2020-10-10 Simon J Gerraty + + * main.c: check for CTL_HW being defined. + * unit-tests/Makefile: ensure export tests output are POSIX compliant + disable opt-debug-jobs test until it works on ubuntu + + * VERSION (_MAKE_VERSION): 20201010 + Merge with NetBSD make, pick up + o dir.c: remove pathname limit for Dir_FindHereOrAbove + o hash.c: replace strcpy with memcpy in Hash_CreateEntry + o main.c: extract init_machine and init_machine_arch from main + allow to disable debug logging options + o parse.c: enable format string truncation warnings + extract parsing of sources from ParseDoDependency + split ParseDoSrc into smaller functions + hide implementation details from Parse_DoVar + clean up parsing of variable assignments + split Parse_DoVar into manageable pieces + don't modify the given line during Parse_DoVar + fix out-of-bounds memory access in Parse_DoVar + fix parsing of the :sh assignment modifier + o var.c: rework memory allocation for the name of variables + extract ApplyModifier_Literal into separate function + in lint mode, reject modifiers without delimiter + do not export variable names starting with '-' + o fix double-free bug in -DCLEANUP mode + o more cleanup to enable higher warnings level + o more unit tests + +2020-10-02 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201002 + Merge with NetBSD make, pick up + o dir.c: use hash table for looking up open directories by name + o main.c: clean up option handling + o parse.c: add missing const for Parse_AddIncludeDir + o var.c: ApplyModifier_To, update pp in each branch + o remove redundant function prototypes + o more unit tests + +2020-10-01 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20201001 + Merge with NetBSD make, pick up + o compat.c: comment about "..." + +2020-09-30 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200930 + Merge with NetBSD make, pick up + o job.c: split Job.jobPipe into 2 separate fields + replace Lst_Open with direct iteration + o lst.c: remove redundant assertions + o targ.c: replace Lst_Open with direct iteration + o var.c: fix bug in evaluation of indirect variable modifiers + extract ApplyModifier_Quote into separate function + o make debug logging simpler + +2020-09-27 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200927 + Merge with NetBSD make, pick up + o parse.c: ensure parse errors result in 'stopped in' message. + o compat.c: make parameter of Compat_RunCommand const + o main.c: extract InitVarTarget from main + o parse.c: rename ParseFinishLine to FinishDependencyGroup + refactor ParseDoDependency + o var.c: Var_Subst no longer returns string result + rename Var_ParsePP back to Var_Parse + in lint mode, improve error handling for undefined variables + extract ParseVarname from Var_Parse + o rename Lst_ForEach to Lst_ForEachUntil + o inline Lst_ForEachUntil in several cases + o clean up API for finding and creating GNodes + o fix assertion failure in -j mode with .END node + o inline and remove LstNode_Prev and LstNode_Next + o use fine-grained type names for lists and their nodes + o more unit tests + +2020-09-11 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200911 + Merge with NetBSD make, pick up + o cond.c: split EvalComparison into smaller functions + reorder parameters of condition parsing functions + reduce code size in CondParser_Eval + rename CondGetString to CondParser_String + add CondLexer_SkipWhitespace + group the condition parsing state into a struct + in CondGetString, replace repeated Buf_Add with Buf_AddStr + o migrate Var_Parse to Var_ParsePP + o add wrappers around ctype.h functions + o lst.c: use a stack instead of a list for the nested include path + o more unit tests + +2020-09-04 Simon J Gerraty + + * make-bootstrap.sh.in: adjust object list + +2020-09-02 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200902 + Merge with NetBSD make, pick up + o use make_stat to ensure no confusion over valid fields + returned by cached_stat + o var.c: make VarQuote const-correct + o add unit tests for .for + +2020-09-01 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200901 + Merge with NetBSD make, pick up + o rename Hash_Table fields + o make data types in Dir_HasWildcards more precise + +2020-08-31 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200831 + Merge with NetBSD make, pick up + o suff.c: fix unbalanced Lst_Open/Lst_Close in SuffFindCmds + o lst.c: Lst_Open renable assert that list isn't open + o unit test for .TARGET dependent flags + o var.c: fix aliasing bug in VarUniq + o more unit tests for :u + +2020-08-30 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200830 + Merge with NetBSD make, pick up + o allow for strict type checking for Boolean + o Var_Parse never returns NULL + o Var_Subst never returns NULL + o Lst_Find now takes boolean match function + o rename Lst_Memeber to Lst_FindDatum + o rename LstNode functions to match their type + o rename GNode.iParents to implicitParents + o fix assertion failure for .SUFFIXES in archives + o compat.c: clean up documentation for CompatInterrupt and Compat_Run + remove unreachable code from CompatRunCommand + o main.c: simplify getBoolean + o stc.c: replace brk_string with simpler Str_Words + o suff.c: add debug macros + +2020-08-28 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200828 + Merge with NetBSD make, pick up + o lst.c: inline LstIsValid and LstNodeIsValid + o remove trailing S from Lst function names after migration complete + o more comment cleanup/clarification + o suff.c: clean up suffix handling + o more unit tests + +2020-08-26 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200826 + Merge with NetBSD make, pick up + o enum.c: distinguish between bitsets containing flags and + ordinary enums + o var.c: fix error message for ::!= modifier with shell error + o fix bugs in -DCLEANUP mode + +2020-08-24 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200824 + Merge with NetBSD make, pick up + o in debug mode, print GNode details in symbols + +2020-08-23 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200823 + Merge with NetBSD make, pick up + o lst.c: more asserts, + make args to Lst_Find match others. + o var.c: pass flags to VarAdd + o arch.c: use Buffer + o str.c: brk_string return size_t for nwords + o more unit tests + +2020-08-22 Simon J Gerraty + + * VERSION (_MAKE_VERSION): + Merge with NetBSD make, pick up + o var.c: support for read-only variables eg .SHELL + being the shell used to run scripts. + o lst.c: more simplification + o more documentation and style cleanup + o more unit tests + o ensure unit-test/Makefile is run by TEST_MAKE + o reduce duplication of header inclusion + +2020-08-21 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200821 + Merge with NetBSD make, pick up + o lst.c: revert invalid assertion - but document it + o dir.c: split Dir_Init into two functions + +2020-08-20 Simon J Gerraty + + * lst.c: needs inttypes.h on Linux + + * VERSION (_MAKE_VERSION): 20200820 + Merge with NetBSD make, pick up + o make.1: clarify some passages + o var.c: more cleanup, clarify comments + o make_malloc.c: remove unreachable code + o cond.c: make CondGetString easier to debug + o simplify list usage + o unit-tests: more + +2020-08-16 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200816 + Merge with NetBSD make, pick up + o refactor unit-tests to be more fine grained + not all tests moved yet + +2020-08-14 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200814 + Merge with NetBSD make, pick up + o more str_concat variants + o more enums for flags + o var.c: cleanup for higher warnings level + +2020-08-10 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200810 + Merge with NetBSD make, pick up + o more unit tests + o general comment and style cleanup + +2020-08-08 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200808 + Merge with NetBSD make, pick up + o enum.[ch]: streamline, enums for use in flags and debug output + o cond.c: cleanup + o var.c: reduce duplicate code for modifiers + debug logging for Var_Parse + more detailed debug output + o more unit tests + +2020-08-06 Simon J Gerraty + + * unit-tests/Makefile: -r for recursive and include Makefile.inc + so I can run tests in meta mode + supress extra noise if in meta mode + + * VERSION (_MAKE_VERSION): 20200806 + Merge with NetBSD make, pick up + o parse.c: remove VARE_WANTRES for LINT + we just want to check parsing (for now). + +2020-08-05 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200805 + Merge with NetBSD make, pick up + o make.1: Rework the description of dependence operators + +2020-08-03 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200803 + Merge with NetBSD make, pick up + o revert some C99 usage, for max portability + o unit-tests/lint + +2020-08-02 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200802 + Merge with NetBSD make, pick up + o more unit tests + +2020-08-01 Simon J Gerraty + + * Remove NetBSD specific plumbing from unit-tests/Makefile + + * VERSION (_MAKE_VERSION): 20200801 + Merge with NetBSD make, pick up + o make Var_Value return const + o size_t for buf sizes + o optimize some buffer operations - avoid strlen + +2020-07-31 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200731 + Merge with NetBSD make, pick up + o var.c: fix undefinded behavior for incomplete :t modifier + fixes unit-test/moderrs on Ubuntu + o parse.c: When parsing variable assignments other than := + if DEBUG(LINT) test substition of value, so we get a file and + line number in the resulting error. + o dir.c: fix parsing of nested braces in dependency lines + add unit-tests + +2020-07-30 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200730 + Merge with NetBSD make, pick up + o var.c: minor cleanup + o unit-tests: more tests to improve code coverage + +2020-07-28 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200728 + Merge with NetBSD make, pick up + o var.c: more optimizations + +2020-07-26 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200726 + Merge with NetBSD make, pick up + o collapse lsd.lib into lst.c - reduce code size and allow inlining + o lots of function comment updates + o var.c: more optimizations + o make return of Var_Parse const + +2020-07-20 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200720 + Merge with NetBSD make, pick up + o DEBUG_HASH report stats at end and tone down the noise + o var.c: each flag type gets its own prefix. + move SysV string matching to var.c + make ampersand in ${VAR:from=to&} an ordinary character + cleanup and simplify implementation of modifiers + o make.1: move documentation for assignment modifiers + +2020-07-18 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200718 + Merge with NetBSD make, pick up + o DEBUG_HASH to see how well the hash tables are working + +2020-07-11 Simon J Gerraty + + * bsd.after-import.mk: make sure we update unit-tests/Makefile + +2020-07-10 Simon J Gerraty + + * configure.in: use AC_INCLUDES_DEFAULT rather than AC_HEADER_STDC + + * VERSION (_MAKE_VERSION): 20200710 + Merge with NetBSD make, pick up + o filemon/filemon_dev.c: use O_CLOEXEC rather than extra syscall + o meta.c: target flagged .META is out-of-date if meta file missing + +2020-07-09 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200709 + Merge with NetBSD make, pick up + o cond.c: fix for compare_expression when doEval=0 + o unit-tests/Makefile: rework + o filemon/filemon_dev.c: ensure filemon fd is closed on exec. + +2020-07-04 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200704 + Merge with NetBSD make, pick up + (most of this by rillig@) + o lots of style and white-space cleanup + o lots more unit tests for variable modifiers + o simplified description of some functions + o str.c: refactor Str_Match + o var.c: debugging output for :@ + constify VarModify parameter + fix :hash modifier on 16-bit platforms + remove unnecessary forward declarations + refactor ApplyModifier_SysV to have less indentation + simplify code for :E and :R + clean up code for :H and :T + refactor ApplyModifiers + + * var.c: we need stdint.h on some platforms to get uint32_t + * unit-test/Makefile: we need to supress the specific error + for RE substitution error in modmisc, since it varies accross + different OS. + +2020-07-02 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200702 + Merge with NetBSD make, pick up + o var.c: more improvements to avoiding unnecessary evaluation + use enums for flags + o remove flags arg to Var_Set which outside of var.c is always 0 + +2020-07-01 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200701 + Merge with NetBSD make, pick up + o var.c: with change to cond.c; ensure that nested variables + within a variable name are expanded. + o unit-tests/varmisc.mk: test for nested varname + +2020-06-29 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200629 + Merge with NetBSD make, pick up + o cond.c: do not eval unnecessary terms of conditionals. + +2020-06-25 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200625 + Merge with NetBSD make, pick up + o meta.c: report error if lseek in filemon_read fails + +2020-06-22 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200622 + Merge with NetBSD make, pick up + o dieQuietly: ignore OP_SUBMAKE as too aggressive + +2020-06-19 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200619 + Merge with NetBSD make, pick up + o str.c: performance improvement for Str_Match for multiple '*' + o dieQuietly: supress the failure output from make + when failing node is a sub-make or a sibling failed. + This cuts down greatly on unhelpful noise at the end of + build log. Disabled by -dj or .MAKE.DIE_QUIETLY=no + +2020-06-10 Simon J Gerraty + + * FILES: add LICENSE to appease some packagers. + This is an attempt to fairly represent the license on almost + 200 files, which are almost all BSD-3-Clause + The few exceptions being more liberal. + + * VERSION (_MAKE_VERSION): 20200610 + Merge with NetBSD make, pick up + o unit test for :Or + +2020-06-06 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200606 + Merge with NetBSD make, pick up + o make.1: cleanup + + * Makefile: fix depends for main.o which broke MAKE_VERSION + +2020-06-05 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200605 + Merge with NetBSD make, pick up + o dir.c: cached_stats - don't confuse stat and lstat results. + o var.c: add :Or for reverse sort. + +2020-05-24 Simon J Gerraty + + * configure.in: add AC_PROG_CC_C99 for mipspro compiler + also if --with-filemon= specifies path to filemon.h + set use_filemon=dev + * dirname.c: remove include of namespace.h + +2020-05-17 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200517 + Merge with NetBSD make, pick up + o modified dollar tests to avoid shell dependencies + o new tests for .INCLUDEFROM + +2020-05-16 Simon J Gerraty + + * unit-tests/dollar.mk: tweak '1 dollar literal' test + to not depend so much on shell behavior + +2020-05-10 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200510 + Merge with NetBSD make, pick up + o unit test for dollar handling + +2020-05-06 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200506 + Merge with NetBSD make, pick up + o str.c: empty string does not match % pattern + plus unit-test changes + +2020-05-04 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200504 + May the 4th be with you + Merge with NetBSD make, pick up + o var.c: import handling of old sysV style modifier using '%' + o str.c: refactor brk_string + o unit-tests: add test case for lazy conditions + +2020-04-18 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200418 + + * configure.in: use_makefile=no for cygwin et al. + case insensitive filesystems just don't work if both + makefile and Makefile exist. + NOTE: bmake does not support cygwin and likely never will, + but if brave souls want to try it - help them out. + +2020-04-02 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200402 + Merge with NetBSD make, pick up + o meta.c: meta_oodate, CHECK_VALID_META is too aggressive for CMD + a blank command is perfectly valid. + +2020-03-30 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200330 + Merge with NetBSD make, pick up + o make.h: extern debug_file + +2020-03-18 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200318 + Merge with NetBSD make, pick up + o meta.c: meta_oodate, check for corrupted meta file + earlier and more often. + +2020-02-20 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200220 + +2020-02-19 Simon J Gerraty + + * boot-strap: unset MAKEFLAGS + +2020-02-12 Simon J Gerraty + + * VERSION (_MAKE_VERSION): 20200212 + * meta.c: meta_compat_parent check for USE_FILEMON + patch from Soeren Tempel + +2020-02-05 Simon J Gerraty + + * VERSION: 20200205 + Merge with NetBSD make, pick up + o meta.c: fix compat mode, need to call meta_job_output() + o job.c: extra fds for meta mode not needed if using filemon_dev + +2020-01-22 Simon J Gerraty + + * VERSION: 20200122 + Merge with NetBSD make, pick up + o meta.c: avoid passing NULL to filemon_*() when meta_needed() + returns FALSE. + +2020-01-21 Simon J Gerraty + + * VERSION: 20200121 + Merge with NetBSD make, pick up + o filemon/filemon_{dev,ktrace}.c: allow selection of + filemon implementation. filemon_dev.c uses the kernel module + while filemon_ktrace.c leverages the fktrace api available in + NetBSD. filemon_ktrace.c can hopefully form the basis for + adding support for other tracing mechanisms such as strace on + Linux. + o meta.c: when target is out-of-date per normal make rules + record value of .OODATE in meta file. + +2019-09-26 Simon J Gerraty + + * VERSION: 20190926 + Merge with NetBSD make, pick up + o parse.c: don't pass NULL to realpath(3) + some versions cannot handle it. + +2019-04-09 Simon J Gerraty + + * VERSION: 20190409 + Merge with NetBSD make, pick up + o parse.c: ParseDoDependency: free paths rather than assert + +2018-12-22 Simon J Gerraty + + * VERSION: 20181222 + + * configure.in: add --without-makefile to avoid generating + makefile and make-bootstrap.sh + + * include Makefile.inc if it exists + + * Use Makefile and Makefile.config.in in unit-tests + so we can use just: make obj && make && make test + when bmake is already available. + We add --without-makefile to CONFIGURE_ARGS in this case. + + * tweak bsd.after-import.mk (captures Makefile.config etc + after import to FreeBSD for example) to cope with all the above. + +2018-12-21 Simon J Gerraty + + * VERSION: 20181221 + Merge with NetBSD make, pick up + o parse.c: ParseVErrorInternal use .PARSEDIR + and apply if relative, and then use .PARSEFILE + for consistent result. + +2018-12-20 Simon J Gerraty + + * VERSION: 20181220 + Merge with NetBSD make, pick up + o parse.c: ParseVErrorInternal use .CURDIR if .PARSEDIR + is relative + o var.c: avoid SEGFAULT in .unexport-env + when MAKELEVEL is not set + +2018-12-16 Simon J Gerraty + + * VERSION: 20181216 + Merge with NetBSD make, pick up + o fix for unit-tests/varquote.mk on Debian + +2018-09-21 Simon J. Gerraty + + * VERSION: 20180919 + Merge with NetBSD make, pick up + o var.c: add :q + o dir.c: cleanup caching of stats + +2018-09-21 Simon J Gerraty + + * Makefile.config.in: use += where it makes sense. + +2018-05-12 Simon J. Gerraty + + * VERSION: 20180512 + Merge with NetBSD make, pick up + o job.c: skip polling job token pipe + +2018-04-05 Simon J. Gerraty + + * VERSION: 20180405 + Merge with NetBSD make, pick up + o parse.c: be more cautious about detecting depenency line + rather than sysV style include. + +2018-02-22 Simon J. Gerraty + + * VERSION: 20180222 + Merge with NetBSD make, pick up + o parse.c: avoid calling sysconf for every call to loadfile + +2018-02-18 Simon J. Gerraty + + * VERSION: 20180218 + Merge with NetBSD make, pick up + o var.c: Var_Set handle NULL value anytime. + +2018-02-12 Simon J. Gerraty + + * VERSION: 20180212 + Merge with NetBSD make, pick up + o parse.c: do not treat .info as warning with -W + +2017-12-07 Simon J. Gerraty + + * VERSION: 20171207 + Merge with NetBSD make, pick up + o var.c: Var_Append use Var_Set if var not previously set + so that VAR_CMD is handled correctly. + Add a suitable unit-test. + +2017-11-26 Simon J. Gerraty + + * VERSION (_MAKE_VERSION): 20171126 + + * aclocal.m4: use AC_LINK_IFELSE for AC_C___ATTRIBUTE__ + since AC_TRY_COMPILE puts input inside main() + which upsets modern compilers. + +2017-11-18 Simon J. Gerraty + + * VERSION: 20171118 + Merge with NetBSD make, pick up + o var.c: do not append to variable set on command line + add unit-test to catch this. + +2017-10-28 Simon J. Gerraty + + * VERSION: 20171028 + Merge with NetBSD make, pick up + o main.c: ignore empty MAKEOBJDIR + + * Makefile.config.in: + make @prefix@ @machine*@ and @default_sys_path@ defaults. + +2017-10-05 Simon J. Gerraty + + * VERSION: 20171005 + + * unit-tests/dotwait.mk: redirect stderr through pipe for more + consistent result on some platforms. + +2017-08-13 Simon J. Gerraty + + * machine.sh: entry for AIX + +2017-08-12 Simon J. Gerraty + + * VERSION (_MAKE_VERSION): Move the setting of _MAKE_VERSION + to a file that can be included by configure as well as make. + This allows configure to set set _MAKE_VERSION in make-bootstrap.sh + +2017-08-10 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170810 + Merge with NetBSD make, pick up + o meta.c: if target is in subdir we only need subdir name in + meta_name. + +2017-07-20 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170720 + Merge with NetBSD make, pick up + o compat.c: pass SIGINT etc onto child and wait for it to exit + before we self-terminate. + +2017-07-11 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170711 + forgot to update after merge on 20170708 ;-) + o main.c: refactor to reduce size of main function. + add -v option to always fully expand values. + o meta.c: ensure command output in meta file has ending newline + even when filemon not being used. + When matching ${.MAKE.META.IGNORE_PATTERNS} do not use + pathname via ':L' since any ':' in pathname breaks that. + Instead set a '${.p.}' to pathname in the target context and + use that. + +2017-05-10 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170510 + Merge with NetBSD make, pick up + o main.c: Main_SetObjdir: ensure buf2 is in scope + +2017-05-08 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170505 + see mk/ChangeLog + +2017-05-05 Simon J. Gerraty + + * parse.c: not everyone has stdint.h + +2017-05-01 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170501 + see mk/ChangeLog + +2017-04-21 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170421 + Merge with NetBSD make, pick up + o str.c: Str_Match: fix closure tests for [^] and add unit-test. + +2017-04-20 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170420 + Merge with NetBSD make, pick up + o main.c: only use -C arg "as is" if it contains no + relative component. + +2017-04-18 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170418 + Merge with NetBSD make, pick up + o main.c: fix Main_SetObjdir() for relative paths (eg obj). + +2017-04-17 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170417 + Merge with NetBSD make, pick up + o fixes a number of coverity complaints + - check return value of fseek, fcntl + - plug memory leak in Dir_FindFile, Var_LoopExpand, + JobPrintCommand, ParseTraditionalInclude + - use bmake_malloc() where NULL is not tollerated + - use MAKE_ATTR_UNUSED rather that kludges like + return(unused ? 0 : 0) + - use purge_cached_realpaths() rather than abuse cached_realpath() + +2017-04-13 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170413 + Merge with NetBSD make, pick up + o main.c: when setting .OBJDIR ignore '$' in paths. + + * job.c: use MALLOC_OPTIONS to set malloc_options. + +2017-04-11 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170411 + Merge with NetBSD make, pick up + o str.c: Str_Match: allow [^a-z] to behave as expected. + +2017-03-26 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170326 + Merge with NetBSD make, pick up + o main.c: purge relative paths from realpath cache when .OBJDIR + is changed. + +2017-03-11 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170311 + Merge with NetBSD make, pick up + o main.c: only use -C arg "as is" if it starts with '/'. + +2017-03-01 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170301 + Merge with NetBSD make, pick up + o main.c: use -C arg "as is" rather than getcwd() + if they identify the same directory. + o parse.c: ensure loadfile buffer is \n terminated in non-mmap case + +2017-02-01 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170201 + Merge with NetBSD make, pick up + o var.c: allow :_=var and avoid use of special context. + +2017-01-30 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170130 + Merge with NetBSD make, pick up + o var.c: add :range and :_ + o main.c: partially initialize Dir_* before MainParseArgs() + can be called. + If -V, skip Main_ExportMAKEFLAGS() + +2017-01-14 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20170114 + Merge with NetBSD make, pick up + o var.c: allow specifying the utc value used by :{gm,local}time + +2016-12-12 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20161212 + Merge with NetBSD make, pick up + o main.c: look for obj.${MACHINE}-${MACHINE_ARCH} too. + +2016-12-09 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20161209 + Merge with NetBSD make, pick up + o main.c: cleanup setting of .OBJDIR + o parse.c: avoid coredump from (var)=val + +2016-11-26 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20161126 + Merge with NetBSD make, pick up + o make.c: Make_OODate: report src node name if path not set + +2016-09-26 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160926 + Merge with NetBSD make, pick up + o support for .DELETE_ON_ERROR: (remove targets that fail) + +2016-09-26 Simon J. Gerraty + + * Makefile MAN: tweak .Dt to match ${PROG} + +2016-08-18 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160818 + its a neater number; pick up whitespace fixes to man page. + +2016-08-17 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160817 + Merge with NetBSD make, pick up + o meta.c: move handling of .MAKE.META.IGNORE_* to meta_ignore() + so we can call it before adding entries to missingFiles. + Thus we do not track files we have been told to ignore. + +2016-08-15 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160815 + Merge with NetBSD make, pick up + o meta_oodate: apply .MAKE.META.IGNORE_FILTER (if defined) to + pathnames, and skip if the expansion is empty. + Useful for dirdeps.mk when checking DIRDEPS_CACHE. + +2016-08-12 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160812 + Merge with NetBSD make, pick up + o meta.c: remove all missingFiles entries that match a deleted + dir. + o main.c: set .ERROR_CMD if possible. + +2016-06-06 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160606 + Merge with NetBSD make, pick up + o dir.c: extend mtimes cache to others via cached_stat() + +2016-06-04 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160604 + Merge with NetBSD make, pick up + o meta.c: missing filemon data is only relevant if we read a + meta file. + Also do not return oodate for a missing metafile if gn->path + points to .CURDIR + +2016-06-02 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160602 + Merge with NetBSD make, pick up + o cached_realpath(): avoid hitting filesystem more than necessary. + o meta.c: refactor need_meta decision, add knobs for + missing meta file and filemon data wrt out-of-datedness. + +2016-05-28 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160528 + + * boot-strap, make-bootstrap.sh.in: Makefile now uses _MAKE_VERSION + +2016-05-12 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160512 + Merge with NetBSD make, pick up + o meta.c: ignore paths that match .MAKE.META.IGNORE_PATTERNS + this is useful for gcov builds. + o propagate errors from filemon(4). + +2016-05-09 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160509 + Merge with NetBSD make, pick up + o remove use of non-standard types u_int etc. + o meta.c: apply realpath() before matching against metaIgnorePaths + +2016-04-04 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160404 + Merge with NetBSD make, pick up + o allow makefile to set .MAKE.JOBS + + * Makefile (PROG_NAME): use ${_MAKE_VERSION} + +2016-03-15 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): 20160315 + Merge with NetBSD make, pick up + o fix handling of archive members + +2016-03-13 Simon J. Gerraty + + * Makefile (_MAKE_VERSION): rename variable to avoid interference + with checks for ${MAKE_VERSION} + +2016-03-10 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20160310 + Merge with NetBSD make, pick up + o meta.c: treat missing Read file same as Write, incase we Delete it. + +2016-03-07 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20160307 + Merge with NetBSD make, pick up + o var.c: fix :ts\nnn to be octal by default. + o meta.c: meta_finish() to cleanup memory. + +2016-02-26 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20160226 + Merge with NetBSD make, pick up + o meta.c: allow meta file for makeDepend if makefiles want it. + +2016-02-19 Simon J. Gerraty + + * var.c: default .MAKE.SAVE_DOLLARS to FALSE + for backwards compatability. + + * Makefile (MAKE_VERSION): 20160220 + Merge with NetBSD make, pick up + o var.c: add knob to control handling of '$$' in := + +2016-02-18 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20160218 + Merge with NetBSD make, pick up + o var.c: add .export-literal allows us to fix sys.clean-env.mk + post the changes to Var_Subst. + Var_Subst now takes flags, and does not consume '$$' in := + +2016-02-17 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20160217 + Merge with NetBSD make, pick up + o var.c: preserve '$$' in := + o parse.c: add .dinclude for handling included + makefile like .depend + +2015-12-20 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151220 + Merge with NetBSD make, pick up + o suff.c: re-initialize suffNull when clearing suffixes. + +2015-12-01 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151201 + Merge with NetBSD make, pick up + o cond.c: CondCvtArg: avoid access beyond end of empty buffer. + o meta.c: meta_oodate: use lstat(2) for checking link target + in case it is a symlink. + o var.c: avoid calling brk_string and Var_Export1 with empty + strings. + +2015-11-26 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151126 + Merge with NetBSD make, pick up + o parse.c: ParseTrackInput don't access beyond + end of old value. + +2015-10-22 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151022 + + * Add support for BSD/OS which lacks inttypes.h + and really needs sys/param.h for sys/sysctl.h + also 'type' is not a shell builtin. + + * var.c: eliminate uint32_t and need for inttypes.h + + * main.c: PrintOnError flush stdout before run .ERROR + + * parse.c: cope with _SC_PAGESIZE not being defined. + + +2015-10-20 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151020 + Merge with NetBSD make, pick up + o var.c: fix uninitialized var + +2015-10-12 Simon J. Gerraty + + * var.c: the conditional expressions used with ':?' can be + expensive, if already discarding do not evaluate or expand + anything. + +2015-10-10 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151010 + Merge with NetBSD make, pick up + o Add Boolean wantit flag to Var_Subst and Var_Parse + when FALSE we know we are discarding the result and can + skip operations like Cmd_Exec. + +2015-10-09 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20151009 + Merge with NetBSD make, pick up + o var.c: don't check for NULL before free() + o meta.c: meta_oodate, do not hard code ignore of makeDependfile + +2015-09-10 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150910 + Merge with NetBSD make, pick up + o main.c: with -w print Enter/Leaving messages for objdir too + if necessary. + o centralize shell metachar handling + + * FILES: add metachar.[ch] + +2015-06-06 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150606 + Merge with NetBSD make, pick up + o make.1: document .OBJDIR target + +2015-05-05 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150505 + Merge with NetBSD make, pick up + o cond.c: be strict about lhs of comparison when evaluating .if + but less so when called from variable expansion. + o unit-tests/cond2.mk: test various error conditions + +2015-05-04 Simon J. Gerraty + + * machine.sh (MACHINE): Add Bitrig + patch from joerg@netbsd.org + +2015-04-18 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150418 + Merge with NetBSD make, pick up + o job.c: use memmove() rather than memcpy() + + * unit-tests/varshell.mk: SunOS cannot handle the TERMINATED_BY_SIGNAL + case, so skip it. + +2015-04-11 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150411 + bump version - only mk/ changes. + +2015-04-10 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150410 + Merge with NetBSD make, pick up + o document different handling of '-' in jobs mode vs compat + o fix jobs mode so that '-' only applies to whole job + when shell lacks hasErrCtl + o meta.c: use separate vars to track lcwd and latestdir (read) + per process + +2015-04-01 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20150401 + Merge with NetBSD make, pick up + o meta.c: close meta file in child + + * Makefile: use BINDIR.bmake if set. + Same for MANDIR and SHAREDIR + Handy for testing release candidates + in various environments. + +2015-03-26 Simon J. Gerraty + + * move initialization of savederr to block where it is used + to avoid spurious warning from gcc5 + +2014-11-11 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20141111 + just a cooler number + +2014-11-05 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20141105 + Merge with NetBSD make, pick up + o revert major overhaul of suffix handling + and POSIX compliance - too much breakage + and impossible to make backwards compatible. + o we still have the new unit test structure which is ok. + o meta.c ensure "-- filemon" is at start of line. + +2014-09-17 Simon J. Gerraty + + * configure.in: test that result of getconf PATH_MAX is numeric + and discard if not. Apparently needed for Hurd. + +2014-08-30 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140830 + Merge with NetBSD make, pick up + o major overhaul of suffix handling + o improved POSIX compliance + o overhauled unit-tests + +2014-06-20 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140620 + Merge with NetBSD make, pick up + o var.c return varNoError rather than var_Error for ::= modifiers. + +2014-05-22 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140522 + Merge with NetBSD make, pick up + o var.c detect some parse errors. + +2014-04-05 Simon J. Gerraty + + * Fix spelling errors - patch from Pedro Giffuni + +2014-02-14 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140214 + Merge with NetBSD make, pick up + o .INCLUDEFROM* + o use Var_Value to get MAKEOBJDIR[PREFIX] + o reduced realloc'ign in brk_string. + * configure.in: add a check for compiler supporting __func__ + +2014-01-03 Simon J. Gerraty + + * boot-strap: ignore mksrc=none + +2014-01-02 Simon J. Gerraty + + * Makefile (DEFAULT_SYS_PATH?): use just ${prefix}/share/mk + +2014-01-01 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20140101 + * configure.in: set bmake_path_max to min(_SC_PATH_MAX,1024) + * Makefile.config: defined BMAKE_PATH_MAX to bmake_path_max + * make.h: use BMAKE_PATH_MAX if MAXPATHLEN not defined (needed for + Hurd) + * configure.in: Add AC_PREREQ and check for + sysctl; patch from Andrew Shadura andrewsh at debian.org + +2013-10-16 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20131010 + * lose the const from arg to systcl to avoid problems on older BSDs. + +2013-10-01 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20131001 + Merge with NetBSD make, pick up + o main.c: for NATIVE build sysctl to get MACHINE_ARCH from + hw.machine_arch if necessary. + o meta.c: meta_oodate - need to look at src of Link and target + of Move as well. + * main.c: check that CTL_HW and HW_MACHINE_ARCH exist. + provide __arraycount() if needed. + +2013-09-04 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130904 + Merge with NetBSD make, pick up + o Add VAR_INTERNAL context, so that internal setting of + MAKEFILE does not override value set by makefiles. + +2013-09-02 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130902 + Merge with NetBSD make, pick up + o CompatRunCommand: only apply shellErrFlag when errCheck is true + +2013-08-28 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130828 + Merge with NetBSD make, pick up + o Fix VAR :sh = syntax from Will Andrews at freebsd.org + o Call Job_SetPrefix() from Job_Init() so makefiles have + opportunity to set .MAKE.JOB.PREFIX + +2013-07-30 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130730 + Merge with NetBSD make, pick up + o Allow suppression of --- job -- tokens by setting + .MAKE.JOB.PREFIX empty. + +2013-07-16 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130716 + Merge with NetBSD make, pick up + o number of gmake compatibility tweaks + -w for gmake style entering/leaving messages + if .MAKE.LEVEL > 0 indicate it in progname "make[1]" etc. + handle MAKEFLAGS containing only letters. + o when overriding a GLOBAL variable on the command line, + delete it from GLOBAL context so -V doesn't show the wrong + value. + +2013-07-06 Simon J. Gerraty + + * configure.in: We don't need MAKE_LEVEL_SAFE anymore. + + * Makefile (MAKE_VERSION): 20130706 + Merge with NetBSD make, pick up + o Shell_Init(): export shellErrFlag if commandShell hasErrCtl is + true so that CompatRunCommand() can use it, to ensure + consistent behavior with jobs mode. + o use MAKE_LEVEL_ENV to define the variable to propagate + .MAKE.LEVEL - currently set to MAKELEVEL (same as gmake). + o meta.c: use .MAKE.META.IGNORE_PATHS to allow customization of + paths to ignore. + +2013-06-04 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130604 + Merge with NetBSD make, pick up + o job.c: JobCreatePipe: do fcntl() after any tweaking of fd's + to avoid leaking descriptors. + +2013-05-28 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130528 + Merge with NetBSD make, pick up + o var.c: cleanup some left-overs in VarHash() + +2013-05-20 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130520 + generate manifest from component FILES rather than have to + update FILES when mk/FILES changes. + +2013-05-18 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130518 + Merge with NetBSD make, pick up + o suff.c: don't skip all processsing for .PHONY targets + else wildcard srcs do not get expanded. + o var.c: expand name of variable to delete if necessary. + +2013-03-30 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130330 + Merge with NetBSD make, pick up + o meta.c: refine the handling of .OODATE in commands. + Rather than suppress command comparison for the entire script + as though .NOMETA_CMP had been used, only suppress it for the + one command line. + This allows something like ${.OODATE:M.NOMETA_CMP} to be used to + suppress comparison of a command without otherwise affecting it. + o make.1: document that + +2013-03-22 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130321 + yes, not quite right but its a cooler number. + Merge with NetBSD make, pick up + o parse.c: fix ParseGmakeExport to be portable + and add a unit-test. + * meta.c: call meta_init() before makefiles are read and if built + with filemon support set .MAKE.PATH_FILEMON to _PATH_FILEMON + this let's makefiles test for support. + Call meta_mode_init() to process .MAKE.MODE. + +2013-03-13 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130305 + Merge with NetBSD make, pick up + o run .STALE: target when a dependency from .depend is missing. + o job.c: add Job_RunTarget() for the above and .BEGIN + +2013-03-03 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130303 + Merge with NetBSD make, pick up + o main.c: set .MAKE.OS to utsname.sysname + o job.c: more checks for read and poll errors + o var.c: lose VarChangeCase() saves 4% time + +2013-03-02 Simon J. Gerraty + + * boot-strap: remove MAKEOBJDIRPREFIX from environment since we + want to use MAKEOBJDIR + +2013-01-27 Simon J. Gerraty + + * Merge with NetBSD make, pick up + o make.1: more info on how shell commands are handled. + o job.c,main.c: detect write errors to job pipes. + +2013-01-25 Simon J. Gerraty + + * Makefile (MAKE_VERSION): 20130123 + Merge with NetBSD make, pick up + o meta.c: if script uses .OODATE and meta_oodate() decides + rebuild is needed, .OODATE will be empty - set it to .ALLSRC. + o var.c: in debug output indicate which variabale modifiers + apply to. + o remove Check_Cwd logic the makefiles have been fixed. + +2012-12-12 Simon J. Gerraty + + * makefile.in: add a simple makefile for folk who insist on + ./configure; make; make install + it just runs boot-strap + * include mk/* to accommodate the above + * boot-strap: re-work to accommodate the above + mksrc defaults to $Mydir/mk + allow op={configure,build,install,clean,all} + add options to facilitate install + * Makefile.config.in: just the bits set by configure + * Makefile: bump version to 20121212 + abandon Makefile.in (NetBSD Makefile) + leverage mk/* instead + * configure.in: ensure srcdir is absolute + +2012-11-11 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20121111 + fix generation of bmake.cat1 + +2012-11-09 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20121109 + Merge with NetBSD make, pick up + o make.c: MakeBuildChild: return 0 so search continues if a + .ORDER dependency is detected. + o unit-tests/order: test the above + +2012-11-02 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20121102 + Merge with NetBSD make, pick up + o cond.c: allow cond_state[] to grow. + In meta mode with a very large tree, we can hit the limit + while processing dirdeps. + +2012-10-25 Simon J. Gerraty + + * Makefile.in: we need to use ${srcdir} not ${.CURDIR} + +2012-10-10 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20121010 + o protect syntax that only bmake parses correctly. + o remove auto setting of FORCE_MACHINE, use configure's + --with-force-machine=whatever if that is desired. + +2012-10-08 Simon J. Gerraty + + * Makefile.in: do not lose history from make.1 when generating bmake.1 + +2012-10-07 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20121007 + Merge with NetBSD make, pick up + o compat.c: ignore empty commands - same as jobs mode. + o make.1: document meta chars that cause use of shell + +2012-09-11 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120911 + * bsd.after-import.mk: include Makefile.inc early and allow it to + override PROG + +2012-08-31 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120831 + Merge with NetBSD make, pick up + o cast sizeof() to int for comparison + o minor make.1 tweak + +2012-08-30 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120830 + Merge with NetBSD make, pick up + o .MAKE.EXPAND_VARIABLES knob can control default behavior of -V + o debug flag -dV causes -V to show raw value regardless. + +2012-07-05 Simon J. Gerraty + + * bsd.after-import.mk (after-import): ensure unit-tests/Makefile + gets SRCTOP set. + +2012-07-04 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120704 + Merge with NetBSD make, pick up + o Job_ParseShell should call Shell_Init if it has been + previously called. + * Makefile.in: set USE_META based on configure result. + also .PARSEDIR is safer indicator of bmake. + +2012-06-26 Simon J. Gerraty + + * Makefile.in: bump version to 20120626 + ensure CPPFLAGS is in CFLAGS + * meta.c: avoid nested externs + * bsd.after-import.mk: avoid ${.CURDIR}/Makefile as target + +2012-06-20 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120620 + Merge with NetBSD make, pick up + o make_malloc.c: avoid including make_malloc.h again + + * Makefile.in: avoid bmake only syntax or protect with + .if defined(.MAKE.LEVEL) + * bsd.after-import.mk: replace .-include with .sinclude + ensure? SRCTOP gets a value + * configure.in: look for filemon.h in /usr/include/dev/filemon first. + +2012-06-19 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120612 + Merge with NetBSD make, pick up + o use MAKE_ATTR_* rather than those defined by cdefs.h or compiler + for greater portability. + o unit-tests/forloop: check that .for works as expected wrt + number of times and with "quoted strings". + +2012-06-06 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120606 + Merge with NetBSD make, pick up + o compat.c: use kill(2) rather than raise(3). + * configure.in: look for sys/dev/filemon + * bsd.after-import.mk: add a .-include "Makefile.inc" to Makefile + and pass BOOTSTRAP_XTRAS to boot-strap. + +2012-06-04 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120604 + Merge with NetBSD make, pick up + o util.c and var.c share same var for tracking if environ + has been reallocated. + o util.c provide getenv with setenv. + * Add MAKE_LEVEL_SAFE as an alternate means of passing MAKE_LEVEL + when the shell actively strips .MAKE.* from the environment. + We still refer to the variable always as .MAKE.LEVEL + * util.c fix bug in findenv() was finding prefix of name. + * compat.c: re-raising SIGINT etc after running .INTERRUPT + results in more reliable termination of all activity on many + platforms. + +2012-06-02 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120602 + Merge with NetBSD make, pick up + o for.c: handle quoted items in .for list + +2012-05-30 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120530 + Merge with NetBSD make, pick up + o compat.c: ignore empty command. + +2012-05-24 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120524 + * FILES: add bsd.after-import.mk: + A simple means of integrating bmake into a BSD build system. + +2012-05-20 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120520 + Merge with NetBSD make, pick up + o increased limit for nested conditionals. + +2012-05-18 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120518 + Merge with NetBSD make, pick up + o use _exit(2) in signal hanlder + o Don't use the [dir] cache when building nodes that might have + changed since the last exec. + o Avoid nested extern declaration warnings. + +2012-04-27 Simon J. Gerraty + + * meta.c (fgetLine): avoid %z - not portable. + * parse.c: Since we moved include of sys/mman.h + and def's of MAP_COPY etc. we got dups from a merge. + +2012-04-24 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120420 + Merge with NetBSD make, pick up + o restore duplicate supression in .MAKE.MAKEFILES + runtime saving can be significant. + o Var_Subst() uses Buf_DestroyCompact() to reduce memory + consumption up to 20%. + +2012-04-20 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120420 + Merge with NetBSD make, pick up + o remove duplicate supression in .MAKE.MAKEFILES + o improved dir cache behavior + o gmake'ish export command + +2012-03-25 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20120325 + Merge with NetBSD make, pick up + o fix parsing of :[#] in conditionals. + +2012-02-10 Simon J. Gerraty + + * Makefile.in: replace use of .Nx in bmake.1 with NetBSD + since some systems cannot cope with .Nx + +2011-11-14 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20111111 + Merge with NetBSD make, pick up + o debug output for .PARSEDIR and .PARSEFILE + +2011-10-10 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20111010 + +2011-10-09 Simon J. Gerraty + + * boot-strap: check for an expected file in the dirs we look for. + * make-bootstrap.sh: pass on LDSTATIC + +2011-10-01 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20111001 + Merge with NetBSD make, pick up + o ensure .PREFIX is set for .PHONY + and .TARGET set for .PHONY run via .END + o __dead used consistently + +2011-09-10 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): 20110909 is a better number ;-) + +2011-09-05 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110905 + Merge with NetBSD make, pick up + o meta_oodate: ignore makeDependfile + +2011-08-28 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110828 + Merge with NetBSD make, pick up + o silent=yes in .MAKE.MODE causes meta mode to mark targets + as SILENT if a .meta file is created + +2011-08-18 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110818 + Merge with NetBSD make, pick up + o in meta mode, if target flagged .META a missing .meta file + means target is out-of-date + o fixes for gcc 4.5 warnings + o simplify job printing code + +2011-08-09 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110808 + Merge with NetBSD make, pick up + o do not touch OP_SPECIAL targets when doing make -t + +2011-06-22 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110622 + Merge with NetBSD make, pick up + o meta_oodate detect corrupted .meta file and declare oodate. + * configure.in: add check for setsid + +2011-06-07 Simon J. Gerraty + + * Merge with NetBSD make, pick up + o unit-tests/modts now works on MirBSD + +2011-06-04 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110606 + Merge with NetBSD make, pick up + o ApplyModifiers: when we parse a variable which is not + the entire modifier string, or not followed by ':', do not + consider it as containing modifiers. + o loadfile: ensure newline at end of mapped file. + +2011-05-05 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110505 + Merge with NetBSD make, pick up + o .MAKE.META.BAILIWICK - list of prefixes which define the scope + of make's control. In meta mode, any generated file within + said bailiwick, which is found to be missing, causes current + target to be out-of-date. + +2011-04-11 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110411 + Merge with NetBSD make, pick up + o when long modifiers fail to match, check sysV style. + - add a test case + +2011-04-10 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110410 + Merge with NetBSD make, pick up + o :hash - cheap 32bit hash of value + o :localtime, :gmtime - use value as format string for strftime. + +2011-03-30 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110330 + mostly because its a cooler version. + Merge with NetBSD make, pick up + o NetBSD tags for meta.[ch] + o job.c call meta_job_finish() after meta_job_error(). + o meta_job_error() should call meta_job_finish() to ensure + .meta file is closed, and safe to copy - if .ERROR target wants. + meta_job_finish() is safe to call repeatedly. + +2011-03-29 Simon J. Gerraty + + * unit-tests/modts: use printf if it is a builtin, + to save us from MirBSD + + * Makefile.in (MAKE_VERSION): bump version to 20110329 + Merge with NetBSD make, pick up + o fix for use after free() in CondDoExists(). + o meta_oodate() report extra commands and return earlier. + +2011-03-27 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110327 + Merge with NetBSD make, pick up + o meta.c, if .MAKE.MODE contains curdirOk=yes + allow creating .meta files in .CURDIR + * boot-strap (TOOL_DIFF): aparently at least on linux distro + formats the output of 'type' differently - so eat any "()" + +2011-03-06 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110306 + Merge with NetBSD make, pick up + o meta.c, only do getcwd() once + +2011-03-05 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110305 + Merge with NetBSD make, pick up + o correct sysV substitution handling of empty lhs and variable + o correct exists() check for dir with trailing / + o correct handling of modifiers for non-existant variables + during evaluation of conditionals. + o ensure MAP_FILE is defined. + o meta.c use curdir[] now exported by main.c + +2011-02-25 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110225 + Merge with NetBSD make, pick up + o fix for incorrect .PARSEDIR when .OBJDIR is re-computed after + makefiles have been read. + o fix example of :? modifier in man page. + +2011-02-13 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110214 + Merge with NetBSD make, pick up + o meta.c handle realpath() failing when generating meta file + name. + + * sigcompat.c: convert to ansi so we can use higher warning levels. + + +2011-02-07 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110207 + Merge with NetBSD make, pick up + o fix for bug in meta mode. + +2011-01-03 Simon J. Gerraty + + * parse.c: SunOS 5.8 at least does not have MAP_FILE + +2011-01-01 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20110101 + Merge with NetBSD make, pick up + o use mmap(2) if available, for reading makefiles + +2010-12-15 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20101215 + Merge with NetBSD make, pick up + o ensure meta_job_error() does not report a previous .meta file + as being culprit. + +2010-12-10 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20101210 + Merge with NetBSD make, pick up + o meta_oodate: track cwd per process, and only consider target + out-of-date if missing file is outside make's CWD. + Ignore files in /tmp/ etc. + o to ensure unit-tests results match, need to control LC_ALL + as well as LANG. + o fix for parsing bug in var.c + +2010-11-26 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20101126 + Merge with NetBSD make, pick up + o if stale dependency is an IMPSRC, search via .PATH + o meta_oodate: if a referenced file is missing, target is + out-of-date. + o meta_oodate: if a target uses .OODATE in its commands, + it (.OODATE) needs to be recomputed. + o keep a pointer to youngest child node, rather than just its + mtime. + +2010-11-02 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20101101 + +2010-10-16 Simon J. Gerraty + + * machine.sh: like os.sh, + allow for uname -p producing useless drivel + +2010-09-13 Simon J. Gerraty + + * boot-strap: document configure knobs for meta and filemon. + + * Makefile.in (MAKE_VERSION): bump version to 20100911 + Merge with NetBSD make, pick up + o meta.c - meta mode + + * make-bootstrap.sh.in: handle meta.c + * configure.in: add knobs for use_meta and filemon_h + also, look for dirname, str[e]sep and strlcpy + * util.c: add simple err[x] and warn[x] + +2010-08-08 Simon J. Gerraty + + * boot-strap (TOOL_DIFF): set this to ensure tests use + the same version of diff that configure tested + + * Makefile.in (MAKE_VERSION): bump version to 20100808 + Merge with NetBSD make, pick up + o in jobs mode, when we discover we cannot make something, + call PrintOnError before exit. + +2010-08-06 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100806 + Merge with NetBSD make, pick up + o formatting fixes for ignored errors + o ensure jobs are cleaned up regardless of where wait() was called. + +2010-06-28 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100618 + * os.sh (MACHINE_ARCH): watch out for drivel from uname -p + +2010-06-16 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100616 + Merge with NetBSD make, pick up + o man page update + o call PrintOnError from JobFinish when we detect an error we + are not ignoring. + +2010-06-06 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100606 + Merge with NetBSD make, pick up + o man page update + +2010-06-05 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100605 + Merge with NetBSD make, pick up + o use bmake_signal() which is a wrapper around sigaction() + in place of signal() + o add .export-env to allow exporting variables to environment + without tracking (so no re-export when the internal value is + changed). + +2010-05-24 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100524 + Merge with NetBSD make, pick up + o fix for .info et al being greedy. + +2010-05-23 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100520 + Merge with NetBSD make, pick up + o back to using realpath on argv[0] + but only if contains '/' and does not start with '/'. + +2010-05-10 Simon J. Gerraty + + * boot-strap: use absolute path for bmake when running tests. + + * Makefile.in (MAKE_VERSION): bump version to 20100510 + Merge with NetBSD make, pick up + o revert use of realpath on argv[0] + too many corner cases. + o print MAKE_PRINT_VAR_ON_ERROR before running .ERROR target. + +2010-05-05 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100505 + Merge with NetBSD make, pick up + o fix for missed SIGCHLD when compiled with SunPRO + actually for bmake, defining FORCE_POSIX_SIGNALS would have + done the job. + +2010-04-30 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100430 + Merge with NetBSD make, pick up + o fflush stdout before writing to stdout + +2010-04-23 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100423 + Merge with NetBSD make, pick up + o updated unit tests for Haiku (this time for sure). + * boot-strap: based on patch from joerg + honor --with-default-sys-path better. + * boot-strap: remove mention of --with-prefix-sys-path + +2010-04-22 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100422 + * Merge with NetBSD make, pick up + o fix for vfork() on Darwin. + o fix for bogus $TMPDIR. + o set .MAKE.MODE=compat for -B + o set .MAKE.JOBS=max_jobs for -j max_jobs + o allow unit-tests to run without any *.mk + o unit-tests/modmisc be more conservative in dirs presumed to exist. + * boot-strap: ignore /usr/share/mk except on NetBSD. + * unit-tests/Makefile.in: set LANG=C when running unit-tests to + ensure sort(1) behaves as expected. + +2010-04-21 Simon J. Gerraty + + * boot-strap: add FindHereOrAbove so we can use -m .../mk + +2010-04-20 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100420 + * Merge with NetBSD make, pick up + o fix for variable realpath() behavior. + we have to stat(2) the result to be sure. + o fix for .export (all) when nested vars use :sh + +2010-04-14 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100414 + * Merge with NetBSD make, pick up + o use realpath to resolve argv[0] (for .MAKE) if needed. + o add realpath from libc. + o add :tA to resolve variable via realpath(3) if possible. + +2010-04-08 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100408 + * Merge with NetBSD make, pick up + o unit tests for .ERROR, .error + o fix for .ERROR to ensure it cannot be default target. + +2010-04-06 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100406 + * Merge with NetBSD make, pick up + o fix for compat mode "Error code" going to debug_file. + o fix for .ALLSRC being populated twice. + o support for .info, .warning and .error directives + o .MAKE.MODE to control make's operational mode + o .MAKE.MAKEFILE_PREFERENCE to control the preferred makefile + name(s). + o .MAKE.DEPENDFILE to control the name of the depend file + o .ERROR target - run on failure. + +2010-03-18 Simon J. Gerraty + + * make-bootstrap.sh.in: extract MAKE_VERSION from Makefile + + * os.sh,arch.c: patch for Haiku from joerg at netbsd + +2010-03-17 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100222 + * Merge with NetBSD make, pick up + o better error msg for .for with mutiple inter vars + + * boot-strap: + o use make-bootstrap.sh from joerg at netbsd + to avoid the need for a native make when bootstrapping. + o add "" everywhere ;-) + o if /usr/share/tmac/andoc.tmac exists install nroff bmake.1 + otherwise the pre-formated version. + +2010-01-04 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20100102 + * Merge with NetBSD make, pick up: + o fix for -m .../ + +2009-11-18 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20091118 + * Merge with NetBSD make, pick up: + o .unexport + o report lines that start with '.' and should have ':' + (catch typo's of .el*if). + +2009-10-30 Simon J. Gerraty + + * configure.in: Ensure that srcdir and mksrc are absolute paths. + +2009-10-09 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): fix version to 20091007 + +2009-10-07 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 200910007 + * Merge with NetBSD make, pick up: + o fix for parsing of :S;...;...; applied to .for loop iterator + appearing in a dependency line. + +2009-09-09 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20090909 + * Merge with NetBSD make, pick up: + o fix for -C, .CURDIR and .OBJDIR + * boot-strap: + o allow share_dir to be set independent of prefix. + o select default share_dir better when prefix ends in $HOST_TARGET + o if FORCE_BSD_MK etc were set, include them in the suggested + install-mk command. + +2009-09-08 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20090908 + * Merge with NetBSD make, pick up: + o .MAKE.LEVEL for recursion tracking + o fix for :M scanning \: + +2009-09-03 Simon J. Gerraty + + * configure.in: Don't -D__EXTENSIONS__ if + AC_USE_SYSTEM_EXTENSIONS says "no". + +2009-08-26 Simon J. Gerraty + + * Makefile.in (MAKE_VERSION): bump version to 20090826 + Simplify MAKE_VERSION to just the bare date. + * Merge with NetBSD make, pick up: + o -C directory support. + o support for SIGINFO + o use $TMPDIR for temp files. + o child of vfork should be careful about modifying parent's state. + + +2009-03-26 Simon J. Gerraty + + * Appy some patches for MiNT from David Brownlee + +2009-02-26 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20090222 + * Merge with NetBSD make, pick up: + o Possible null pointer de-ref in Var_Set. + +2009-02-08 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20090204 + * Merge with NetBSD make, pick up: + o bmake_malloc et al moved to their own .c + o Count both () and {} when looking for the end of a :M pattern + o Change 'Buffer' so that it is the actual struct, not a pointer to it. + o strlist.c - functions for processing extendable arrays of pointers to strings. + o ClientData replaced with void *, so const void * can be used. + o New debug flag C for DEBUG_CWD + +2008-11-11 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20081111 + Apply patch from Joerg Sonnenberge to + configure.in: + o remove some redundant checks + o check for emlloc etc only in libutil and require the whole family. + util.c: + o remove [v]asprintf which is no longer used. + +2008-11-04 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20081101 + * Merge with NetBSD make, pick up: + o util.c: avoid use of putenv() - christos + +2008-10-30 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20081030 + pick up man page tweaks. + +2008-10-29 Simon J. Gerraty + + * Makefile.in: move processing of LIBOBJS to after is definition! + thus we'll have getenv.c in SRCS only if needed. + + * make.1: add examples of how to use :? + + * Makefile.in (BMAKE_VERSION): bump version to 20081029 + * Merge with NetBSD make, pick up: + o fix for .END processing with -j + o segfault from Parse_Error when no makefile is open + o handle numeric expressions in any variable expansion + o debug output now defaults to stderr, -dF to change it - apb + o make now uses bmake_malloc etc so that it can build natively + on A/UX - wasn't an issue for bmake, but we want to keep in sync. + +2008-09-27 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20080808 + * Merge with NetBSD make, pick up: + o fix for PR/38840: Pierre Pronchery: make crashes while parsing + long lines in Makefiles + o optimizations for VarQuote by joerg + o fix for PR/38756: dominik: make dumps core on invalid makefile + +2008-05-15 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20080515 + * Merge with NetBSD make, pick up: + o fix skip setting vars in VAR_GLOBAL context, to handle + cases where VAR_CMD is used for other than command line vars. + +2008-05-14 Simon J. Gerraty + + * boot-strap (make_version): we may need to look in + $prefix/share/mk for sys.mk + + * Makefile.in (BMAKE_VERSION): bump version to 20080514 + * Merge with NetBSD make, pick up: + o skip setting vars in VAR_GLOBAL context, when already set in + VAR_CMD which takes precedence. + +2008-03-30 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20080330 + * Merge with NetBSD make, pick up: + o fix for ?= when LHS contains variable reference. + +2008-02-15 Simon J. Gerraty + + * merge some patches from NetBSD pkgsrc. + + * makefile.boot.in (BOOTSTRAP_SYS_PATH): Allow better control of + the MAKSYSPATH used during bootstrap. + + * Makefile.in (BMAKE_VERSION): bump version to 20080215 + * Merge with NetBSD make, pick up: + o warn if non-space chars follow 'empty' in a conditional. + +2008-01-18 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20080118 + * Merge with NetBSD make, pick up: + o consider dependencies read from .depend as optional - dsl + o remember when buffer for reading makefile grows - dsl + o add -dl (aka LOUD) - David O'Brien + +2007-10-22 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20071022 + * Merge with NetBSD make, pick up: + o Allow .PATH to be used for .include "" + + * boot-strap: source default settings from .bmake-boot-strap.rc + +2007-10-16 Simon J. Gerraty + + * Makefile.in: fix maninstall on various systems + provided that our man.mk is used. + For non-BSD systems we install the preformatted page + into $MANDIR/cat1 + +2007-10-15 Simon J. Gerraty + + * boot-strap: make bmake.1 too, so maninstall works. + +2007-10-14 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20071014 + * Merge with NetBSD make, pick up: + o revamped handling of defshell - configure no longer needs to + know the content of the shells array - apb + o stop Var_Subst modifying its input - apb + o avoid calling ParseTrackInput too often - dsl + +2007-10-11 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20071011 + * Merge with NetBSD make, pick up: + o fix Shell_Init for case that _BASENAME_DEFSHELL is absolute path. + + * sigcompat.c: some tweaks for HP-UX 11.x based on + patch from Tobias Nygren + + * configure.in: update handling of --with-defshell to match + new make behavior. --with-defshell=/usr/xpg4/bin/sh + will now do what one might hope - provided the chosen shell + behaves enough like sh. + +2007-10-08 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20071008 + * Merge with NetBSD make, pick up: + o .MAKE.JOB.PREFIX - control the token output before jobs - sjg + o .export/.MAKE.EXPORTED - export of variables - sjg + o .MAKE.MAKEFILES - track all makefiles read - sjg + o performance improvements - dsl + o revamp parallel job scheduling - dsl + +2006-07-28 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060728 + * Merge with NetBSD make, pick up: + o extra debug info during variable and cond processing - sjg + o shell definition now covers newline - rillig + o minor mem leak in PrintOnError - sjg + +2006-05-11 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060511 + * Merge with NetBSD make, pick up: + o more memory leaks - coverity + o possible overflow in ArchFindMember - coverity + o extract variable modifier code out of Var_Parse() + so it can be called recursively - sjg + o unit-tests/moderrs - sjg + +2006-04-12 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060412 + * Merge with NetBSD make, pick up: + o fixes for some memory leaks - coverity + o only read first sys.mk etc when searching sysIncPath - sjg + + * main.c (ReadMakefile): remove hack for __INTERIX that prevented + setting ${MAKEFILE} - OBATA Akio + +2006-03-18 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060318 + * Merge with NetBSD make, pick up: + o cleanup of job.c to remove remote handling, distcc is more + useful and this code was likely bit-rotting - dsl + o fix for :P modifier - sjg + * boot-strap: set default prefix to something reasonable + (for me anyway). + +2006-03-01 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060301 + * Merge with NetBSD make, pick up: + o make .WAIT apply recursively, document and test case - apb + o allow variable modifiers in a variable appear anywhere in + modifier list, document and test case - sjg + +2006-02-22 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20060222 + * Merge with NetBSD make, pick up: + o improved job token handling - dsl + o SIG_DFL the correct signal before exec - dsl + o more debug info during parsing - dsl + o allow variable modifiers to be specified via variable - sjg + * boot-strap: explain why we died if no mksrc + +2005-11-05 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20051105 + * configure.in: always set default_sys_path + default is ${prefix}/share/mk + - remove prefix_sys_path, anyone wanting more than above + needs to set it manually. + +2005-11-04 Simon J. Gerraty + + * boot-strap: make this a bit easier for pkgsrc folk. + bootstrap still fails on IRIX64 since MACHINE_ARCH gets set to + 'mips' while pkgsrc wants 'mipseb' or 'mipsel' + +2005-11-02 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20051102 + * job.c (JobFinish): fix likely ancient merge lossage + fix from Todd Vierling. + * boot-strap (srcdir): allow setting mksrc=none + +2005-10-31 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20051031 + * ranlib.h: skip on OSF too. + (NetBSD PR 31864) + +2005-10-10 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20051002 + fix a silly typo + +2005-10-09 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20051001 + support for UnixWare and some other systems, + based on patches from pkgsrc/bootstrap + +2005-09-03 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20050901 + * Merge with NetBSD make, pick up: + o possible parse error causing us to wander off. + +2005-06-06 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20050606 + * Merge with NetBSD make, pick up: + o :0x modifier for randomizing a list + o fixes for a number of -Wuninitialized issues. + +2005-05-30 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20050530 + * Merge with NetBSD make, pick up: + o Handle dependencies for .BEGIN, .END and .INTERRUPT + + * README: was seriously out of date. + +2005-03-22 Simon J. Gerraty + + * Important to use .MAKE rather than MAKE. + +2005-03-15 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20050315 + * Merge with NetBSD make, pick up: + o don't mistake .elsefoo for .else + o use suffix-specific search path correctly + o bunch of style nits + +2004-05-11 Simon J. Gerraty + + * boot-strap: + o ensure that args to --src and --with-mksrc + are resolved before giving them to configure. + o add -o "objdir" so that builder can control it, + default is $OS as determined by os.sh + o add -q to suppress all the install instructions. + +2004-05-08 Simon J. Gerraty + + * Remove __IDSTRING() + + * Makefile.in (BMAKE_VERSION): bump to 20040508 + * Merge with NetBSD make, pick up: + o posix fixes + - remove '-e' from compat mode + - add support for '+' command-line prefix. + o fix for handling '--' on command-line. + o fix include in lst.lib/lstInt.h to simplify '-I's + o we also picked up replacement of MAKE_BOOTSTRAP + with !MAKE_NATIVE which is a noop, but possibly confusing. + +2004-04-14 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20040414 + * Merge with NetBSD make, pick up: + o allow quoted strings on lhs of conditionals + o issue warning when extra .else is seen + o print line numer when errors encountered during parsing from + string. + +2004-02-20 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20040220 + * Merge with NetBSD make, pick up: + o fix for old :M parsing bug. + o re-jigged unit-tests + +2004-02-15 Simon J. Gerraty + + * Makefile.in (accept test): use ${.MAKE:S,^./,${.CURDIR}/,} + so that './bmake -f Makefile test' works. + +2004-02-14 Simon J. Gerraty + + * Makefile.in: (BMAKE_VERSION): bump to 20040214 + * Merge with NetBSD make, pick up: + o search upwards for *.mk + o fix for double free of var substitution buffers + o use of getopt replaced with custom code, since the usage + (re-scanning) isn't posix compatible. + +2004-02-12 Simon J. Gerraty + + * arch.c: don't include ranlib.h on ELF systems + (thanks to Chuck Cranor ). + +2004-01-18 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump to 20040118 + + * boot-strap (while): export vars we assign to on cmdline + * unit-test/Makefile.in: ternary is .PHONY + +2004-01-08 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20040108 + * Merge with NetBSD make, pick up: + o fix for ternary modifier + +2004-01-06 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20040105 + * Merge with NetBSD make, pick up: + o fix for cond.c to handle compound expressions better + o variable expansion within sysV style replacements + +2003-12-22 Simon J. Gerraty + + * Make portable snprintf safer - output to /dev/null first to + check space needed. + + * Makefile.in (BMAKE_VERSION): bump version to 20031222 + * Merge with NetBSD make, pick up: + o -dg3 to show input graph when things go wrong. + o explicitly look for makefiles in objdir if not found in curdir so + that errors in .depend etc will be reported accurarely. + o avoid use of -e in shell scripts in jobs mode, use '|| exit $?' + instead as it more accurately reflects the expected behavior and + is more consistently implemented. + o avoid use of asprintf. + +2003-09-28 Simon J. Gerraty + + * util.c: Add asprintf and vasprintf. + + * Makefile.in (BMAKE_VERSION): bump version to 20030928 + * Merge with NetBSD make, pick up: + :[] modifier - allows picking words from a variable. + :tW modifier - allows treating value as one big word. + W flag for :C and :S - allows treating value as one big word. + +2003-09-12 Simon J. Gerraty + + * Merge with NetBSD make + pick up -de flag to enable printing failed command. + don't skip 1st two dir entries (normally . and ..) since + coda does not have them. + +2003-09-09 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20030909 + * Merge with NetBSD make, pick up: + - changes for -V '${VAR}' to print fully expanded value + cf. -V VAR + - CompatRunCommand now prints the command that failed. + - several files got updated 3 clause Berkeley license. + +2003-08-02 Simon J. Gerraty + + * boot-strap: Allow setting configure args on command line. + +2003-07-31 Simon J. Gerraty + + * configure.in: add --with-defshell to allow sh or ksh + to be selected as default shell. + + * Makefile.in: bump version to 20030731 + + * Merge with NetBSD make + Pick up .SHELL spec for ksh and associate man page changes. + Also compat mode now uses the same shell specs. + +2003-07-29 Simon J. Gerraty + + * var.c (Var_Parse): ensure delim is initialized. + + * unit-tests/Makefile.in: use single quotes to avoid problems from + some shells. + + * makefile.boot.in: + Run the unit-tests as part of the bootstrap procedure. + +2003-07-28 Simon J. Gerraty + + * unit-tests/Makefile.in: always force complaints from + ${TEST_MAKE} to be from 'make'. + + * configure.in: add check for 'diff -u' + also fix some old autoconf'isms + + * Makefile.in (BMAKE_VERSION): bump version to 20030728. + if using GCC add -Wno-cast-qual to CFLAGS for var.o + + * Merge with NetBSD make + Pick up fix for :ts parsing error in some cases. + Pick unit-tests. + +2003-07-23 Simon J. Gerraty + + * Makefile.in (BMAKE_VERSION): bump version to 20030723. + + * var.c (Var_Parse): fix bug in :ts modifier, after const + correctness fixes, must pass nstr to VarModify. + +2003-07-14 Simon J. Gerraty + + * Makefile.in: BMAKE_VERSION switch to a date based version. + We'll generally use the date of last import from NetBSD. + + * Merge with NetBSD make + Pick up fixes for const-correctness, now passes WARNS=3 on + NetBSD. + Pick up :ts modifier, allows controlling the separator used + between words in variable expansion. + +2003-07-11 Simon J. Gerraty + + * FILES: include boot-strap and os.sh + + * Makefile.in: only set WARNS if we are NetBSD, the effect on + FreeBSD is known to be bad. + + * makefile.boot.in (bootstrap): make this the default target. + + * Makefile.in: bump version to 3.1.19 + + * machine.sh: avoid A-Z with tr as it is bound to lose. + +2003-07-10 Simon J. Gerraty + + * Merge with NetBSD make + Pick up fix for PR/19781 - unhelpful error msg on unclosed ${var:foo + Plus some doc fixes. + +2003-04-27 Simon J. Gerraty + + * Merge with NetBSD make + Pick up fix for PR/1523 - don't count a library as built, if there + is no way to build it + + * Bump version to 3.1.18 + +2003-03-23 Simon J. Gerraty + + * Merge with NetBSD make + Pick up fix for ParseDoSpecialSrc - we only use it if .WAIT + appears in src list. + +2003-03-21 Simon J. Gerraty + + * Merge with NetBSD make (mmm 10th anniversary!) + pick up fix for .WAIT in srcs that refer to $@ or $* (PR#20828) + pick up -X which tells us to not export VAR=val via setenv if + we are already doing so via MAKEFLAGS. This saves valuable env + space on systems like Darwin. + set MAKE_VERSION to 3.1.17 + + * parse.c: pix up fix for suffix rules + +2003-03-06 Simon J. Gerraty + + * Merge with NetBSD make. + pick up fix for propagating -B via MAKEFLAGS. + set MAKE_VERSION to 3.1.16 + + * Apply some patches from pkgsrc-bootstrap/bmake + Originally by Grant Beattie + I may have missed some - since they are based on bmake-3.1.12 + +2002-12-03 Simon J. Gerraty + + * makefile.boot.in (bmake): update install targets for those that + use them, also clear MAKEFLAGS when invoking bmake.boot to avoid + havoc from gmake -w. Thanks to Harlan Stenn . + + * bmake.cat1: update the pre-formatted man page! + +2002-11-30 Simon J. Gerraty + + * Merge with NetBSD make. + pick up fix for premature free of pointer used in call + to Dir_InitCur(). + set MAKE_VERSION to 3.1.15 + +2002-11-26 Simon J. Gerraty + + * configure.in: determine suitable value for MKSRC. + override using --with-mksrc=PATH. + + * machine.sh: use `uname -p` for MACHINE_ARCH on modern SunOS systems. + configs(8) will use 'sun4' as an alias for 'sparc'. + +2002-11-25 Simon J. Gerraty + + * Merge with NetBSD make. + pick up ${.PATH} + pick up fix for finding ../cat.c via .PATH when .CURDIR=.. + set MAKE_VERSION to 3.1.14 + add configure checks for killpg and sys/socket.h + +2002-09-16 Simon J. Gerraty + + * tag bmake-3-1-13 + + * makefile.boot.in (bmake): use install-mk + Also setup ./mk before trying to invoke bmake.boot incase we + needed install-mk to create a sys.mk for us. + + * configure.in: If we need to add -I${srcdir}/missing, make it an + absolute path so that it works for lst.lib too. + + * make.h: always include sys/cdefs.h since we provide one if the + host does not. + + * Makefile.in (install-mk): + use MKSRC/install-mk which will do the right thing. + use uname -p for ARCH if possible. + since install-mk will setup links bsd.prog.mk -> prog.mk if + needed, just .include bsd.prog.mk + + * Merge with NetBSD make (NetBSD-1.6) + Code is ansi-C only now. + Bug in handling of dotLast is fixed. + Can now assign .OBJDIR and make will reset its notions of life. + New modifiers :tu :tl for toUpper and toLower. + +Tue Oct 16 12:18:42 2001 Simon J. Gerraty + + * Merge with NetBSD make + pick up fix for .END failure in compat mode. + pick up fix for extra va_end() in ParseVErrorInternal. + +Thu Oct 11 13:20:06 2001 Simon J. Gerraty + + * configure.in: for systems that have sys/cdefs.h check if it is + compatible. If not, include the one under missing, but tell it to + include the native one too - necessary on Linux. + + * missing/sys/cdefs.h: if NEED_HOST_CDEFS_H is defined, use + include_next (for gcc) to get the native sys/cdefs.h + +Tue Aug 21 02:29:34 2001 Simon J. Gerraty + + * job.c (JobFinish): Fix an earlier merge bug that resulted in + leaking descriptors when using -jN. + + * job.c (JobPrintCommand): See if "curdir" exists before + attempting to chdir(). Doing the chdir directly in make (when in + compat mode) fails silently, so let the -jN version do the same. + This can happen when building kernels in an object tree and + playing clever games to reset .CURDIR. + + * Merged with NetBSD make + pick up .USEBEFORE + +Tue Jun 26 23:45:11 2001 Simon J. Gerraty + + * makefile.boot.in: Give bmake.boot a MAKESYSPATH that might work. + +Tue Jun 12 16:48:57 2001 Simon J. Gerraty + + * var.c (Var_Set): Add 4th (flags) arg so VarLoopExpand can tell + us not to export the iterator variable when using VAR_CMD context. + +Sun Jun 10 21:55:21 2001 Simon J. Gerraty + + * job.c (Job_CatchChildren): don't call Job_CatchOutput() here, + its the wrong "fix". + +Sat Jun 9 00:11:24 2001 Simon J. Gerraty + + * Redesigned export of VAR_CMD's via MAKEFLAGS. + We now simply append the variable names to .MAKEOVERRIDES, and + handle duplicate suppression and quoting in ExportMAKEFLAGS using: + ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@} + Apart from fixing quoting bugs in previous version, this allows us + to export vars to the environment by simply doing: + .MAKEOVERRIDES+= PATH + Merged again with NetBSD make, but the above is the only change. + + * configure.in: added + --disable-pwd-override disable $PWD overriding getcwd() + --disable-check-make-chdir disable make trying to guess + when it should automatically cd ${.CURDIR} + + * Merge with NetBSD make, changes include: + parse.c (ParseDoDependency): Spot that the syntax error is + caused by an unresolved cvs/rcs conflict and say so. + var.c: most of Var* functions now take a ctxt as 1st arg. + now does variable substituion on rhs of sysv style modifiers. + + * var.c (Var_Set): exporting of command line variables (VAR_CMD) + is now done here. We append the name='value' to .MAKEOVERRIDES + rather than directly into MAKEFLAGS as this allows a Makefile to + use .MAKEOVERRIDES= to disable this behaviour. GNU make uses a + very similar mechanism. Note that in adding name='value' to + .MAKEOVERRIDES we do the moral equivalent of: + .MAKEOVERRIDES:= ${.MAKEOVERRIDES:Nname=*} name='val' + +Fri Jun 1 14:08:02 2001 Simon J. Gerraty + + * make-conf.h (USE_IOVEC): make it conditional on HAVE_SYS_UIO_H + + * Merged with NetBSD make + make -dx can now be used to run commands via sh -x + better error messages on exec failures. + +Thu May 31 01:44:54 2001 Simon J. Gerraty + + * Makefile.in (main.o): depends on ${SRCS} ${MAKEFILE} so that + MAKE_VERSION gets updated. Also don't use ?= for MAKE_VERSION, + MACHINE etc otherwise they propagate from the previous bmake. + + * configure.in (machine): allow --with-machine=generic to make + configure use machine.sh to set MACHINE. + + * job.c (JobInterrupt): convert to using WAIT_T and friends. + + * Makefile.in: mention in bmake.1 that we use autoconf. + + * make.1: mention MAKE_PRINT_VAR_ON_ERROR. + +Wed May 30 23:17:18 2001 Simon J. Gerraty + + * main.c (ReadMakefile): don't set MAKEFILE if reading ".depend" + as that rather defeats the usefulness of ${MAKEFILE}. + + * main.c (MainParseArgs): append command line variable assignments + to MAKEFLAGS so that they get propagated to child make's. + Apparently this is required POSIX behaviour? Its useful anyway. + +Tue May 29 02:20:07 2001 Simon J. Gerraty + + * compat.c (CompatRunCommand): don't use perror() since stdio may + cause problems in child of vfork(). + + * compat.c, main.c: Call PrintOnError() when we are going to bail. + This routine prints out the .curdir where we stopped and will also + display any vars listed in ${MAKE_PRINT_VAR_ON_ERROR}. + + * main.c: add ${.newline} to hold a "\n" - sometimes handy in + :@ expansion. + + * var.c: VarLoopExpand: ignore addSpace if a \n is present. + + * Added RCSid's for the files we've touched. + +Thu May 24 15:41:37 2001 Simon J. Gerraty + + * configure.in: Thanks to some clues from mdb@juniper.net, + added autoconf magic to control setting of MACHINE, MACHINE_ARCH + as well as what ends up in _PATH_DEFSYSPATH. We now have: + + --with-machine=MACHINE explicitly set MACHINE + --with-force-machine=MACHINE set FORCE_MACHINE + --with-machine_arch=MACHINE_ARCH explicitly set MACHINE_ARCH + --with-default-sys-path=PATH:DIR:LIST use an explicit _PATH_DEFSYSPATH + --with-prefix-sys-path=PATH:DIR:LIST prefix _PATH_PREFIX_SYSPATH + --with-path-objdirprefix=PATH override _PATH_OBJDIRPREFIX + + If _PATH_OBJDIRPREFIX is set to "no" we won't define it. + + * makefile: added a pathetically simple makefile to drive + bootstrapping. Running configure by hand is more useful. + + * Makefile.in: added MAKE_VERSION, and reworked things to be less + dependent on NetBSD bsd.*.mk + + * pathnames.h: allow NO_PATH_OBJDIRPREFIX to stop us defining + _PATH_OBJDIRPREFIX for those that don't want a default. + construct _PATH_DEFSYSPATH from the info we get from configure. + + * main.c: allow for no _PATH_OBJDIRPREFIX, set ${MAKE_VERSION} + if MAKE_VERSION is defined. + + * compat.c: when we bail, print out the .CURDIR we were in. + +Sat May 12 00:34:12 2001 Simon J. Gerraty + + * Merged with NetBSD make + + * var.c: fixed a bug in the handling of the modifier :P + if the node as found but the path was null, we segfault trying to + duplicate it. + +Mon Mar 5 16:20:33 2001 Simon J. Gerraty + + * Merged with NetBSD make + + * make.c: Make_OODate's test for a library out of date was using + cmtime where it should have used mtime (my bug). + + * compat.c: Use perror() to tell us what really went wrong when we + cannot exec a command. + +Fri Dec 15 10:11:08 2000 Simon J. Gerraty + + * Merged with NetBSD make + +Sat Jun 10 10:11:08 2000 Simon J. Gerraty + + * Merged with NetBSD make + +Thu Jun 1 10:11:08 2000 Simon J. Gerraty + + * Merged with NetBSD make + +Tue May 30 10:11:08 2000 Simon J. Gerraty + + * Merged with NetBSD make + +Thu Apr 27 00:07:47 2000 Simon J. Gerraty + + * util.c: don't provide signal() since we use sigcompat.c + + * Makefile.in: added a build target. + + * var.c (Var_Parse): added ODE modifiers :U, :D, :L, :P, :@ and :! + These allow some quite clever magic. + + * main.c (main): added support for getenv(MAKESYSPATH). + +Mon Apr 2 16:25:13 2000 Simon J. Gerraty + + * Disable $PWD overriding getcwd() if MAKEOBJDIRPREFIX is set. + This avoids objdir having a different value depending on how a + directory was reached (via command line, or subdir.mk). + + * If FORCE_MACHINE is defined, ignore getenv("MACHINE"). + +Mon Apr 2 23:15:31 2000 Simon J. Gerraty + + * Do a chdir(${.CURDIR}) before invoking ${.MAKE} or ${.MAKE:T} if + MAKEOBJDIRPREFIX is set and NOCHECKMAKECHDIR is not. + I've been testing this in NetBSD's make for some weeks. + + * Turn Makefile into Makefile.in and make it useful. + +Tue Feb 29 22:08:00 2000 Simon J. Gerraty + + * Imported NetBSD's -current make(1) and resolve conflicts. + + * Applied autoconf patches from bmake v2 + + * Imported clean code base from NetBSD-1.0 Index: vendor/NetBSD/bmake/20201101/FILES =================================================================== --- vendor/NetBSD/bmake/20201101/FILES (nonexistent) +++ vendor/NetBSD/bmake/20201101/FILES (revision 367461) @@ -0,0 +1,750 @@ +ChangeLog +FILES +LICENSE +Makefile +Makefile.config.in +PSD.doc/Makefile +PSD.doc/tutorial.ms +README +VERSION +aclocal.m4 +arch.c +bmake.1 +bmake.cat1 +boot-strap +bsd.after-import.mk +buf.c +buf.h +compat.c +cond.c +config.h.in +configure +configure.in +dir.c +dir.h +dirname.c +enum.c +enum.h +filemon/filemon.h +filemon/filemon_dev.c +filemon/filemon_ktrace.c +find_lib.sh +for.c +getopt.c +hash.c +hash.h +install-sh +job.c +job.h +lst.c +lst.h +machine.sh +main.c +make-bootstrap.sh.in +make-conf.h +make.1 +make.c +make.h +make_malloc.c +make_malloc.h +makefile.in +meta.c +meta.h +metachar.c +metachar.h +missing/sys/cdefs.h +mkdeps.sh +nonints.h +os.sh +parse.c +pathnames.h +ranlib.h +realpath.c +setenv.c +sigcompat.c +str.c +stresep.c +strlcpy.c +suff.c +targ.c +trace.c +trace.h +unit-tests/Makefile +unit-tests/Makefile.config.in +unit-tests/archive-suffix.exp +unit-tests/archive-suffix.mk +unit-tests/archive.exp +unit-tests/archive.mk +unit-tests/cmd-interrupt.exp +unit-tests/cmd-interrupt.mk +unit-tests/cmdline.exp +unit-tests/cmdline.mk +unit-tests/comment.exp +unit-tests/comment.mk +unit-tests/cond-cmp-numeric-eq.exp +unit-tests/cond-cmp-numeric-eq.mk +unit-tests/cond-cmp-numeric-ge.exp +unit-tests/cond-cmp-numeric-ge.mk +unit-tests/cond-cmp-numeric-gt.exp +unit-tests/cond-cmp-numeric-gt.mk +unit-tests/cond-cmp-numeric-le.exp +unit-tests/cond-cmp-numeric-le.mk +unit-tests/cond-cmp-numeric-lt.exp +unit-tests/cond-cmp-numeric-lt.mk +unit-tests/cond-cmp-numeric-ne.exp +unit-tests/cond-cmp-numeric-ne.mk +unit-tests/cond-cmp-numeric.exp +unit-tests/cond-cmp-numeric.mk +unit-tests/cond-cmp-string.exp +unit-tests/cond-cmp-string.mk +unit-tests/cond-cmp-unary.exp +unit-tests/cond-cmp-unary.mk +unit-tests/cond-func-commands.exp +unit-tests/cond-func-commands.mk +unit-tests/cond-func-defined.exp +unit-tests/cond-func-defined.mk +unit-tests/cond-func-empty.exp +unit-tests/cond-func-empty.mk +unit-tests/cond-func-exists.exp +unit-tests/cond-func-exists.mk +unit-tests/cond-func-make.exp +unit-tests/cond-func-make.mk +unit-tests/cond-func-target.exp +unit-tests/cond-func-target.mk +unit-tests/cond-func.exp +unit-tests/cond-func.mk +unit-tests/cond-late.exp +unit-tests/cond-late.mk +unit-tests/cond-op-and.exp +unit-tests/cond-op-and.mk +unit-tests/cond-op-not.exp +unit-tests/cond-op-not.mk +unit-tests/cond-op-or.exp +unit-tests/cond-op-or.mk +unit-tests/cond-op-parentheses.exp +unit-tests/cond-op-parentheses.mk +unit-tests/cond-op.exp +unit-tests/cond-op.mk +unit-tests/cond-short.exp +unit-tests/cond-short.mk +unit-tests/cond-token-number.exp +unit-tests/cond-token-number.mk +unit-tests/cond-token-plain.exp +unit-tests/cond-token-plain.mk +unit-tests/cond-token-string.exp +unit-tests/cond-token-string.mk +unit-tests/cond-token-var.exp +unit-tests/cond-token-var.mk +unit-tests/cond-undef-lint.exp +unit-tests/cond-undef-lint.mk +unit-tests/cond1.exp +unit-tests/cond1.mk +unit-tests/counter-append.exp +unit-tests/counter-append.mk +unit-tests/counter.exp +unit-tests/counter.mk +unit-tests/dep-colon-bug-cross-file.exp +unit-tests/dep-colon-bug-cross-file.mk +unit-tests/dep-colon.exp +unit-tests/dep-colon.mk +unit-tests/dep-double-colon-indep.exp +unit-tests/dep-double-colon-indep.mk +unit-tests/dep-double-colon.exp +unit-tests/dep-double-colon.mk +unit-tests/dep-exclam.exp +unit-tests/dep-exclam.mk +unit-tests/dep-none.exp +unit-tests/dep-none.mk +unit-tests/dep-percent.exp +unit-tests/dep-percent.mk +unit-tests/dep-var.exp +unit-tests/dep-var.mk +unit-tests/dep-wildcards.exp +unit-tests/dep-wildcards.mk +unit-tests/dep.exp +unit-tests/dep.mk +unit-tests/depsrc-end.exp +unit-tests/depsrc-end.mk +unit-tests/depsrc-exec.exp +unit-tests/depsrc-exec.mk +unit-tests/depsrc-ignore.exp +unit-tests/depsrc-ignore.mk +unit-tests/depsrc-made.exp +unit-tests/depsrc-made.mk +unit-tests/depsrc-make.exp +unit-tests/depsrc-make.mk +unit-tests/depsrc-meta.exp +unit-tests/depsrc-meta.mk +unit-tests/depsrc-nometa.exp +unit-tests/depsrc-nometa.mk +unit-tests/depsrc-nometa_cmp.exp +unit-tests/depsrc-nometa_cmp.mk +unit-tests/depsrc-nopath.exp +unit-tests/depsrc-nopath.mk +unit-tests/depsrc-notmain.exp +unit-tests/depsrc-notmain.mk +unit-tests/depsrc-optional.exp +unit-tests/depsrc-optional.mk +unit-tests/depsrc-phony.exp +unit-tests/depsrc-phony.mk +unit-tests/depsrc-precious.exp +unit-tests/depsrc-precious.mk +unit-tests/depsrc-recursive.exp +unit-tests/depsrc-recursive.mk +unit-tests/depsrc-silent.exp +unit-tests/depsrc-silent.mk +unit-tests/depsrc-use.exp +unit-tests/depsrc-use.mk +unit-tests/depsrc-usebefore-double-colon.exp +unit-tests/depsrc-usebefore-double-colon.mk +unit-tests/depsrc-usebefore.exp +unit-tests/depsrc-usebefore.mk +unit-tests/depsrc-wait.exp +unit-tests/depsrc-wait.mk +unit-tests/depsrc.exp +unit-tests/depsrc.mk +unit-tests/deptgt-begin.exp +unit-tests/deptgt-begin.mk +unit-tests/deptgt-default.exp +unit-tests/deptgt-default.mk +unit-tests/deptgt-delete_on_error.exp +unit-tests/deptgt-delete_on_error.mk +unit-tests/deptgt-end-jobs.exp +unit-tests/deptgt-end-jobs.mk +unit-tests/deptgt-end.exp +unit-tests/deptgt-end.mk +unit-tests/deptgt-error.exp +unit-tests/deptgt-error.mk +unit-tests/deptgt-ignore.exp +unit-tests/deptgt-ignore.mk +unit-tests/deptgt-interrupt.exp +unit-tests/deptgt-interrupt.mk +unit-tests/deptgt-main.exp +unit-tests/deptgt-main.mk +unit-tests/deptgt-makeflags.exp +unit-tests/deptgt-makeflags.mk +unit-tests/deptgt-no_parallel.exp +unit-tests/deptgt-no_parallel.mk +unit-tests/deptgt-nopath.exp +unit-tests/deptgt-nopath.mk +unit-tests/deptgt-notparallel.exp +unit-tests/deptgt-notparallel.mk +unit-tests/deptgt-objdir.exp +unit-tests/deptgt-objdir.mk +unit-tests/deptgt-order.exp +unit-tests/deptgt-order.mk +unit-tests/deptgt-path-suffix.exp +unit-tests/deptgt-path-suffix.mk +unit-tests/deptgt-path.exp +unit-tests/deptgt-path.mk +unit-tests/deptgt-phony.exp +unit-tests/deptgt-phony.mk +unit-tests/deptgt-precious.exp +unit-tests/deptgt-precious.mk +unit-tests/deptgt-shell.exp +unit-tests/deptgt-shell.mk +unit-tests/deptgt-silent.exp +unit-tests/deptgt-silent.mk +unit-tests/deptgt-stale.exp +unit-tests/deptgt-stale.mk +unit-tests/deptgt-suffixes.exp +unit-tests/deptgt-suffixes.mk +unit-tests/deptgt.exp +unit-tests/deptgt.mk +unit-tests/dir-expand-path.exp +unit-tests/dir-expand-path.mk +unit-tests/dir.exp +unit-tests/dir.mk +unit-tests/directive-dinclude.exp +unit-tests/directive-dinclude.mk +unit-tests/directive-elif.exp +unit-tests/directive-elif.mk +unit-tests/directive-elifdef.exp +unit-tests/directive-elifdef.mk +unit-tests/directive-elifmake.exp +unit-tests/directive-elifmake.mk +unit-tests/directive-elifndef.exp +unit-tests/directive-elifndef.mk +unit-tests/directive-elifnmake.exp +unit-tests/directive-elifnmake.mk +unit-tests/directive-else.exp +unit-tests/directive-else.mk +unit-tests/directive-endif.exp +unit-tests/directive-endif.mk +unit-tests/directive-error.exp +unit-tests/directive-error.mk +unit-tests/directive-export-env.exp +unit-tests/directive-export-env.mk +unit-tests/directive-export-gmake.exp +unit-tests/directive-export-gmake.mk +unit-tests/directive-export-literal.exp +unit-tests/directive-export-literal.mk +unit-tests/directive-export.exp +unit-tests/directive-export.mk +unit-tests/directive-for-generating-endif.exp +unit-tests/directive-for-generating-endif.mk +unit-tests/directive-for.exp +unit-tests/directive-for.mk +unit-tests/directive-hyphen-include.exp +unit-tests/directive-hyphen-include.mk +unit-tests/directive-if.exp +unit-tests/directive-if.mk +unit-tests/directive-ifdef.exp +unit-tests/directive-ifdef.mk +unit-tests/directive-ifmake.exp +unit-tests/directive-ifmake.mk +unit-tests/directive-ifndef.exp +unit-tests/directive-ifndef.mk +unit-tests/directive-ifnmake.exp +unit-tests/directive-ifnmake.mk +unit-tests/directive-include-fatal.exp +unit-tests/directive-include-fatal.mk +unit-tests/directive-include.exp +unit-tests/directive-include.mk +unit-tests/directive-info.exp +unit-tests/directive-info.mk +unit-tests/directive-sinclude.exp +unit-tests/directive-sinclude.mk +unit-tests/directive-undef.exp +unit-tests/directive-undef.mk +unit-tests/directive-unexport-env.exp +unit-tests/directive-unexport-env.mk +unit-tests/directive-unexport.exp +unit-tests/directive-unexport.mk +unit-tests/directive-warning.exp +unit-tests/directive-warning.mk +unit-tests/directive.exp +unit-tests/directive.mk +unit-tests/directives.exp +unit-tests/directives.mk +unit-tests/dollar.exp +unit-tests/dollar.mk +unit-tests/doterror.exp +unit-tests/doterror.mk +unit-tests/dotwait.exp +unit-tests/dotwait.mk +unit-tests/envfirst.exp +unit-tests/envfirst.mk +unit-tests/error.exp +unit-tests/error.mk +unit-tests/escape.exp +unit-tests/escape.mk +unit-tests/export-all.exp +unit-tests/export-all.mk +unit-tests/export-env.exp +unit-tests/export-env.mk +unit-tests/export-variants.exp +unit-tests/export-variants.mk +unit-tests/export.exp +unit-tests/export.mk +unit-tests/forloop.exp +unit-tests/forloop.mk +unit-tests/forsubst.exp +unit-tests/forsubst.mk +unit-tests/hanoi-include.exp +unit-tests/hanoi-include.mk +unit-tests/impsrc.exp +unit-tests/impsrc.mk +unit-tests/include-main.exp +unit-tests/include-main.mk +unit-tests/include-sub.mk +unit-tests/include-subsub.mk +unit-tests/job-output-long-lines.exp +unit-tests/job-output-long-lines.mk +unit-tests/lint.exp +unit-tests/lint.mk +unit-tests/make-exported.exp +unit-tests/make-exported.mk +unit-tests/moderrs.exp +unit-tests/moderrs.mk +unit-tests/modmatch.exp +unit-tests/modmatch.mk +unit-tests/modmisc.exp +unit-tests/modmisc.mk +unit-tests/modts.exp +unit-tests/modts.mk +unit-tests/modword.exp +unit-tests/modword.mk +unit-tests/opt-backwards.exp +unit-tests/opt-backwards.mk +unit-tests/opt-chdir.exp +unit-tests/opt-chdir.mk +unit-tests/opt-debug-all.exp +unit-tests/opt-debug-all.mk +unit-tests/opt-debug-archive.exp +unit-tests/opt-debug-archive.mk +unit-tests/opt-debug-cond.exp +unit-tests/opt-debug-cond.mk +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.exp +unit-tests/opt-debug-errors.mk +unit-tests/opt-debug-file.exp +unit-tests/opt-debug-file.mk +unit-tests/opt-debug-for.exp +unit-tests/opt-debug-for.mk +unit-tests/opt-debug-graph1.exp +unit-tests/opt-debug-graph1.mk +unit-tests/opt-debug-graph2.exp +unit-tests/opt-debug-graph2.mk +unit-tests/opt-debug-graph3.exp +unit-tests/opt-debug-graph3.mk +unit-tests/opt-debug-hash.exp +unit-tests/opt-debug-hash.mk +unit-tests/opt-debug-jobs.exp +unit-tests/opt-debug-jobs.mk +unit-tests/opt-debug-lint.exp +unit-tests/opt-debug-lint.mk +unit-tests/opt-debug-loud.exp +unit-tests/opt-debug-loud.mk +unit-tests/opt-debug-making.exp +unit-tests/opt-debug-making.mk +unit-tests/opt-debug-meta.exp +unit-tests/opt-debug-meta.mk +unit-tests/opt-debug-no-rm.exp +unit-tests/opt-debug-no-rm.mk +unit-tests/opt-debug-parse.exp +unit-tests/opt-debug-parse.mk +unit-tests/opt-debug-suff.exp +unit-tests/opt-debug-suff.mk +unit-tests/opt-debug-targets.exp +unit-tests/opt-debug-targets.mk +unit-tests/opt-debug-var.exp +unit-tests/opt-debug-var.mk +unit-tests/opt-debug-varraw.exp +unit-tests/opt-debug-varraw.mk +unit-tests/opt-debug-x-trace.exp +unit-tests/opt-debug-x-trace.mk +unit-tests/opt-debug.exp +unit-tests/opt-debug.mk +unit-tests/opt-define.exp +unit-tests/opt-define.mk +unit-tests/opt-env.exp +unit-tests/opt-env.mk +unit-tests/opt-file.exp +unit-tests/opt-file.mk +unit-tests/opt-ignore.exp +unit-tests/opt-ignore.mk +unit-tests/opt-include-dir.exp +unit-tests/opt-include-dir.mk +unit-tests/opt-jobs-internal.exp +unit-tests/opt-jobs-internal.mk +unit-tests/opt-jobs.exp +unit-tests/opt-jobs.mk +unit-tests/opt-keep-going.exp +unit-tests/opt-keep-going.mk +unit-tests/opt-m-include-dir.exp +unit-tests/opt-m-include-dir.mk +unit-tests/opt-no-action-at-all.exp +unit-tests/opt-no-action-at-all.mk +unit-tests/opt-no-action.exp +unit-tests/opt-no-action.mk +unit-tests/opt-query.exp +unit-tests/opt-query.mk +unit-tests/opt-raw.exp +unit-tests/opt-raw.mk +unit-tests/opt-silent.exp +unit-tests/opt-silent.mk +unit-tests/opt-touch.exp +unit-tests/opt-touch.mk +unit-tests/opt-tracefile.exp +unit-tests/opt-tracefile.mk +unit-tests/opt-var-expanded.exp +unit-tests/opt-var-expanded.mk +unit-tests/opt-var-literal.exp +unit-tests/opt-var-literal.mk +unit-tests/opt-warnings-as-errors.exp +unit-tests/opt-warnings-as-errors.mk +unit-tests/opt-where-am-i.exp +unit-tests/opt-where-am-i.mk +unit-tests/opt-x-reduce-exported.exp +unit-tests/opt-x-reduce-exported.mk +unit-tests/opt.exp +unit-tests/opt.mk +unit-tests/order.exp +unit-tests/order.mk +unit-tests/parse-var.exp +unit-tests/parse-var.mk +unit-tests/phony-end.exp +unit-tests/phony-end.mk +unit-tests/posix.exp +unit-tests/posix.mk +unit-tests/posix1.exp +unit-tests/posix1.mk +unit-tests/qequals.exp +unit-tests/qequals.mk +unit-tests/recursive.exp +unit-tests/recursive.mk +unit-tests/sh-dots.exp +unit-tests/sh-dots.mk +unit-tests/sh-jobs-error.exp +unit-tests/sh-jobs-error.mk +unit-tests/sh-jobs.exp +unit-tests/sh-jobs.mk +unit-tests/sh-leading-at.exp +unit-tests/sh-leading-at.mk +unit-tests/sh-leading-hyphen.exp +unit-tests/sh-leading-hyphen.mk +unit-tests/sh-leading-plus.exp +unit-tests/sh-leading-plus.mk +unit-tests/sh-meta-chars.exp +unit-tests/sh-meta-chars.mk +unit-tests/sh-multi-line.exp +unit-tests/sh-multi-line.mk +unit-tests/sh-single-line.exp +unit-tests/sh-single-line.mk +unit-tests/sh.exp +unit-tests/sh.mk +unit-tests/shell-csh.exp +unit-tests/shell-csh.mk +unit-tests/shell-custom.exp +unit-tests/shell-custom.mk +unit-tests/shell-ksh.exp +unit-tests/shell-ksh.mk +unit-tests/shell-sh.exp +unit-tests/shell-sh.mk +unit-tests/suff-add-later.exp +unit-tests/suff-add-later.mk +unit-tests/suff-clear-regular.exp +unit-tests/suff-clear-regular.mk +unit-tests/suff-clear-single.exp +unit-tests/suff-clear-single.mk +unit-tests/suff-lookup.exp +unit-tests/suff-lookup.mk +unit-tests/suff-main.exp +unit-tests/suff-main.mk +unit-tests/suff-rebuild.exp +unit-tests/suff-rebuild.mk +unit-tests/suff-transform-endless.exp +unit-tests/suff-transform-endless.mk +unit-tests/suff-transform-expand.exp +unit-tests/suff-transform-expand.mk +unit-tests/suff-transform-select.exp +unit-tests/suff-transform-select.mk +unit-tests/sunshcmd.exp +unit-tests/sunshcmd.mk +unit-tests/ternary.exp +unit-tests/ternary.mk +unit-tests/unexport-env.exp +unit-tests/unexport-env.mk +unit-tests/unexport.exp +unit-tests/unexport.mk +unit-tests/use-inference.exp +unit-tests/use-inference.mk +unit-tests/var-class-cmdline.exp +unit-tests/var-class-cmdline.mk +unit-tests/var-class-env.exp +unit-tests/var-class-env.mk +unit-tests/var-class-global.exp +unit-tests/var-class-global.mk +unit-tests/var-class-local-legacy.exp +unit-tests/var-class-local-legacy.mk +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-op-append.exp +unit-tests/var-op-append.mk +unit-tests/var-op-assign.exp +unit-tests/var-op-assign.mk +unit-tests/var-op-default.exp +unit-tests/var-op-default.mk +unit-tests/var-op-expand.exp +unit-tests/var-op-expand.mk +unit-tests/var-op-shell.exp +unit-tests/var-op-shell.mk +unit-tests/var-op-sunsh.exp +unit-tests/var-op-sunsh.mk +unit-tests/var-op.exp +unit-tests/var-op.mk +unit-tests/var-recursive.exp +unit-tests/var-recursive.mk +unit-tests/varcmd.exp +unit-tests/varcmd.mk +unit-tests/vardebug.exp +unit-tests/vardebug.mk +unit-tests/varfind.exp +unit-tests/varfind.mk +unit-tests/varmisc.exp +unit-tests/varmisc.mk +unit-tests/varmod-assign.exp +unit-tests/varmod-assign.mk +unit-tests/varmod-defined.exp +unit-tests/varmod-defined.mk +unit-tests/varmod-edge.exp +unit-tests/varmod-edge.mk +unit-tests/varmod-exclam-shell.exp +unit-tests/varmod-exclam-shell.mk +unit-tests/varmod-extension.exp +unit-tests/varmod-extension.mk +unit-tests/varmod-gmtime.exp +unit-tests/varmod-gmtime.mk +unit-tests/varmod-hash.exp +unit-tests/varmod-hash.mk +unit-tests/varmod-head.exp +unit-tests/varmod-head.mk +unit-tests/varmod-ifelse.exp +unit-tests/varmod-ifelse.mk +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.exp +unit-tests/varmod-loop.mk +unit-tests/varmod-match-escape.exp +unit-tests/varmod-match-escape.mk +unit-tests/varmod-match.exp +unit-tests/varmod-match.mk +unit-tests/varmod-no-match.exp +unit-tests/varmod-no-match.mk +unit-tests/varmod-order-reverse.exp +unit-tests/varmod-order-reverse.mk +unit-tests/varmod-order-shuffle.exp +unit-tests/varmod-order-shuffle.mk +unit-tests/varmod-order.exp +unit-tests/varmod-order.mk +unit-tests/varmod-path.exp +unit-tests/varmod-path.mk +unit-tests/varmod-quote-dollar.exp +unit-tests/varmod-quote-dollar.mk +unit-tests/varmod-quote.exp +unit-tests/varmod-quote.mk +unit-tests/varmod-range.exp +unit-tests/varmod-range.mk +unit-tests/varmod-remember.exp +unit-tests/varmod-remember.mk +unit-tests/varmod-root.exp +unit-tests/varmod-root.mk +unit-tests/varmod-select-words.exp +unit-tests/varmod-select-words.mk +unit-tests/varmod-shell.exp +unit-tests/varmod-shell.mk +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-sysv.exp +unit-tests/varmod-sysv.mk +unit-tests/varmod-tail.exp +unit-tests/varmod-tail.mk +unit-tests/varmod-to-abs.exp +unit-tests/varmod-to-abs.mk +unit-tests/varmod-to-lower.exp +unit-tests/varmod-to-lower.mk +unit-tests/varmod-to-many-words.exp +unit-tests/varmod-to-many-words.mk +unit-tests/varmod-to-one-word.exp +unit-tests/varmod-to-one-word.mk +unit-tests/varmod-to-separator.exp +unit-tests/varmod-to-separator.mk +unit-tests/varmod-to-upper.exp +unit-tests/varmod-to-upper.mk +unit-tests/varmod-undefined.exp +unit-tests/varmod-undefined.mk +unit-tests/varmod-unique.exp +unit-tests/varmod-unique.mk +unit-tests/varmod.exp +unit-tests/varmod.mk +unit-tests/varname-dollar.exp +unit-tests/varname-dollar.mk +unit-tests/varname-dot-alltargets.exp +unit-tests/varname-dot-alltargets.mk +unit-tests/varname-dot-curdir.exp +unit-tests/varname-dot-curdir.mk +unit-tests/varname-dot-includedfromdir.exp +unit-tests/varname-dot-includedfromdir.mk +unit-tests/varname-dot-includedfromfile.exp +unit-tests/varname-dot-includedfromfile.mk +unit-tests/varname-dot-includes.exp +unit-tests/varname-dot-includes.mk +unit-tests/varname-dot-libs.exp +unit-tests/varname-dot-libs.mk +unit-tests/varname-dot-make-dependfile.exp +unit-tests/varname-dot-make-dependfile.mk +unit-tests/varname-dot-make-expand_variables.exp +unit-tests/varname-dot-make-expand_variables.mk +unit-tests/varname-dot-make-exported.exp +unit-tests/varname-dot-make-exported.mk +unit-tests/varname-dot-make-jobs-prefix.exp +unit-tests/varname-dot-make-jobs-prefix.mk +unit-tests/varname-dot-make-jobs.exp +unit-tests/varname-dot-make-jobs.mk +unit-tests/varname-dot-make-level.exp +unit-tests/varname-dot-make-level.mk +unit-tests/varname-dot-make-makefile_preference.exp +unit-tests/varname-dot-make-makefile_preference.mk +unit-tests/varname-dot-make-makefiles.exp +unit-tests/varname-dot-make-makefiles.mk +unit-tests/varname-dot-make-meta-bailiwick.exp +unit-tests/varname-dot-make-meta-bailiwick.mk +unit-tests/varname-dot-make-meta-created.exp +unit-tests/varname-dot-make-meta-created.mk +unit-tests/varname-dot-make-meta-files.exp +unit-tests/varname-dot-make-meta-files.mk +unit-tests/varname-dot-make-meta-ignore_filter.exp +unit-tests/varname-dot-make-meta-ignore_filter.mk +unit-tests/varname-dot-make-meta-ignore_paths.exp +unit-tests/varname-dot-make-meta-ignore_paths.mk +unit-tests/varname-dot-make-meta-ignore_patterns.exp +unit-tests/varname-dot-make-meta-ignore_patterns.mk +unit-tests/varname-dot-make-meta-prefix.exp +unit-tests/varname-dot-make-meta-prefix.mk +unit-tests/varname-dot-make-mode.exp +unit-tests/varname-dot-make-mode.mk +unit-tests/varname-dot-make-path_filemon.exp +unit-tests/varname-dot-make-path_filemon.mk +unit-tests/varname-dot-make-pid.exp +unit-tests/varname-dot-make-pid.mk +unit-tests/varname-dot-make-ppid.exp +unit-tests/varname-dot-make-ppid.mk +unit-tests/varname-dot-make-save_dollars.exp +unit-tests/varname-dot-make-save_dollars.mk +unit-tests/varname-dot-makeoverrides.exp +unit-tests/varname-dot-makeoverrides.mk +unit-tests/varname-dot-newline.exp +unit-tests/varname-dot-newline.mk +unit-tests/varname-dot-objdir.exp +unit-tests/varname-dot-objdir.mk +unit-tests/varname-dot-parsedir.exp +unit-tests/varname-dot-parsedir.mk +unit-tests/varname-dot-parsefile.exp +unit-tests/varname-dot-parsefile.mk +unit-tests/varname-dot-path.exp +unit-tests/varname-dot-path.mk +unit-tests/varname-dot-shell.exp +unit-tests/varname-dot-shell.mk +unit-tests/varname-dot-targets.exp +unit-tests/varname-dot-targets.mk +unit-tests/varname-empty.exp +unit-tests/varname-empty.mk +unit-tests/varname-make.exp +unit-tests/varname-make.mk +unit-tests/varname-make_print_var_on_error-jobs.exp +unit-tests/varname-make_print_var_on_error-jobs.mk +unit-tests/varname-make_print_var_on_error.exp +unit-tests/varname-make_print_var_on_error.mk +unit-tests/varname-makefile.exp +unit-tests/varname-makefile.mk +unit-tests/varname-makeflags.exp +unit-tests/varname-makeflags.mk +unit-tests/varname-pwd.exp +unit-tests/varname-pwd.mk +unit-tests/varname-vpath.exp +unit-tests/varname-vpath.mk +unit-tests/varname.exp +unit-tests/varname.mk +unit-tests/varparse-dynamic.exp +unit-tests/varparse-dynamic.mk +unit-tests/varparse-mod.exp +unit-tests/varparse-mod.mk +unit-tests/varparse-undef-partial.exp +unit-tests/varparse-undef-partial.mk +unit-tests/varquote.exp +unit-tests/varquote.mk +unit-tests/varshell.exp +unit-tests/varshell.mk +util.c +var.c +wait.h Index: vendor/NetBSD/bmake/20201101/Makefile =================================================================== --- vendor/NetBSD/bmake/20201101/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20201101/Makefile (revision 367461) @@ -0,0 +1,214 @@ +# $Id: Makefile,v 1.113 2020/10/26 17:55:09 sjg Exp $ + +PROG= bmake + +SRCS= \ + arch.c \ + buf.c \ + compat.c \ + cond.c \ + dir.c \ + enum.c \ + for.c \ + hash.c \ + job.c \ + lst.c \ + main.c \ + make.c \ + make_malloc.c \ + meta.c \ + metachar.c \ + parse.c \ + str.c \ + suff.c \ + targ.c \ + trace.c \ + util.c \ + var.c + +.-include "VERSION" +.-include "Makefile.inc" + +# this file gets generated by configure +.-include "Makefile.config" + +.if !empty(LIBOBJS) +SRCS+= ${LIBOBJS:T:.o=.c} +.endif + +# just in case +prefix?= /usr +srcdir?= ${.CURDIR} + +DEFAULT_SYS_PATH?= ${prefix}/share/mk + +CPPFLAGS+= -DUSE_META +CFLAGS+= ${CPPFLAGS} +CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\" +CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE +CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}} +COPTS.main.c+= "-DMAKE_VERSION=\"${_MAKE_VERSION}\"" + +# meta mode can be useful even without filemon +# should be set by now +USE_FILEMON ?= no +.if ${USE_FILEMON:tl} != "no" +.PATH: ${srcdir}/filemon +SRCS+= filemon_${USE_FILEMON}.c +COPTS.meta.c+= -DUSE_FILEMON -DUSE_FILEMON_${USE_FILEMON:tu} +COPTS.job.c+= ${COPTS.meta.c} + +.if ${USE_FILEMON} == "dev" +FILEMON_H ?= /usr/include/dev/filemon/filemon.h +.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h" +COPTS.filemon_dev.c += -DHAVE_FILEMON_H -I${FILEMON_H:H} +.endif +.endif # USE_FILEMON == dev + +.endif # USE_FILEMON + +.PATH: ${srcdir} + +.if make(obj) || make(clean) +SUBDIR+= unit-tests +.endif + +# start-delete1 for bsd.after-import.mk +# we skip a lot of this when building as part of FreeBSD etc. + +# list of OS's which are derrived from BSD4.4 +BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly MirBSD Bitrig +# we are... +OS := ${.MAKE.OS:U${uname -s:L:sh}} +# are we 4.4BSD ? +isBSD44:=${BSD44_LIST:M${OS}} + +.if ${isBSD44} == "" +MANTARGET= cat +INSTALL?=${srcdir}/install-sh +.if (${MACHINE} == "sun386") +# even I don't have one of these anymore :-) +CFLAGS+= -DPORTAR +.elif (${MACHINE} != "sunos") +SRCS+= sigcompat.c +CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART +.endif +.else +MANTARGET?= man +.endif + +# turn this on by default - ignored if we are root +WITH_INSTALL_AS_USER= + +# suppress with -DWITHOUT_* +OPTIONS_DEFAULT_YES+= \ + AUTOCONF_MK \ + INSTALL_MK \ + PROG_LINK + +OPTIONS_DEFAULT_NO+= \ + PROG_VERSION + +# process options now +.include + +.if ${MK_PROG_VERSION} == "yes" +PROG_NAME= ${PROG}-${_MAKE_VERSION} +.if ${MK_PROG_LINK} == "yes" +SYMLINKS+= ${PROG_NAME} ${BINDIR}/${PROG} +.endif +.endif + +EXTRACT_MAN=no +# end-delete1 + +MAN= ${PROG}.1 +MAN1= ${MAN} + +.if (${PROG} != "make") +CLEANFILES+= my.history +.if make(${MAN}) || !exists(${srcdir}/${MAN}) +my.history: + @(echo ".Nm"; \ + echo "is derived from NetBSD"; \ + echo ".Xr make 1 ."; \ + echo "It uses autoconf to facilitate portability to other platforms."; \ + echo ".Pp") > $@ + +.NOPATH: ${MAN} +${MAN}: make.1 my.history + @echo making $@ + @sed \ + -e '/^.Dt/s/MAKE/${PROG:tu}/' \ + -e 's/^.Nx/NetBSD/' \ + -e '/^.Nm/s/make/${PROG}/' \ + -e '/^.Sh HISTORY/rmy.history' \ + -e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@ + +all beforeinstall: ${MAN} +_mfromdir=. +.endif +.endif + +MANTARGET?= cat +MANDEST?= ${MANDIR}/${MANTARGET}1 + +.if ${MANTARGET} == "cat" +_mfromdir=${srcdir} +.endif + +.include + +CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H +COPTS.var.c += -Wno-cast-qual +COPTS.job.c += -Wno-format-nonliteral +COPTS.parse.c += -Wno-format-nonliteral +COPTS.var.c += -Wno-format-nonliteral + +# Force these +SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share} +BINDIR= ${BINDIR.bmake:U${prefix}/bin} +MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man} + +.if !exists(.depend) +${OBJS}: config.h +.endif + +# start-delete2 for bsd.after-import.mk + +# make sure that MAKE_VERSION gets updated. +main.o: ${srcdir}/VERSION + +.if ${MK_AUTOCONF_MK} == "yes" +CONFIGURE_DEPS += ${.CURDIR}/VERSION +# we do not need or want the generated makefile +CONFIGURE_ARGS += --without-makefile +.include +.endif +SHARE_MK?=${SHAREDIR}/mk +MKSRC=${srcdir}/mk +INSTALL?=${srcdir}/install-sh + +.if ${MK_INSTALL_MK} == "yes" +install: install-mk +.endif + +beforeinstall: + test -d ${DESTDIR}${BINDIR} || ${INSTALL} -m 775 -d ${DESTDIR}${BINDIR} + test -d ${DESTDIR}${MANDEST} || ${INSTALL} -m 775 -d ${DESTDIR}${MANDEST} + +install-mk: +.if exists(${MKSRC}/install-mk) + test -d ${DESTDIR}${SHARE_MK} || ${INSTALL} -m 775 -d ${DESTDIR}${SHARE_MK} + sh ${MKSRC}/install-mk -v -m 644 ${DESTDIR}${SHARE_MK} +.else + @echo need to unpack mk.tar.gz under ${srcdir} or set MKSRC; false +.endif +# end-delete2 + +# A simple unit-test driver to help catch regressions +TEST_MAKE ?= ${.OBJDIR}/${PROG:T} +accept test: + cd ${.CURDIR}/unit-tests && \ + MAKEFLAGS= ${TEST_MAKE} -r -m / ${.TARGET} ${TESTS:DTESTS=${TESTS:Q}} + Property changes on: vendor/NetBSD/bmake/20201101/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/VERSION =================================================================== --- vendor/NetBSD/bmake/20201101/VERSION (nonexistent) +++ vendor/NetBSD/bmake/20201101/VERSION (revision 367461) @@ -0,0 +1,2 @@ +# keep this compatible with sh and make +_MAKE_VERSION=20201101 Index: vendor/NetBSD/bmake/20201101/arch.c =================================================================== --- vendor/NetBSD/bmake/20201101/arch.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/arch.c (revision 367461) @@ -0,0 +1,1158 @@ +/* $NetBSD: arch.c,v 1.151 2020/10/31 18:41:07 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * arch.c -- + * Functions to manipulate libraries, archives and their members. + * + * Once again, cacheing/hashing comes into play in the manipulation + * of archives. The first time an archive is referenced, all of its members' + * headers are read and hashed and the archive closed again. All hashed + * archives are kept on a list which is searched each time an archive member + * is referenced. + * + * The interface to this module is: + * Arch_ParseArchive + * Given an archive specification, return a list + * of GNode's, one for each member in the spec. + * FALSE is returned if the specification is + * invalid for some reason. + * + * Arch_Touch Alter the modification time of the archive + * member described by the given node to be + * the current time. + * + * Arch_TouchLib Update the modification time of the library + * described by the given node. This is special + * because it also updates the modification time + * of the library's table of contents. + * + * Arch_MTime Find the modification time of a member of + * an archive *in the archive*. The time is also + * placed in the member's GNode. Returns the + * modification time. + * + * Arch_MemTime Find the modification time of a member of + * an archive. Called when the member doesn't + * already exist. Looks in the archive for the + * modification time. Returns the modification + * time. + * + * Arch_FindLib Search for a library along a path. The + * library name in the GNode should be in + * -l format. + * + * Arch_LibOODate Special function to decide if a library node + * is out-of-date. + * + * Arch_Init Initialize this module. + * + * Arch_End Clean up this module. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_AR_H +#include +#else +struct ar_hdr { + char ar_name[16]; /* name */ + char ar_date[12]; /* modification time */ + char ar_uid[6]; /* user id */ + char ar_gid[6]; /* group id */ + char ar_mode[8]; /* octal file permissions */ + char ar_size[10]; /* size in bytes */ +#ifndef ARFMAG +#define ARFMAG "`\n" +#endif + char ar_fmag[2]; /* consistency check */ +}; +#endif +#if defined(HAVE_RANLIB_H) && !(defined(__ELF__) || defined(NO_RANLIB)) +#include +#endif +#ifdef HAVE_UTIME_H +#include +#endif + +#include "make.h" +#include "dir.h" + +/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */ +MAKE_RCSID("$NetBSD: arch.c,v 1.151 2020/10/31 18:41:07 rillig Exp $"); + +#ifdef TARGET_MACHINE +#undef MAKE_MACHINE +#define MAKE_MACHINE TARGET_MACHINE +#endif +#ifdef TARGET_MACHINE_ARCH +#undef MAKE_MACHINE_ARCH +#define MAKE_MACHINE_ARCH TARGET_MACHINE_ARCH +#endif + +typedef struct List ArchList; +typedef struct ListNode ArchListNode; + +static ArchList *archives; /* The archives we've already examined */ + +typedef struct Arch { + char *name; /* Name of archive */ + HashTable members; /* All the members of the archive described + * by key/value pairs */ + char *fnametab; /* Extended name table strings */ + size_t fnamesize; /* Size of the string table */ +} Arch; + +static FILE *ArchFindMember(const char *, const char *, + struct ar_hdr *, const char *); +#if defined(__svr4__) || defined(__SVR4) || defined(__ELF__) +#define SVR4ARCHIVES +static int ArchSVR4Entry(Arch *, char *, size_t, FILE *); +#endif + + +#if defined(_AIX) +# define AR_NAME _ar_name.ar_name +# define AR_FMAG _ar_name.ar_fmag +# define SARMAG SAIAMAG +# define ARMAG AIAMAG +# define ARFMAG AIAFMAG +#endif +#ifndef AR_NAME +# define AR_NAME ar_name +#endif +#ifndef AR_DATE +# define AR_DATE ar_date +#endif +#ifndef AR_SIZE +# define AR_SIZE ar_size +#endif +#ifndef AR_FMAG +# define AR_FMAG ar_fmag +#endif +#ifndef ARMAG +# define ARMAG "!\n" +#endif +#ifndef SARMAG +# define SARMAG 8 +#endif + + +#ifdef CLEANUP +static void +ArchFree(void *ap) +{ + Arch *a = ap; + HashIter hi; + + /* Free memory from hash entries */ + HashIter_Init(&hi, &a->members); + while (HashIter_Next(&hi) != NULL) + free(hi.entry->value); + + free(a->name); + free(a->fnametab); + HashTable_Done(&a->members); + free(a); +} +#endif + + +/*- + *----------------------------------------------------------------------- + * Arch_ParseArchive -- + * Parse the archive specification in the given line and find/create + * the nodes for the specified archive members, placing their nodes + * on the given list. + * + * Input: + * linePtr Pointer to start of specification + * nodeLst Lst on which to place the nodes + * ctxt Context in which to expand variables + * + * Results: + * TRUE if it was a valid specification. The linePtr is updated + * to point to the first non-space after the archive spec. The + * nodes for the members are placed on the given list. + *----------------------------------------------------------------------- + */ +Boolean +Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, GNode *ctxt) +{ + char *cp; /* Pointer into line */ + GNode *gn; /* New node */ + char *libName; /* Library-part of specification */ + char *memName; /* Member-part of specification */ + char saveChar; /* Ending delimiter of member-name */ + Boolean subLibName; /* TRUE if libName should have/had + * variable substitution performed on it */ + + libName = *linePtr; + + subLibName = FALSE; + + for (cp = libName; *cp != '(' && *cp != '\0';) { + if (*cp == '$') { + /* + * Variable spec, so call the Var module to parse the puppy + * so we can safely advance beyond it... + */ + const char *nested_p = cp; + void *result_freeIt; + const char *result; + Boolean isError; + + (void)Var_Parse(&nested_p, ctxt, VARE_UNDEFERR|VARE_WANTRES, + &result, &result_freeIt); + /* TODO: handle errors */ + isError = result == var_Error; + free(result_freeIt); + if (isError) + return FALSE; + + subLibName = TRUE; + cp += nested_p - cp; + } else + cp++; + } + + *cp++ = '\0'; + if (subLibName) { + (void)Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES, &libName); + /* TODO: handle errors */ + } + + + for (;;) { + /* + * First skip to the start of the member's name, mark that + * place and skip to the end of it (either white-space or + * a close paren). + */ + Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ + + pp_skip_whitespace(&cp); + + memName = cp; + while (*cp != '\0' && *cp != ')' && !ch_isspace(*cp)) { + if (*cp == '$') { + /* + * Variable spec, so call the Var module to parse the puppy + * so we can safely advance beyond it... + */ + void *freeIt; + const char *result; + Boolean isError; + const char *nested_p = cp; + + (void)Var_Parse(&nested_p, ctxt, VARE_UNDEFERR|VARE_WANTRES, + &result, &freeIt); + /* TODO: handle errors */ + isError = result == var_Error; + free(freeIt); + + if (isError) + return FALSE; + + doSubst = TRUE; + cp += nested_p - cp; + } else { + cp++; + } + } + + /* + * If the specification ends without a closing parenthesis, + * chances are there's something wrong (like a missing backslash), + * so it's better to return failure than allow such things to happen + */ + if (*cp == '\0') { + printf("No closing parenthesis in archive specification\n"); + return FALSE; + } + + /* + * If we didn't move anywhere, we must be done + */ + if (cp == memName) { + break; + } + + saveChar = *cp; + *cp = '\0'; + + /* + * XXX: This should be taken care of intelligently by + * SuffExpandChildren, both for the archive and the member portions. + */ + /* + * If member contains variables, try and substitute for them. + * This will slow down archive specs with dynamic sources, of course, + * since we'll be (non-)substituting them three times, but them's + * the breaks -- we need to do this since SuffExpandChildren calls + * us, otherwise we could assume the thing would be taken care of + * later. + */ + if (doSubst) { + char *buf; + char *sacrifice; + char *oldMemName = memName; + + (void)Var_Subst(memName, ctxt, VARE_UNDEFERR|VARE_WANTRES, + &memName); + /* TODO: handle errors */ + + /* + * Now form an archive spec and recurse to deal with nested + * variables and multi-word variable values.... The results + * are just placed at the end of the nodeLst we're returning. + */ + buf = sacrifice = str_concat4(libName, "(", memName, ")"); + + if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { + /* + * Must contain dynamic sources, so we can't deal with it now. + * Just create an ARCHV node for the thing and let + * SuffExpandChildren handle it... + */ + gn = Targ_GetNode(buf); + gn->type |= OP_ARCHV; + Lst_Append(nodeLst, gn); + + } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { + /* Error in nested call. */ + free(buf); + return FALSE; + } + free(buf); + + } else if (Dir_HasWildcards(memName)) { + StringList *members = Lst_New(); + Dir_Expand(memName, dirSearchPath, members); + + while (!Lst_IsEmpty(members)) { + char *member = Lst_Dequeue(members); + char *fullname = str_concat4(libName, "(", member, ")"); + free(member); + + gn = Targ_GetNode(fullname); + free(fullname); + + gn->type |= OP_ARCHV; + Lst_Append(nodeLst, gn); + } + Lst_Free(members); + + } else { + char *fullname = str_concat4(libName, "(", memName, ")"); + gn = Targ_GetNode(fullname); + free(fullname); + + /* + * We've found the node, but have to make sure the rest of the + * world knows it's an archive member, without having to + * constantly check for parentheses, so we type the thing with + * the OP_ARCHV bit before we place it on the end of the + * provided list. + */ + gn->type |= OP_ARCHV; + Lst_Append(nodeLst, gn); + } + if (doSubst) { + free(memName); + } + + *cp = saveChar; + } + + /* + * If substituted libName, free it now, since we need it no longer. + */ + if (subLibName) { + free(libName); + } + + cp++; /* skip the ')' */ + /* We promised that linePtr would be set up at the next non-space. */ + pp_skip_whitespace(&cp); + *linePtr = cp; + return TRUE; +} + +/* Locate a member of an archive, given the path of the archive and the path + * of the desired member. + * + * Input: + * archive Path to the archive + * member Name of member; only its basename is used. + * hash TRUE if archive should be hashed if not already so. + * + * Results: + * The ar_hdr for the member. + */ +static struct ar_hdr * +ArchStatMember(const char *archive, const char *member, Boolean hash) +{ +#define AR_MAX_NAME_LEN (sizeof(arh.AR_NAME) - 1) + FILE *arch; /* Stream to archive */ + size_t size; /* Size of archive member */ + char magic[SARMAG]; + ArchListNode *ln; + Arch *ar; /* Archive descriptor */ + struct ar_hdr arh; /* archive-member header for reading archive */ + char memName[MAXPATHLEN + 1]; + /* Current member name while hashing. */ + + /* + * Because of space constraints and similar things, files are archived + * using their basename, not the entire path. + */ + const char *lastSlash = strrchr(member, '/'); + if (lastSlash != NULL) + member = lastSlash + 1; + + for (ln = archives->first; ln != NULL; ln = ln->next) { + const Arch *archPtr = ln->datum; + if (strcmp(archPtr->name, archive) == 0) + break; + } + + if (ln != NULL) { + struct ar_hdr *hdr; + + ar = ln->datum; + hdr = HashTable_FindValue(&ar->members, member); + if (hdr != NULL) + return hdr; + + { + /* Try truncated name */ + char copy[AR_MAX_NAME_LEN + 1]; + size_t len = strlen(member); + + if (len > AR_MAX_NAME_LEN) { + len = AR_MAX_NAME_LEN; + snprintf(copy, sizeof copy, "%s", member); + } + hdr = HashTable_FindValue(&ar->members, copy); + return hdr; + } + } + + if (!hash) { + /* + * Caller doesn't want the thing hashed, just use ArchFindMember + * to read the header for the member out and close down the stream + * again. Since the archive is not to be hashed, we assume there's + * no need to allocate extra room for the header we're returning, + * so just declare it static. + */ + static struct ar_hdr sarh; + + arch = ArchFindMember(archive, member, &sarh, "r"); + if (arch == NULL) + return NULL; + + fclose(arch); + return &sarh; + } + + /* + * We don't have this archive on the list yet, so we want to find out + * everything that's in it and cache it so we can get at it quickly. + */ + arch = fopen(archive, "r"); + if (arch == NULL) + return NULL; + + /* + * We use the ARMAG string to make sure this is an archive we + * can handle... + */ + if ((fread(magic, SARMAG, 1, arch) != 1) || + (strncmp(magic, ARMAG, SARMAG) != 0)) { + fclose(arch); + return NULL; + } + + ar = bmake_malloc(sizeof(Arch)); + ar->name = bmake_strdup(archive); + ar->fnametab = NULL; + ar->fnamesize = 0; + HashTable_Init(&ar->members); + memName[AR_MAX_NAME_LEN] = '\0'; + + while (fread((char *)&arh, sizeof(struct ar_hdr), 1, arch) == 1) { + if (strncmp(arh.AR_FMAG, ARFMAG, sizeof(arh.AR_FMAG)) != 0) { + /* + * The header is bogus, so the archive is bad + * and there's no way we can recover... + */ + goto badarch; + } else { + char *nameend; + + /* + * We need to advance the stream's pointer to the start of the + * next header. Files are padded with newlines to an even-byte + * boundary, so we need to extract the size of the file from the + * 'size' field of the header and round it up during the seek. + */ + arh.AR_SIZE[sizeof(arh.AR_SIZE) - 1] = '\0'; + size = (size_t)strtol(arh.ar_size, NULL, 10); + + memcpy(memName, arh.AR_NAME, sizeof(arh.AR_NAME)); + nameend = memName + AR_MAX_NAME_LEN; + while (*nameend == ' ') { + nameend--; + } + nameend[1] = '\0'; + +#ifdef SVR4ARCHIVES + /* + * svr4 names are slash terminated. Also svr4 extended AR format. + */ + if (memName[0] == '/') { + /* + * svr4 magic mode; handle it + */ + switch (ArchSVR4Entry(ar, memName, size, arch)) { + case -1: /* Invalid data */ + goto badarch; + case 0: /* List of files entry */ + continue; + default: /* Got the entry */ + break; + } + } else { + if (nameend[0] == '/') + nameend[0] = '\0'; + } +#endif + +#ifdef AR_EFMT1 + /* + * BSD 4.4 extended AR format: #1/, with name as the + * first bytes of the file + */ + if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && + ch_isdigit(memName[sizeof(AR_EFMT1) - 1])) { + + int elen = atoi(&memName[sizeof(AR_EFMT1) - 1]); + + if ((unsigned int)elen > MAXPATHLEN) + goto badarch; + if (fread(memName, (size_t)elen, 1, arch) != 1) + goto badarch; + memName[elen] = '\0'; + if (fseek(arch, -elen, SEEK_CUR) != 0) + goto badarch; + if (DEBUG(ARCH) || DEBUG(MAKE)) { + debug_printf("ArchStat: Extended format entry for %s\n", + memName); + } + } +#endif + + { + HashEntry *he; + he = HashTable_CreateEntry(&ar->members, memName, NULL); + HashEntry_Set(he, bmake_malloc(sizeof(struct ar_hdr))); + memcpy(HashEntry_Get(he), &arh, sizeof(struct ar_hdr)); + } + } + if (fseek(arch, ((long)size + 1) & ~1, SEEK_CUR) != 0) + goto badarch; + } + + fclose(arch); + + Lst_Append(archives, ar); + + /* + * Now that the archive has been read and cached, we can look into + * the hash table to find the desired member's header. + */ + return HashTable_FindValue(&ar->members, member); + +badarch: + fclose(arch); + HashTable_Done(&ar->members); + free(ar->fnametab); + free(ar); + return NULL; +} + +#ifdef SVR4ARCHIVES +/*- + *----------------------------------------------------------------------- + * ArchSVR4Entry -- + * Parse an SVR4 style entry that begins with a slash. + * If it is "//", then load the table of filenames + * If it is "/", then try to substitute the long file name + * from offset of a table previously read. + * If a table is read, the file pointer is moved to the next archive + * member. + * + * Results: + * -1: Bad data in archive + * 0: A table was loaded from the file + * 1: Name was successfully substituted from table + * 2: Name was not successfully substituted from table + *----------------------------------------------------------------------- + */ +static int +ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch) +{ +#define ARLONGNAMES1 "//" +#define ARLONGNAMES2 "/ARFILENAMES" + size_t entry; + char *ptr, *eptr; + + if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || + strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { + + if (ar->fnametab != NULL) { + DEBUG0(ARCH, "Attempted to redefine an SVR4 name table\n"); + return -1; + } + + /* + * This is a table of archive names, so we build one for + * ourselves + */ + ar->fnametab = bmake_malloc(size); + ar->fnamesize = size; + + if (fread(ar->fnametab, size, 1, arch) != 1) { + DEBUG0(ARCH, "Reading an SVR4 name table failed\n"); + return -1; + } + eptr = ar->fnametab + size; + for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++) + if (*ptr == '/') { + entry++; + *ptr = '\0'; + } + DEBUG1(ARCH, "Found svr4 archive name table with %lu entries\n", + (unsigned long)entry); + return 0; + } + + if (name[1] == ' ' || name[1] == '\0') + return 2; + + entry = (size_t)strtol(&name[1], &eptr, 0); + if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) { + DEBUG1(ARCH, "Could not parse SVR4 name %s\n", name); + return 2; + } + if (entry >= ar->fnamesize) { + DEBUG2(ARCH, "SVR4 entry offset %s is greater than %lu\n", + name, (unsigned long)ar->fnamesize); + return 2; + } + + DEBUG2(ARCH, "Replaced %s with %s\n", name, &ar->fnametab[entry]); + + snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]); + return 1; +} +#endif + + +/*- + *----------------------------------------------------------------------- + * ArchFindMember -- + * Locate a member of an archive, given the path of the archive and + * the path of the desired member. If the archive is to be modified, + * the mode should be "r+", if not, it should be "r". + * The passed struct ar_hdr structure is filled in. + * + * Input: + * archive Path to the archive + * member Name of member. If it is a path, only the last + * component is used. + * arhPtr Pointer to header structure to be filled in + * mode The mode for opening the stream + * + * Results: + * An FILE *, opened for reading and writing, positioned at the + * start of the member's struct ar_hdr, or NULL if the member was + * nonexistent. The current struct ar_hdr for member. + *----------------------------------------------------------------------- + */ +static FILE * +ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr, + const char *mode) +{ + FILE *arch; /* Stream to archive */ + int size; /* Size of archive member */ + char magic[SARMAG]; + size_t len, tlen; + const char *lastSlash; + + arch = fopen(archive, mode); + if (arch == NULL) + return NULL; + + /* + * We use the ARMAG string to make sure this is an archive we + * can handle... + */ + if ((fread(magic, SARMAG, 1, arch) != 1) || + (strncmp(magic, ARMAG, SARMAG) != 0)) { + fclose(arch); + return NULL; + } + + /* + * Because of space constraints and similar things, files are archived + * using their basename, not the entire path. + */ + lastSlash = strrchr(member, '/'); + if (lastSlash != NULL) + member = lastSlash + 1; + + len = tlen = strlen(member); + if (len > sizeof(arhPtr->AR_NAME)) { + tlen = sizeof(arhPtr->AR_NAME); + } + + while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) { + + if (strncmp(arhPtr->AR_FMAG, ARFMAG, sizeof(arhPtr->AR_FMAG)) != 0) { + /* + * The header is bogus, so the archive is bad + * and there's no way we can recover... + */ + fclose(arch); + return NULL; + } + + if (strncmp(member, arhPtr->AR_NAME, tlen) == 0) { + /* + * If the member's name doesn't take up the entire 'name' field, + * we have to be careful of matching prefixes. Names are space- + * padded to the right, so if the character in 'name' at the end + * of the matched string is anything but a space, this isn't the + * member we sought. + */ + if (tlen != sizeof arhPtr->AR_NAME && arhPtr->AR_NAME[tlen] != ' ') + goto skip; + + /* + * To make life easier, we reposition the file at the start + * of the header we just read before we return the stream. + * In a more general situation, it might be better to leave + * the file at the actual member, rather than its header, but + * not here... + */ + if (fseek(arch, -(long)sizeof(struct ar_hdr), SEEK_CUR) != 0) { + fclose(arch); + return NULL; + } + return arch; + } + +#ifdef AR_EFMT1 + /* + * BSD 4.4 extended AR format: #1/, with name as the + * first bytes of the file + */ + if (strncmp(arhPtr->AR_NAME, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && + ch_isdigit(arhPtr->AR_NAME[sizeof(AR_EFMT1) - 1])) + { + int elen = atoi(&arhPtr->AR_NAME[sizeof(AR_EFMT1) - 1]); + char ename[MAXPATHLEN + 1]; + + if ((unsigned int)elen > MAXPATHLEN) { + fclose(arch); + return NULL; + } + if (fread(ename, (size_t)elen, 1, arch) != 1) { + fclose(arch); + return NULL; + } + ename[elen] = '\0'; + if (DEBUG(ARCH) || DEBUG(MAKE)) { + debug_printf("ArchFind: Extended format entry for %s\n", ename); + } + if (strncmp(ename, member, len) == 0) { + /* Found as extended name */ + if (fseek(arch, -(long)sizeof(struct ar_hdr) - elen, + SEEK_CUR) != 0) { + fclose(arch); + return NULL; + } + return arch; + } + if (fseek(arch, -elen, SEEK_CUR) != 0) { + fclose(arch); + return NULL; + } + } +#endif + +skip: + /* + * This isn't the member we're after, so we need to advance the + * stream's pointer to the start of the next header. Files are + * padded with newlines to an even-byte boundary, so we need to + * extract the size of the file from the 'size' field of the + * header and round it up during the seek. + */ + arhPtr->ar_size[sizeof(arhPtr->ar_size) - 1] = '\0'; + size = (int)strtol(arhPtr->ar_size, NULL, 10); + if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) { + fclose(arch); + return NULL; + } + } + + /* + * We've looked everywhere, but the member is not to be found. Close the + * archive and return NULL -- an error. + */ + fclose(arch); + return NULL; +} + +/*- + *----------------------------------------------------------------------- + * Arch_Touch -- + * Touch a member of an archive. + * The modification time of the entire archive is also changed. + * For a library, this could necessitate the re-ranlib'ing of the + * whole thing. + * + * Input: + * gn Node of member to touch + * + * Results: + * The 'time' field of the member's header is updated. + *----------------------------------------------------------------------- + */ +void +Arch_Touch(GNode *gn) +{ + FILE *arch; /* Stream open to archive, positioned properly */ + struct ar_hdr arh; /* Current header describing member */ + + arch = ArchFindMember(GNode_VarArchive(gn), GNode_VarMember(gn), + &arh, "r+"); + + snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long)now); + + if (arch != NULL) { + (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); + fclose(arch); + } +} + +/* Given a node which represents a library, touch the thing, making sure that + * the table of contents also is touched. + * + * Both the modification time of the library and of the RANLIBMAG member are + * set to 'now'. + * + * Input: + * gn The node of the library to touch + */ +void +Arch_TouchLib(GNode *gn) +{ +#ifdef RANLIBMAG + FILE * arch; /* Stream open to archive */ + struct ar_hdr arh; /* Header describing table of contents */ + struct utimbuf times; /* Times for utime() call */ + + arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+"); + snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now); + + if (arch != NULL) { + (void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch); + fclose(arch); + + times.actime = times.modtime = now; + utime(gn->path, ×); + } +#else + (void)gn; +#endif +} + +/* Return the modification time of a member of an archive. The mtime field + * of the given node is filled in with the value returned by the function. + * + * Input: + * gn Node describing archive member + */ +time_t +Arch_MTime(GNode *gn) +{ + struct ar_hdr *arhPtr; /* Header of desired member */ + time_t modTime; /* Modification time as an integer */ + + arhPtr = ArchStatMember(GNode_VarArchive(gn), GNode_VarMember(gn), TRUE); + if (arhPtr != NULL) { + modTime = (time_t)strtol(arhPtr->AR_DATE, NULL, 10); + } else { + modTime = 0; + } + + gn->mtime = modTime; + return modTime; +} + +/* Given a non-existent archive member's node, get its modification time from + * its archived form, if it exists. gn->mtime is filled in as well. */ +time_t +Arch_MemMTime(GNode *gn) +{ + GNodeListNode *ln; + + for (ln = gn->parents->first; ln != NULL; ln = ln->next) { + GNode *pgn = ln->datum; + + if (pgn->type & OP_ARCHV) { + /* + * If the parent is an archive specification and is being made + * and its member's name matches the name of the node we were + * given, record the modification time of the parent in the + * child. We keep searching its parents in case some other + * parent requires this child to exist... + */ + const char *nameStart = strchr(pgn->name, '(') + 1; + const char *nameEnd = strchr(nameStart, ')'); + size_t nameLen = (size_t)(nameEnd - nameStart); + + if ((pgn->flags & REMAKE) && + strncmp(nameStart, gn->name, nameLen) == 0) { + gn->mtime = Arch_MTime(pgn); + } + } else if (pgn->flags & REMAKE) { + /* + * Something which isn't a library depends on the existence of + * this target, so it needs to exist. + */ + gn->mtime = 0; + break; + } + } + + return gn->mtime; +} + +/* Search for a library along the given search path. + * + * The node's 'path' field is set to the found path (including the + * actual file name, not -l...). If the system can handle the -L + * flag when linking (or we cannot find the library), we assume that + * the user has placed the .LIBS variable in the final linking + * command (or the linker will know where to find it) and set the + * TARGET variable for this node to be the node's name. Otherwise, + * we set the TARGET variable to be the full path of the library, + * as returned by Dir_FindFile. + * + * Input: + * gn Node of library to find + */ +void +Arch_FindLib(GNode *gn, SearchPath *path) +{ + char *libName = str_concat3("lib", gn->name + 2, ".a"); + gn->path = Dir_FindFile(libName, path); + free(libName); + +#ifdef LIBRARIES + Var_Set(TARGET, gn->name, gn); +#else + Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn); +#endif +} + +/* Decide if a node with the OP_LIB attribute is out-of-date. Called from + * Make_OODate to make its life easier. + * The library will be hashed if it hasn't been already. + * + * There are several ways for a library to be out-of-date that are + * not available to ordinary files. In addition, there are ways + * that are open to regular files that are not available to + * libraries. A library that is only used as a source is never + * considered out-of-date by itself. This does not preclude the + * library's modification time from making its parent be out-of-date. + * A library will be considered out-of-date for any of these reasons, + * given that it is a target on a dependency line somewhere: + * + * Its modification time is less than that of one of its sources + * (gn->mtime < gn->youngestChild->mtime). + * + * Its modification time is greater than the time at which the make + * began (i.e. it's been modified in the course of the make, probably + * by archiving). + * + * The modification time of one of its sources is greater than the one + * of its RANLIBMAG member (i.e. its table of contents is out-of-date). + * We don't compare of the archive time vs. TOC time because they can be + * too close. In my opinion we should not bother with the TOC at all + * since this is used by 'ar' rules that affect the data contents of the + * archive, not by ranlib rules, which affect the TOC. + * + * Input: + * gn The library's graph node + * + * Results: + * TRUE if the library is out-of-date. FALSE otherwise. + */ +Boolean +Arch_LibOODate(GNode *gn) +{ + Boolean oodate; + + if (gn->type & OP_PHONY) { + oodate = TRUE; + } else if (!GNode_IsTarget(gn) && Lst_IsEmpty(gn->children)) { + oodate = FALSE; + } else if ((!Lst_IsEmpty(gn->children) && gn->youngestChild == NULL) || + (gn->mtime > now) || + (gn->youngestChild != NULL && + gn->mtime < gn->youngestChild->mtime)) { + oodate = TRUE; + } else { +#ifdef RANLIBMAG + struct ar_hdr *arhPtr; /* Header for __.SYMDEF */ + int modTimeTOC; /* The table-of-contents's mod time */ + + arhPtr = ArchStatMember(gn->path, RANLIBMAG, FALSE); + + if (arhPtr != NULL) { + modTimeTOC = (int)strtol(arhPtr->AR_DATE, NULL, 10); + + if (DEBUG(ARCH) || DEBUG(MAKE)) { + debug_printf("%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); + } + oodate = (gn->youngestChild == NULL || gn->youngestChild->mtime > modTimeTOC); + } else { + /* + * A library w/o a table of contents is out-of-date + */ + if (DEBUG(ARCH) || DEBUG(MAKE)) { + debug_printf("No t.o.c...."); + } + oodate = TRUE; + } +#else + oodate = FALSE; +#endif + } + return oodate; +} + +/* Initialize the archives module. */ +void +Arch_Init(void) +{ + archives = Lst_New(); +} + +/* Clean up the archives module. */ +void +Arch_End(void) +{ +#ifdef CLEANUP + Lst_Destroy(archives, ArchFree); +#endif +} + +Boolean +Arch_IsLib(GNode *gn) +{ + static const char armag[] = "!\n"; + char buf[sizeof armag - 1]; + int fd; + + if ((fd = open(gn->path, O_RDONLY)) == -1) + return FALSE; + + if (read(fd, buf, sizeof buf) != sizeof buf) { + (void)close(fd); + return FALSE; + } + + (void)close(fd); + + return memcmp(buf, armag, sizeof buf) == 0; +} Property changes on: vendor/NetBSD/bmake/20201101/arch.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/bmake.1 =================================================================== --- vendor/NetBSD/bmake/20201101/bmake.1 (nonexistent) +++ vendor/NetBSD/bmake/20201101/bmake.1 (revision 367461) @@ -0,0 +1,2455 @@ +.\" $NetBSD: make.1,v 1.290 2020/11/01 20:24:45 rillig Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. 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. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 +.\" +.Dd November 1, 2020 +.Dt BMAKE 1 +.Os +.Sh NAME +.Nm bmake +.Nd maintain program dependencies +.Sh SYNOPSIS +.Nm +.Op Fl BeikNnqrstWwX +.Op Fl C Ar directory +.Op Fl D Ar variable +.Op Fl d Ar flags +.Op Fl f Ar makefile +.Op Fl I Ar directory +.Op Fl J Ar private +.Op Fl j Ar max_jobs +.Op Fl m Ar directory +.Op Fl T Ar file +.Op Fl V Ar variable +.Op Fl v Ar variable +.Op Ar variable=value +.Op Ar target ... +.Sh DESCRIPTION +.Nm +is a program designed to simplify the maintenance of other programs. +Its input is a list of specifications as to the files upon which programs +and other files depend. +If no +.Fl f Ar makefile +makefile option is given, +.Nm +will try to open +.Ql Pa makefile +then +.Ql Pa Makefile +in order to find the specifications. +If the file +.Ql Pa .depend +exists, it is read (see +.Xr mkdep 1 ) . +.Pp +This manual page is intended as a reference document only. +For a more thorough description of +.Nm +and makefiles, please refer to +.%T "PMake \- A Tutorial" . +.Pp +.Nm +will prepend the contents of the +.Va MAKEFLAGS +environment variable to the command line arguments before parsing them. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl B +Try to be backwards compatible by executing a single shell per command and +by executing the commands to make the sources of a dependency line in sequence. +.It Fl C Ar directory +Change to +.Ar directory +before reading the makefiles or doing anything else. +If multiple +.Fl C +options are specified, each is interpreted relative to the previous one: +.Fl C Pa / Fl C Pa etc +is equivalent to +.Fl C Pa /etc . +.It Fl D Ar variable +Define +.Ar variable +to be 1, in the global context. +.It Fl d Ar [-]flags +Turn on debugging, and specify which portions of +.Nm +are to print debugging information. +Unless the flags are preceded by +.Ql \- +they are added to the +.Va MAKEFLAGS +environment variable and will be processed by any child make processes. +By default, debugging information is printed to standard error, +but this can be changed using the +.Ar F +debugging flag. +The debugging output is always unbuffered; in addition, if debugging +is enabled but debugging output is not directed to standard output, +then the standard output is line buffered. +.Ar Flags +is one or more of the following: +.Bl -tag -width Ds +.It Ar A +Print all possible debugging information; +equivalent to specifying all of the debugging flags. +.It Ar a +Print debugging information about archive searching and caching. +.It Ar C +Print debugging information about current working directory. +.It Ar c +Print debugging information about conditional evaluation. +.It Ar d +Print debugging information about directory searching and caching. +.It Ar e +Print debugging information about failed commands and targets. +.It Ar F Ns Oo Sy \&+ Oc Ns Ar filename +Specify where debugging output is written. +This must be the last flag, because it consumes the remainder of +the argument. +If the character immediately after the +.Ql F +flag is +.Ql \&+ , +then the file will be opened in append mode; +otherwise the file will be overwritten. +If the file name is +.Ql stdout +or +.Ql stderr +then debugging output will be written to the +standard output or standard error output file descriptors respectively +(and the +.Ql \&+ +option has no effect). +Otherwise, the output will be written to the named file. +If the file name ends +.Ql .%d +then the +.Ql %d +is replaced by the pid. +.It Ar f +Print debugging information about loop evaluation. +.It Ar "g1" +Print the input graph before making anything. +.It Ar "g2" +Print the input graph after making everything, or before exiting +on error. +.It Ar "g3" +Print the input graph before exiting on error. +.It Ar h +Print debugging information about hash table operations. +.It Ar j +Print debugging information about running multiple shells. +.It Ar L +Turn on lint checks. +This will throw errors for variable assignments that do not parse +correctly, at the time of assignment so the file and line number +are available. +.It Ar l +Print commands in Makefiles regardless of whether or not they are prefixed by +.Ql @ +or other "quiet" flags. +Also known as "loud" behavior. +.It Ar M +Print debugging information about "meta" mode decisions about targets. +.It Ar m +Print debugging information about making targets, including modification +dates. +.It Ar n +Don't delete the temporary command scripts created when running commands. +These temporary scripts are created in the directory +referred to by the +.Ev TMPDIR +environment variable, or in +.Pa /tmp +if +.Ev TMPDIR +is unset or set to the empty string. +The temporary scripts are created by +.Xr mkstemp 3 , +and have names of the form +.Pa makeXXXXXX . +.Em NOTE : +This can create many files in +.Ev TMPDIR +or +.Pa /tmp , +so use with care. +.It Ar p +Print debugging information about makefile parsing. +.It Ar s +Print debugging information about suffix-transformation rules. +.It Ar t +Print debugging information about target list maintenance. +.It Ar V +Force the +.Fl V +option to print raw values of variables, overriding the default behavior +set via +.Va .MAKE.EXPAND_VARIABLES . +.It Ar v +Print debugging information about variable assignment. +.It Ar x +Run shell commands with +.Fl x +so the actual commands are printed as they are executed. +.El +.It Fl e +Specify that environment variables override macro assignments within +makefiles. +.It Fl f Ar makefile +Specify a makefile to read instead of the default +.Ql Pa makefile . +If +.Ar makefile +is +.Ql Fl , +standard input is read. +Multiple makefiles may be specified, and are read in the order specified. +.It Fl I Ar directory +Specify a directory in which to search for makefiles and included makefiles. +The system makefile directory (or directories, see the +.Fl m +option) is automatically included as part of this list. +.It Fl i +Ignore non-zero exit of shell commands in the makefile. +Equivalent to specifying +.Ql Fl +before each command line in the makefile. +.It Fl J Ar private +This option should +.Em not +be specified by the user. +.Pp +When the +.Ar j +option is in use in a recursive build, this option is passed by a make +to child makes to allow all the make processes in the build to +cooperate to avoid overloading the system. +.It Fl j Ar max_jobs +Specify the maximum number of jobs that +.Nm +may have running at any one time. +The value is saved in +.Va .MAKE.JOBS . +Turns compatibility mode off, unless the +.Ar B +flag is also specified. +When compatibility mode is off, all commands associated with a +target are executed in a single shell invocation as opposed to the +traditional one shell invocation per line. +This can break traditional scripts which change directories on each +command invocation and then expect to start with a fresh environment +on the next line. +It is more efficient to correct the scripts rather than turn backwards +compatibility on. +.It Fl k +Continue processing after errors are encountered, but only on those targets +that do not depend on the target whose creation caused the error. +.It Fl m Ar directory +Specify a directory in which to search for sys.mk and makefiles included +via the +.Li \&< Ns Ar file Ns Li \&> Ns -style +include statement. +The +.Fl m +option can be used multiple times to form a search path. +This path will override the default system include path: /usr/share/mk. +Furthermore the system include path will be appended to the search path used +for +.Li \*q Ns Ar file Ns Li \*q Ns -style +include statements (see the +.Fl I +option). +.Pp +If a file or directory name in the +.Fl m +argument (or the +.Ev MAKESYSPATH +environment variable) starts with the string +.Qq \&.../ +then +.Nm +will search for the specified file or directory named in the remaining part +of the argument string. +The search starts with the current directory of +the Makefile and then works upward towards the root of the file system. +If the search is successful, then the resulting directory replaces the +.Qq \&.../ +specification in the +.Fl m +argument. +If used, this feature allows +.Nm +to easily search in the current source tree for customized sys.mk files +(e.g., by using +.Qq \&.../mk/sys.mk +as an argument). +.It Fl n +Display the commands that would have been executed, but do not +actually execute them unless the target depends on the .MAKE special +source (see below) or the command is prefixed with +.Ql Ic + . +.It Fl N +Display the commands which would have been executed, but do not +actually execute any of them; useful for debugging top-level makefiles +without descending into subdirectories. +.It Fl q +Do not execute any commands, but exit 0 if the specified targets are +up-to-date and 1, otherwise. +.It Fl r +Do not use the built-in rules specified in the system makefile. +.It Fl s +Do not echo any commands as they are executed. +Equivalent to specifying +.Ql Ic @ +before each command line in the makefile. +.It Fl T Ar tracefile +When used with the +.Fl j +flag, +append a trace record to +.Ar tracefile +for each job started and completed. +.It Fl t +Rather than re-building a target as specified in the makefile, create it +or update its modification time to make it appear up-to-date. +.It Fl V Ar variable +Print the value of +.Ar variable . +Do not build any targets. +Multiple instances of this option may be specified; +the variables will be printed one per line, +with a blank line for each null or undefined variable. +The value printed is extracted from the global context after all +makefiles have been read. +By default, the raw variable contents (which may +include additional unexpanded variable references) are shown. +If +.Ar variable +contains a +.Ql \&$ +then the value will be recursively expanded to its complete resultant +text before printing. +The expanded value will also be printed if +.Va .MAKE.EXPAND_VARIABLES +is set to true and +the +.Fl dV +option has not been used to override it. +Note that loop-local and target-local variables, as well as values +taken temporarily by global variables during makefile processing, are +not accessible via this option. +The +.Fl dv +debug mode can be used to see these at the cost of generating +substantial extraneous output. +.It Fl v Ar variable +Like +.Fl V +but the variable is always expanded to its complete value. +.It Fl W +Treat any warnings during makefile parsing as errors. +.It Fl w +Print entering and leaving directory messages, pre and post processing. +.It Fl X +Don't export variables passed on the command line to the environment +individually. +Variables passed on the command line are still exported +via the +.Va MAKEFLAGS +environment variable. +This option may be useful on systems which have a small limit on the +size of command arguments. +.It Ar variable=value +Set the value of the variable +.Ar variable +to +.Ar value . +Normally, all values passed on the command line are also exported to +sub-makes in the environment. +The +.Fl X +flag disables this behavior. +Variable assignments should follow options for POSIX compatibility +but no ordering is enforced. +.El +.Pp +There are seven different types of lines in a makefile: file dependency +specifications, shell commands, variable assignments, include statements, +conditional directives, for loops, and comments. +.Pp +In general, lines may be continued from one line to the next by ending +them with a backslash +.Pq Ql \e . +The trailing newline character and initial whitespace on the following +line are compressed into a single space. +.Sh FILE DEPENDENCY SPECIFICATIONS +Dependency lines consist of one or more targets, an operator, and zero +or more sources. +This creates a relationship where the targets +.Dq depend +on the sources +and are customarily created from them. +A target is considered out-of-date if it does not exist, or if its +modification time is less than that of any of its sources. +An out-of-date target will be re-created, but not until all sources +have been examined and themselves re-created as needed. +Three operators may be used: +.Bl -tag -width flag +.It Ic \&: +Many dependency lines may name this target but only one may have +attached shell commands. +All sources named in all dependency lines are considered together, +and if needed the attached shell commands are run to create or +re-create the target. +If +.Nm +is interrupted, the target is removed. +.It Ic \&! +The same, but the target is always re-created whether or not it is out +of date. +.It Ic \&:: +Any dependency line may have attached shell commands, but each one +is handled independently: its sources are considered and the attached +shell commands are run if the target is out of date with respect to +(only) those sources. +Thus, different groups of the attached shell commands may be run +depending on the circumstances. +Furthermore, unlike +.Ic \&:, +for dependency lines with no sources, the attached shell +commands are always run. +Also unlike +.Ic \&:, +the target will not be removed if +.Nm +is interrupted. +.El +All dependency lines mentioning a particular target must use the same +operator. +.Pp +Targets and sources may contain the shell wildcard values +.Ql \&? , +.Ql * , +.Ql [] , +and +.Ql {} . +The values +.Ql \&? , +.Ql * , +and +.Ql [] +may only be used as part of the final +component of the target or source, and must be used to describe existing +files. +The value +.Ql {} +need not necessarily be used to describe existing files. +Expansion is in directory order, not alphabetically as done in the shell. +.Sh SHELL COMMANDS +Each target may have associated with it one or more lines of shell +commands, normally +used to create the target. +Each of the lines in this script +.Em must +be preceded by a tab. +(For historical reasons, spaces are not accepted.) +While targets can appear in many dependency lines if desired, by +default only one of these rules may be followed by a creation +script. +If the +.Ql Ic \&:: +operator is used, however, all rules may include scripts and the +scripts are executed in the order found. +.Pp +Each line is treated as a separate shell command, unless the end of +line is escaped with a backslash +.Pq Ql \e +in which case that line and the next are combined. +.\" The escaped newline is retained and passed to the shell, which +.\" normally ignores it. +.\" However, the tab at the beginning of the following line is removed. +If the first characters of the command are any combination of +.Ql Ic @ , +.Ql Ic + , +or +.Ql Ic \- , +the command is treated specially. +A +.Ql Ic @ +causes the command not to be echoed before it is executed. +A +.Ql Ic + +causes the command to be executed even when +.Fl n +is given. +This is similar to the effect of the .MAKE special source, +except that the effect can be limited to a single line of a script. +A +.Ql Ic \- +in compatibility mode +causes any non-zero exit status of the command line to be ignored. +.Pp +When +.Nm +is run in jobs mode with +.Fl j Ar max_jobs , +the entire script for the target is fed to a +single instance of the shell. +In compatibility (non-jobs) mode, each command is run in a separate process. +If the command contains any shell meta characters +.Pq Ql #=|^(){};&<>*?[]:$`\e\en +it will be passed to the shell; otherwise +.Nm +will attempt direct execution. +If a line starts with +.Ql Ic \- +and the shell has ErrCtl enabled then failure of the command line +will be ignored as in compatibility mode. +Otherwise +.Ql Ic \- +affects the entire job; +the script will stop at the first command line that fails, +but the target will not be deemed to have failed. +.Pp +Makefiles should be written so that the mode of +.Nm +operation does not change their behavior. +For example, any command which needs to use +.Dq cd +or +.Dq chdir +without potentially changing the directory for subsequent commands +should be put in parentheses so it executes in a subshell. +To force the use of one shell, escape the line breaks so as to make +the whole script one command. +For example: +.Bd -literal -offset indent +avoid-chdir-side-effects: + @echo Building $@ in `pwd` + @(cd ${.CURDIR} && ${MAKE} $@) + @echo Back in `pwd` + +ensure-one-shell-regardless-of-mode: + @echo Building $@ in `pwd`; \e + (cd ${.CURDIR} && ${MAKE} $@); \e + echo Back in `pwd` +.Ed +.Pp +Since +.Nm +will +.Xr chdir 2 +to +.Ql Va .OBJDIR +before executing any targets, each child process +starts with that as its current working directory. +.Sh VARIABLE ASSIGNMENTS +Variables in make are much like variables in the shell, and, by tradition, +consist of all upper-case letters. +.Ss Variable assignment modifiers +The five operators that can be used to assign values to variables are as +follows: +.Bl -tag -width Ds +.It Ic \&= +Assign the value to the variable. +Any previous value is overridden. +.It Ic \&+= +Append the value to the current value of the variable. +.It Ic \&?= +Assign the value to the variable if it is not already defined. +.It Ic \&:= +Assign with expansion, i.e. expand the value before assigning it +to the variable. +Normally, expansion is not done until the variable is referenced. +.Em NOTE : +References to undefined variables are +.Em not +expanded. +This can cause problems when variable modifiers are used. +.It Ic \&!= +Expand the value and pass it to the shell for execution and assign +the result to the variable. +Any newlines in the result are replaced with spaces. +.El +.Pp +Any white-space before the assigned +.Ar value +is removed; if the value is being appended, a single space is inserted +between the previous contents of the variable and the appended value. +.Pp +Variables are expanded by surrounding the variable name with either +curly braces +.Pq Ql {} +or parentheses +.Pq Ql () +and preceding it with +a dollar sign +.Pq Ql \&$ . +If the variable name contains only a single letter, the surrounding +braces or parentheses are not required. +This shorter form is not recommended. +.Pp +If the variable name contains a dollar, then the name itself is expanded first. +This allows almost arbitrary variable names, however names containing dollar, +braces, parentheses, or whitespace are really best avoided! +.Pp +If the result of expanding a variable contains a dollar sign +.Pq Ql \&$ +the string is expanded again. +.Pp +Variable substitution occurs at three distinct times, depending on where +the variable is being used. +.Bl -enum +.It +Variables in dependency lines are expanded as the line is read. +.It +Variables in shell commands are expanded when the shell command is +executed. +.It +.Dq .for +loop index variables are expanded on each loop iteration. +Note that other variables are not expanded inside loops so +the following example code: +.Bd -literal -offset indent + +.Dv .for i in 1 2 3 +a+= ${i} +j= ${i} +b+= ${j} +.Dv .endfor + +all: + @echo ${a} + @echo ${b} + +.Ed +will print: +.Bd -literal -offset indent +1 2 3 +3 3 3 + +.Ed +Because while ${a} contains +.Dq 1 2 3 +after the loop is executed, ${b} +contains +.Dq ${j} ${j} ${j} +which expands to +.Dq 3 3 3 +since after the loop completes ${j} contains +.Dq 3 . +.El +.Ss Variable classes +The four different classes of variables (in order of increasing precedence) +are: +.Bl -tag -width Ds +.It Environment variables +Variables defined as part of +.Nm Ns 's +environment. +.It Global variables +Variables defined in the makefile or in included makefiles. +.It Command line variables +Variables defined as part of the command line. +.It Local variables +Variables that are defined specific to a certain target. +.El +.Pp +Local variables are all built in and their values vary magically from +target to target. +It is not currently possible to define new local variables. +The seven local variables are as follows: +.Bl -tag -width ".ARCHIVE" -offset indent +.It Va .ALLSRC +The list of all sources for this target; also known as +.Ql Va \&> . +.It Va .ARCHIVE +The name of the archive file; also known as +.Ql Va \&! . +.It Va .IMPSRC +In suffix-transformation rules, the name/path of the source from which the +target is to be transformed (the +.Dq implied +source); also known as +.Ql Va \&< . +It is not defined in explicit rules. +.It Va .MEMBER +The name of the archive member; also known as +.Ql Va % . +.It Va .OODATE +The list of sources for this target that were deemed out-of-date; also +known as +.Ql Va \&? . +.It Va .PREFIX +The file prefix of the target, containing only the file portion, no suffix +or preceding directory components; also known as +.Ql Va * . +The suffix must be one of the known suffixes declared with +.Ic .SUFFIXES +or it will not be recognized. +.It Va .TARGET +The name of the target; also known as +.Ql Va @ . +For compatibility with other makes this is an alias for +.Ic .ARCHIVE +in archive member rules. +.El +.Pp +The shorter forms +.Ql ( Va > , +.Ql Va \&! , +.Ql Va < , +.Ql Va % , +.Ql Va \&? , +.Ql Va * , +and +.Ql Va @ ) +are permitted for backward +compatibility with historical makefiles and legacy POSIX make and are +not recommended. +.Pp +Variants of these variables with the punctuation followed immediately by +.Ql D +or +.Ql F , +e.g. +.Ql Va $(@D) , +are legacy forms equivalent to using the +.Ql :H +and +.Ql :T +modifiers. +These forms are accepted for compatibility with +.At V +makefiles and POSIX but are not recommended. +.Pp +Four of the local variables may be used in sources on dependency lines +because they expand to the proper value for each target on the line. +These variables are +.Ql Va .TARGET , +.Ql Va .PREFIX , +.Ql Va .ARCHIVE , +and +.Ql Va .MEMBER . +.Ss Additional built-in variables +In addition, +.Nm +sets or knows about the following variables: +.Bl -tag -width .MAKEOVERRIDES +.It Va \&$ +A single dollar sign +.Ql \&$ , +i.e. +.Ql \&$$ +expands to a single dollar +sign. +.It Va .ALLTARGETS +The list of all targets encountered in the Makefile. +If evaluated during +Makefile parsing, lists only those targets encountered thus far. +.It Va .CURDIR +A path to the directory where +.Nm +was executed. +Refer to the description of +.Ql Ev PWD +for more details. +.It Va .INCLUDEDFROMDIR +The directory of the file this Makefile was included from. +.It Va .INCLUDEDFROMFILE +The filename of the file this Makefile was included from. +.It Ev MAKE +The name that +.Nm +was executed with +.Pq Va argv[0] . +For compatibility +.Nm +also sets +.Va .MAKE +with the same value. +The preferred variable to use is the environment variable +.Ev MAKE +because it is more compatible with other versions of +.Nm +and cannot be confused with the special target with the same name. +.It Va .MAKE.DEPENDFILE +Names the makefile (default +.Ql Pa .depend ) +from which generated dependencies are read. +.It Va .MAKE.EXPAND_VARIABLES +A boolean that controls the default behavior of the +.Fl V +option. +If true, variable values printed with +.Fl V +are fully expanded; if false, the raw variable contents (which may +include additional unexpanded variable references) are shown. +.It Va .MAKE.EXPORTED +The list of variables exported by +.Nm . +.It Va .MAKE.JOBS +The argument to the +.Fl j +option. +.It Va .MAKE.JOB.PREFIX +If +.Nm +is run with +.Ar j +then output for each target is prefixed with a token +.Ql --- target --- +the first part of which can be controlled via +.Va .MAKE.JOB.PREFIX . +If +.Va .MAKE.JOB.PREFIX +is empty, no token is printed. +.br +For example: +.Li .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}] +would produce tokens like +.Ql ---make[1234] target --- +making it easier to track the degree of parallelism being achieved. +.It Ev MAKEFLAGS +The environment variable +.Ql Ev MAKEFLAGS +may contain anything that +may be specified on +.Nm Ns 's +command line. +Anything specified on +.Nm Ns 's +command line is appended to the +.Ql Ev MAKEFLAGS +variable which is then +entered into the environment for all programs which +.Nm +executes. +.It Va .MAKE.LEVEL +The recursion depth of +.Nm . +The initial instance of +.Nm +will be 0, and an incremented value is put into the environment +to be seen by the next generation. +This allows tests like: +.Li .if ${.MAKE.LEVEL} == 0 +to protect things which should only be evaluated in the initial instance of +.Nm . +.It Va .MAKE.MAKEFILE_PREFERENCE +The ordered list of makefile names +(default +.Ql Pa makefile , +.Ql Pa Makefile ) +that +.Nm +will look for. +.It Va .MAKE.MAKEFILES +The list of makefiles read by +.Nm , +which is useful for tracking dependencies. +Each makefile is recorded only once, regardless of the number of times read. +.It Va .MAKE.MODE +Processed after reading all makefiles. +Can affect the mode that +.Nm +runs in. +It can contain a number of keywords: +.Bl -hang -width missing-filemon=bf. +.It Pa compat +Like +.Fl B , +puts +.Nm +into "compat" mode. +.It Pa meta +Puts +.Nm +into "meta" mode, where meta files are created for each target +to capture the command run, the output generated and if +.Xr filemon 4 +is available, the system calls which are of interest to +.Nm . +The captured output can be very useful when diagnosing errors. +.It Pa curdirOk= Ar bf +Normally +.Nm +will not create .meta files in +.Ql Va .CURDIR . +This can be overridden by setting +.Va bf +to a value which represents True. +.It Pa missing-meta= Ar bf +If +.Va bf +is True, then a missing .meta file makes the target out-of-date. +.It Pa missing-filemon= Ar bf +If +.Va bf +is True, then missing filemon data makes the target out-of-date. +.It Pa nofilemon +Do not use +.Xr filemon 4 . +.It Pa env +For debugging, it can be useful to include the environment +in the .meta file. +.It Pa verbose +If in "meta" mode, print a clue about the target being built. +This is useful if the build is otherwise running silently. +The message printed the value of: +.Va .MAKE.META.PREFIX . +.It Pa ignore-cmd +Some makefiles have commands which are simply not stable. +This keyword causes them to be ignored for +determining whether a target is out of date in "meta" mode. +See also +.Ic .NOMETA_CMP . +.It Pa silent= Ar bf +If +.Va bf +is True, when a .meta file is created, mark the target +.Ic .SILENT . +.El +.It Va .MAKE.META.BAILIWICK +In "meta" mode, provides a list of prefixes which +match the directories controlled by +.Nm . +If a file that was generated outside of +.Va .OBJDIR +but within said bailiwick is missing, +the current target is considered out-of-date. +.It Va .MAKE.META.CREATED +In "meta" mode, this variable contains a list of all the meta files +updated. +If not empty, it can be used to trigger processing of +.Va .MAKE.META.FILES . +.It Va .MAKE.META.FILES +In "meta" mode, this variable contains a list of all the meta files +used (updated or not). +This list can be used to process the meta files to extract dependency +information. +.It Va .MAKE.META.IGNORE_PATHS +Provides a list of path prefixes that should be ignored; +because the contents are expected to change over time. +The default list includes: +.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp +.It Va .MAKE.META.IGNORE_PATTERNS +Provides a list of patterns to match against pathnames. +Ignore any that match. +.It Va .MAKE.META.IGNORE_FILTER +Provides a list of variable modifiers to apply to each pathname. +Ignore if the expansion is an empty string. +.It Va .MAKE.META.PREFIX +Defines the message printed for each meta file updated in "meta verbose" mode. +The default value is: +.Dl Building ${.TARGET:H:tA}/${.TARGET:T} +.It Va .MAKEOVERRIDES +This variable is used to record the names of variables assigned to +on the command line, so that they may be exported as part of +.Ql Ev MAKEFLAGS . +This behavior can be disabled by assigning an empty value to +.Ql Va .MAKEOVERRIDES +within a makefile. +Extra variables can be exported from a makefile +by appending their names to +.Ql Va .MAKEOVERRIDES . +.Ql Ev MAKEFLAGS +is re-exported whenever +.Ql Va .MAKEOVERRIDES +is modified. +.It Va .MAKE.PATH_FILEMON +If +.Nm +was built with +.Xr filemon 4 +support, this is set to the path of the device node. +This allows makefiles to test for this support. +.It Va .MAKE.PID +The process-id of +.Nm . +.It Va .MAKE.PPID +The parent process-id of +.Nm . +.It Va .MAKE.SAVE_DOLLARS +value should be a boolean that controls whether +.Ql $$ +are preserved when doing +.Ql := +assignments. +The default is false, for backwards compatibility. +Set to true for compatability with other makes. +If set to false, +.Ql $$ +becomes +.Ql $ +per normal evaluation rules. +.It Va MAKE_PRINT_VAR_ON_ERROR +When +.Nm +stops due to an error, it sets +.Ql Va .ERROR_TARGET +to the name of the target that failed, +.Ql Va .ERROR_CMD +to the commands of the failed target, +and in "meta" mode, it also sets +.Ql Va .ERROR_CWD +to the +.Xr getcwd 3 , +and +.Ql Va .ERROR_META_FILE +to the path of the meta file (if any) describing the failed target. +It then prints its name and the value of +.Ql Va .CURDIR +as well as the value of any variables named in +.Ql Va MAKE_PRINT_VAR_ON_ERROR . +.It Va .newline +This variable is simply assigned a newline character as its value. +This allows expansions using the +.Cm \&:@ +modifier to put a newline between +iterations of the loop rather than a space. +For example, the printing of +.Ql Va MAKE_PRINT_VAR_ON_ERROR +could be done as ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}. +.It Va .OBJDIR +A path to the directory where the targets are built. +Its value is determined by trying to +.Xr chdir 2 +to the following directories in order and using the first match: +.Bl -enum +.It +.Ev ${MAKEOBJDIRPREFIX}${.CURDIR} +.Pp +(Only if +.Ql Ev MAKEOBJDIRPREFIX +is set in the environment or on the command line.) +.It +.Ev ${MAKEOBJDIR} +.Pp +(Only if +.Ql Ev MAKEOBJDIR +is set in the environment or on the command line.) +.It +.Ev ${.CURDIR} Ns Pa /obj. Ns Ev ${MACHINE} +.It +.Ev ${.CURDIR} Ns Pa /obj +.It +.Pa /usr/obj/ Ns Ev ${.CURDIR} +.It +.Ev ${.CURDIR} +.El +.Pp +Variable expansion is performed on the value before it's used, +so expressions such as +.Dl ${.CURDIR:S,^/usr/src,/var/obj,} +may be used. +This is especially useful with +.Ql Ev MAKEOBJDIR . +.Pp +.Ql Va .OBJDIR +may be modified in the makefile via the special target +.Ql Ic .OBJDIR . +In all cases, +.Nm +will +.Xr chdir 2 +to the specified directory if it exists, and set +.Ql Va .OBJDIR +and +.Ql Ev PWD +to that directory before executing any targets. +. +.It Va .PARSEDIR +A path to the directory of the current +.Ql Pa Makefile +being parsed. +.It Va .PARSEFILE +The basename of the current +.Ql Pa Makefile +being parsed. +This variable and +.Ql Va .PARSEDIR +are both set only while the +.Ql Pa Makefiles +are being parsed. +If you want to retain their current values, assign them to a variable +using assignment with expansion: +.Pq Ql Cm \&:= . +.It Va .PATH +A variable that represents the list of directories that +.Nm +will search for files. +The search list should be updated using the target +.Ql Va .PATH +rather than the variable. +.It Ev PWD +Alternate path to the current directory. +.Nm +normally sets +.Ql Va .CURDIR +to the canonical path given by +.Xr getcwd 3 . +However, if the environment variable +.Ql Ev PWD +is set and gives a path to the current directory, then +.Nm +sets +.Ql Va .CURDIR +to the value of +.Ql Ev PWD +instead. +This behavior is disabled if +.Ql Ev MAKEOBJDIRPREFIX +is set or +.Ql Ev MAKEOBJDIR +contains a variable transform. +.Ql Ev PWD +is set to the value of +.Ql Va .OBJDIR +for all programs which +.Nm +executes. +.It Ev .SHELL +The pathname of the shell used to run target scripts. +It is read-only. +.It Ev .TARGETS +The list of targets explicitly specified on the command line, if any. +.It Ev VPATH +Colon-separated +.Pq Dq \&: +lists of directories that +.Nm +will search for files. +The variable is supported for compatibility with old make programs only, +use +.Ql Va .PATH +instead. +.El +.Ss Variable modifiers +Variable expansion may be modified to select or modify each word of the +variable (where a +.Dq word +is white-space delimited sequence of characters). +The general format of a variable expansion is as follows: +.Pp +.Dl ${variable[:modifier[:...]]} +.Pp +Each modifier begins with a colon, +which may be escaped with a backslash +.Pq Ql \e . +.Pp +A set of modifiers can be specified via a variable, as follows: +.Pp +.Dl modifier_variable=modifier[:...] +.Dl ${variable:${modifier_variable}[:...]} +.Pp +In this case the first modifier in the modifier_variable does not +start with a colon, since that must appear in the referencing +variable. +If any of the modifiers in the modifier_variable contain a dollar sign +.Pq Ql $ , +these must be doubled to avoid early expansion. +.Pp +The supported modifiers are: +.Bl -tag -width EEE +.It Cm \&:E +Replaces each word in the variable with its suffix. +.It Cm \&:H +Replaces each word in the variable with everything but the last component. +.It Cm \&:M Ns Ar pattern +Selects only those words that match +.Ar pattern . +The standard shell wildcard characters +.Pf ( Ql * , +.Ql \&? , +and +.Ql Oo Oc ) +may +be used. +The wildcard characters may be escaped with a backslash +.Pq Ql \e . +As a consequence of the way values are split into words, matched, +and then joined, a construct like +.Dl ${VAR:M*} +will normalize the inter-word spacing, removing all leading and +trailing space, and converting multiple consecutive spaces +to single spaces. +. +.It Cm \&:N Ns Ar pattern +This is identical to +.Ql Cm \&:M , +but selects all words which do not match +.Ar pattern . +.It Cm \&:O +Orders every word in variable alphabetically. +.It Cm \&:Or +Orders every word in variable in reverse alphabetical order. +.It Cm \&:Ox +Shuffles the words in variable. +The results will be different each time you are referring to the +modified variable; use the assignment with expansion +.Pq Ql Cm \&:= +to prevent such behavior. +For example, +.Bd -literal -offset indent +LIST= uno due tre quattro +RANDOM_LIST= ${LIST:Ox} +STATIC_RANDOM_LIST:= ${LIST:Ox} + +all: + @echo "${RANDOM_LIST}" + @echo "${RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" +.Ed +may produce output similar to: +.Bd -literal -offset indent +quattro due tre uno +tre due quattro uno +due uno quattro tre +due uno quattro tre +.Ed +.It Cm \&:Q +Quotes every shell meta-character in the variable, so that it can be passed +safely to the shell. +.It Cm \&:q +Quotes every shell meta-character in the variable, and also doubles +.Sq $ +characters so that it can be passed +safely through recursive invocations of +.Nm . +This is equivalent to: +.Sq \&:S/\e\&$/&&/g:Q . +.It Cm \&:R +Replaces each word in the variable with everything but its suffix. +.It Cm \&:range[=count] +The value is an integer sequence representing the words of the original +value, or the supplied +.Va count . +.It Cm \&:gmtime[=utc] +The value is a format string for +.Xr strftime 3 , +using +.Xr gmtime 3 . +If a +.Va utc +value is not provided or is 0, the current time is used. +.It Cm \&:hash +Computes a 32-bit hash of the value and encode it as hex digits. +.It Cm \&:localtime[=utc] +The value is a format string for +.Xr strftime 3 , +using +.Xr localtime 3 . +If a +.Va utc +value is not provided or is 0, the current time is used. +.It Cm \&:tA +Attempts to convert variable to an absolute path using +.Xr realpath 3 , +if that fails, the value is unchanged. +.It Cm \&:tl +Converts variable to lower-case letters. +.It Cm \&:ts Ns Ar c +Words in the variable are normally separated by a space on expansion. +This modifier sets the separator to the character +.Ar c . +If +.Ar c +is omitted, then no separator is used. +The common escapes (including octal numeric codes) work as expected. +.It Cm \&:tu +Converts variable to upper-case letters. +.It Cm \&:tW +Causes the value to be treated as a single word +(possibly containing embedded white space). +See also +.Ql Cm \&:[*] . +.It Cm \&:tw +Causes the value to be treated as a sequence of +words delimited by white space. +See also +.Ql Cm \&:[@] . +.Sm off +.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW +.Sm on +Modifies the first occurrence of +.Ar old_string +in each word of the variable's value, replacing it with +.Ar new_string . +If a +.Ql g +is appended to the last delimiter of the pattern, all occurrences +in each word are replaced. +If a +.Ql 1 +is appended to the last delimiter of the pattern, only the first occurrence +is affected. +If a +.Ql W +is appended to the last delimiter of the pattern, +then the value is treated as a single word +(possibly containing embedded white space). +If +.Ar old_string +begins with a caret +.Pq Ql ^ , +.Ar old_string +is anchored at the beginning of each word. +If +.Ar old_string +ends with a dollar sign +.Pq Ql \&$ , +it is anchored at the end of each word. +Inside +.Ar new_string , +an ampersand +.Pq Ql & +is replaced by +.Ar old_string +(without any +.Ql ^ +or +.Ql \&$ ) . +Any character may be used as a delimiter for the parts of the modifier +string. +The anchoring, ampersand and delimiter characters may be escaped with a +backslash +.Pq Ql \e . +.Pp +Variable expansion occurs in the normal fashion inside both +.Ar old_string +and +.Ar new_string +with the single exception that a backslash is used to prevent the expansion +of a dollar sign +.Pq Ql \&$ , +not a preceding dollar sign as is usual. +.Sm off +.It Cm \&:C No \&/ Ar pattern No \&/ Ar replacement No \&/ Op Cm 1gW +.Sm on +The +.Cm \&:C +modifier is just like the +.Cm \&:S +modifier except that the old and new strings, instead of being +simple strings, are an extended regular expression (see +.Xr regex 3 ) +string +.Ar pattern +and an +.Xr ed 1 Ns \-style +string +.Ar replacement . +Normally, the first occurrence of the pattern +.Ar pattern +in each word of the value is substituted with +.Ar replacement . +The +.Ql 1 +modifier causes the substitution to apply to at most one word; the +.Ql g +modifier causes the substitution to apply to as many instances of the +search pattern +.Ar pattern +as occur in the word or words it is found in; the +.Ql W +modifier causes the value to be treated as a single word +(possibly containing embedded white space). +.Pp +As for the +.Cm \&:S +modifier, the +.Ar pattern +and +.Ar replacement +are subjected to variable expansion before being parsed as +regular expressions. +.It Cm \&:T +Replaces each word in the variable with its last path component. +.It Cm \&:u +Removes adjacent duplicate words (like +.Xr uniq 1 ) . +.Sm off +.It Cm \&:\&? Ar true_string Cm \&: Ar false_string +.Sm on +If the variable name (not its value), when parsed as a .if conditional +expression, evaluates to true, return as its value the +.Ar true_string , +otherwise return the +.Ar false_string . +Since the variable name is used as the expression, \&:\&? must be the +first modifier after the variable name itself - which will, of course, +usually contain variable expansions. +A common error is trying to use expressions like +.Dl ${NUMBERS:M42:?match:no} +which actually tests defined(NUMBERS), +to determine if any words match "42" you need to use something like: +.Dl ${"${NUMBERS:M42}" != \&"\&":?match:no} . +.It Ar :old_string=new_string +This is the +.At V +style variable substitution. +It must be the last modifier specified. +If +.Ar old_string +or +.Ar new_string +do not contain the pattern matching character +.Ar % +then it is assumed that they are +anchored at the end of each word, so only suffixes or entire +words may be replaced. +Otherwise +.Ar % +is the substring of +.Ar old_string +to be replaced in +.Ar new_string . +If only +.Ar old_string +contains the pattern matching character +.Ar % , +and +.Ar old_string +matches, then the result is the +.Ar new_string . +If only the +.Ar new_string +contains the pattern matching character +.Ar % , +then it is not treated specially and it is printed as a literal +.Ar % +on match. +If there is more than one pattern matching character +.Ar ( % ) +in either the +.Ar new_string +or +.Ar old_string , +only the first instance is treated specially (as the pattern character); +all subsequent instances are treated as regular characters. +.Pp +Variable expansion occurs in the normal fashion inside both +.Ar old_string +and +.Ar new_string +with the single exception that a backslash is used to prevent the +expansion of a dollar sign +.Pq Ql \&$ , +not a preceding dollar sign as is usual. +.Sm off +.It Cm \&:@ Ar temp Cm @ Ar string Cm @ +.Sm on +This is the loop expansion mechanism from the OSF Development +Environment (ODE) make. +Unlike +.Cm \&.for +loops, expansion occurs at the time of reference. +Assigns +.Ar temp +to each word in the variable and evaluates +.Ar string . +The ODE convention is that +.Ar temp +should start and end with a period. +For example. +.Dl ${LINKS:@.LINK.@${LN} ${TARGET} ${.LINK.}@} +.Pp +However a single character variable is often more readable: +.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@} +.It Cm \&:_[=var] +Saves the current variable value in +.Ql $_ +or the named +.Va var +for later reference. +Example usage: +.Bd -literal -offset indent +M_cmpv.units = 1 1000 1000000 +M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \&\\ +\\* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh + +.Dv .if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}} + +.Ed +Here +.Ql $_ +is used to save the result of the +.Ql :S +modifier which is later referenced using the index values from +.Ql :range . +.It Cm \&:U Ns Ar newval +If the variable is undefined, +.Ar newval +is the value. +If the variable is defined, the existing value is returned. +This is another ODE make feature. +It is handy for setting per-target CFLAGS for instance: +.Dl ${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}} +If a value is only required if the variable is undefined, use: +.Dl ${VAR:D:Unewval} +.It Cm \&:D Ns Ar newval +If the variable is defined, +.Ar newval +is the value. +.It Cm \&:L +The name of the variable is the value. +.It Cm \&:P +The path of the node which has the same name as the variable +is the value. +If no such node exists or its path is null, then the +name of the variable is used. +In order for this modifier to work, the name (node) must at least have +appeared on the rhs of a dependency. +.Sm off +.It Cm \&:\&! Ar cmd Cm \&! +.Sm on +The output of running +.Ar cmd +is the value. +.It Cm \&:sh +If the variable is non-empty it is run as a command and the output +becomes the new value. +.It Cm \&::= Ns Ar str +The variable is assigned the value +.Ar str +after substitution. +This modifier and its variations are useful in +obscure situations such as wanting to set a variable when shell commands +are being parsed. +These assignment modifiers always expand to +nothing, so if appearing in a rule line by themselves should be +preceded with something to keep +.Nm +happy. +.Pp +The +.Ql Cm \&:: +helps avoid false matches with the +.At V +style +.Cm \&:= +modifier and since substitution always occurs the +.Cm \&::= +form is vaguely appropriate. +.It Cm \&::?= Ns Ar str +As for +.Cm \&::= +but only if the variable does not already have a value. +.It Cm \&::+= Ns Ar str +Append +.Ar str +to the variable. +.It Cm \&::!= Ns Ar cmd +Assign the output of +.Ar cmd +to the variable. +.It Cm \&:\&[ Ns Ar range Ns Cm \&] +Selects one or more words from the value, +or performs other operations related to the way in which the +value is divided into words. +.Pp +Ordinarily, a value is treated as a sequence of words +delimited by white space. +Some modifiers suppress this behavior, +causing a value to be treated as a single word +(possibly containing embedded white space). +An empty value, or a value that consists entirely of white-space, +is treated as a single word. +For the purposes of the +.Ql Cm \&:[] +modifier, the words are indexed both forwards using positive integers +(where index 1 represents the first word), +and backwards using negative integers +(where index \-1 represents the last word). +.Pp +The +.Ar range +is subjected to variable expansion, and the expanded result is +then interpreted as follows: +.Bl -tag -width index +.\" :[n] +.It Ar index +Selects a single word from the value. +.\" :[start..end] +.It Ar start Ns Cm \&.. Ns Ar end +Selects all words from +.Ar start +to +.Ar end , +inclusive. +For example, +.Ql Cm \&:[2..-1] +selects all words from the second word to the last word. +If +.Ar start +is greater than +.Ar end , +then the words are output in reverse order. +For example, +.Ql Cm \&:[-1..1] +selects all the words from last to first. +If the list is already ordered, then this effectively reverses +the list, but it is more efficient to use +.Ql Cm \&:Or +instead of +.Ql Cm \&:O:[-1..1] . +.\" :[*] +.It Cm \&* +Causes subsequent modifiers to treat the value as a single word +(possibly containing embedded white space). +Analogous to the effect of +\&"$*\&" +in Bourne shell. +.\" :[0] +.It 0 +Means the same as +.Ql Cm \&:[*] . +.\" :[*] +.It Cm \&@ +Causes subsequent modifiers to treat the value as a sequence of words +delimited by white space. +Analogous to the effect of +\&"$@\&" +in Bourne shell. +.\" :[#] +.It Cm \&# +Returns the number of words in the value. +.El \" :[range] +.El +.Sh INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS +Makefile inclusion, conditional structures and for loops reminiscent +of the C programming language are provided in +.Nm . +All such structures are identified by a line beginning with a single +dot +.Pq Ql \&. +character. +Files are included with either +.Cm \&.include \&< Ns Ar file Ns Cm \&> +or +.Cm \&.include \&\*q Ns Ar file Ns Cm \&\*q . +Variables between the angle brackets or double quotes are expanded +to form the file name. +If angle brackets are used, the included makefile is expected to be in +the system makefile directory. +If double quotes are used, the including makefile's directory and any +directories specified using the +.Fl I +option are searched before the system +makefile directory. +For compatibility with other versions of +.Nm +.Ql include file ... +is also accepted. +.Pp +If the include statement is written as +.Cm .-include +or as +.Cm .sinclude +then errors locating and/or opening include files are ignored. +.Pp +If the include statement is written as +.Cm .dinclude +not only are errors locating and/or opening include files ignored, +but stale dependencies within the included file will be ignored +just like +.Va .MAKE.DEPENDFILE . +.Pp +Conditional expressions are also preceded by a single dot as the first +character of a line. +The possible conditionals are as follows: +.Bl -tag -width Ds +.It Ic .error Ar message +The message is printed along with the name of the makefile and line number, +then +.Nm +will exit immediately. +.It Ic .export Ar variable ... +Export the specified global variable. +If no variable list is provided, all globals are exported +except for internal variables (those that start with +.Ql \&. ) . +This is not affected by the +.Fl X +flag, so should be used with caution. +For compatibility with other +.Nm +programs +.Ql export variable=value +is also accepted. +.Pp +Appending a variable name to +.Va .MAKE.EXPORTED +is equivalent to exporting a variable. +.It Ic .export-env Ar variable ... +The same as +.Ql .export , +except that the variable is not appended to +.Va .MAKE.EXPORTED . +This allows exporting a value to the environment which is different from that +used by +.Nm +internally. +.It Ic .export-literal Ar variable ... +The same as +.Ql .export-env , +except that variables in the value are not expanded. +.It Ic .info Ar message +The message is printed along with the name of the makefile and line number. +.It Ic .undef Ar variable +Un-define the specified global variable. +Only global variables may be un-defined. +.It Ic .unexport Ar variable ... +The opposite of +.Ql .export . +The specified global +.Va variable +will be removed from +.Va .MAKE.EXPORTED . +If no variable list is provided, all globals are unexported, +and +.Va .MAKE.EXPORTED +deleted. +.It Ic .unexport-env +Unexport all globals previously exported and +clear the environment inherited from the parent. +This operation will cause a memory leak of the original environment, +so should be used sparingly. +Testing for +.Va .MAKE.LEVEL +being 0, would make sense. +Also note that any variables which originated in the parent environment +should be explicitly preserved if desired. +For example: +.Bd -literal -offset indent +.Li .if ${.MAKE.LEVEL} == 0 +PATH := ${PATH} +.Li .unexport-env +.Li .export PATH +.Li .endif +.Pp +.Ed +Would result in an environment containing only +.Ql Ev PATH , +which is the minimal useful environment. +Actually +.Ql Ev .MAKE.LEVEL +will also be pushed into the new environment. +.It Ic .warning Ar message +The message prefixed by +.Ql Pa warning: +is printed along with the name of the makefile and line number. +.It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ... +Test the value of an expression. +.It Ic .ifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +Test the value of a variable. +.It Ic .ifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +Test the value of a variable. +.It Ic .ifmake Oo \&! Oc Ns Ar target Op Ar operator target ... +Test the target being built. +.It Ic .ifnmake Oo \&! Ns Oc Ar target Op Ar operator target ... +Test the target being built. +.It Ic .else +Reverse the sense of the last conditional. +.It Ic .elif Oo \&! Ns Oc Ar expression Op Ar operator expression ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .if . +.It Ic .elifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifdef . +.It Ic .elifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifndef . +.It Ic .elifmake Oo \&! Oc Ns Ar target Op Ar operator target ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifmake . +.It Ic .elifnmake Oo \&! Oc Ns Ar target Op Ar operator target ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifnmake . +.It Ic .endif +End the body of the conditional. +.El +.Pp +The +.Ar operator +may be any one of the following: +.Bl -tag -width "Cm XX" +.It Cm \&|\&| +Logical OR. +.It Cm \&&& +Logical +.Tn AND ; +of higher precedence than +.Dq \&|\&| . +.El +.Pp +As in C, +.Nm +will only evaluate a conditional as far as is necessary to determine +its value. +Parentheses may be used to change the order of evaluation. +The boolean operator +.Ql Ic \&! +may be used to logically negate an entire +conditional. +It is of higher precedence than +.Ql Ic \&&& . +.Pp +The value of +.Ar expression +may be any of the following: +.Bl -tag -width defined +.It Ic defined +Takes a variable name as an argument and evaluates to true if the variable +has been defined. +.It Ic make +Takes a target name as an argument and evaluates to true if the target +was specified as part of +.Nm Ns 's +command line or was declared the default target (either implicitly or +explicitly, see +.Va .MAIN ) +before the line containing the conditional. +.It Ic empty +Takes a variable, with possible modifiers, and evaluates to true if +the expansion of the variable would result in an empty string. +.It Ic exists +Takes a file name as an argument and evaluates to true if the file exists. +The file is searched for on the system search path (see +.Va .PATH ) . +.It Ic target +Takes a target name as an argument and evaluates to true if the target +has been defined. +.It Ic commands +Takes a target name as an argument and evaluates to true if the target +has been defined and has commands associated with it. +.El +.Pp +.Ar Expression +may also be an arithmetic or string comparison. +Variable expansion is +performed on both sides of the comparison, after which the numerical +values are compared. +A value is interpreted as hexadecimal if it is +preceded by 0x, otherwise it is decimal; octal numbers are not supported. +The standard C relational operators are all supported. +If after +variable expansion, either the left or right hand side of a +.Ql Ic == +or +.Ql Ic "!=" +operator is not a numerical value, then +string comparison is performed between the expanded +variables. +If no relational operator is given, it is assumed that the expanded +variable is being compared against 0, or an empty string in the case +of a string comparison. +.Pp +When +.Nm +is evaluating one of these conditional expressions, and it encounters +a (white-space separated) word it doesn't recognize, either the +.Dq make +or +.Dq defined +expression is applied to it, depending on the form of the conditional. +If the form is +.Ql Ic .ifdef , +.Ql Ic .ifndef , +or +.Ql Ic .if +the +.Dq defined +expression is applied. +Similarly, if the form is +.Ql Ic .ifmake +or +.Ql Ic .ifnmake , +the +.Dq make +expression is applied. +.Pp +If the conditional evaluates to true the parsing of the makefile continues +as before. +If it evaluates to false, the following lines are skipped. +In both cases this continues until a +.Ql Ic .else +or +.Ql Ic .endif +is found. +.Pp +For loops are typically used to apply a set of rules to a list of files. +The syntax of a for loop is: +.Pp +.Bl -tag -compact -width Ds +.It Ic \&.for Ar variable Oo Ar variable ... Oc Ic in Ar expression +.It Aq make-lines +.It Ic \&.endfor +.El +.Pp +After the for +.Ic expression +is evaluated, it is split into words. +On each iteration of the loop, one word is taken and assigned to each +.Ic variable , +in order, and these +.Ic variables +are substituted into the +.Ic make-lines +inside the body of the for loop. +The number of words must come out even; that is, if there are three +iteration variables, the number of words provided must be a multiple +of three. +.Sh COMMENTS +Comments begin with a hash +.Pq Ql \&# +character, anywhere but in a shell +command line, and continue to the end of an unescaped new line. +.Sh SPECIAL SOURCES (ATTRIBUTES) +.Bl -tag -width .IGNOREx +.It Ic .EXEC +Target is never out of date, but always execute commands anyway. +.It Ic .IGNORE +Ignore any errors from the commands associated with this target, exactly +as if they all were preceded by a dash +.Pq Ql \- . +.\" .It Ic .INVISIBLE +.\" XXX +.\" .It Ic .JOIN +.\" XXX +.It Ic .MADE +Mark all sources of this target as being up-to-date. +.It Ic .MAKE +Execute the commands associated with this target even if the +.Fl n +or +.Fl t +options were specified. +Normally used to mark recursive +.Nm Ns s . +.It Ic .META +Create a meta file for the target, even if it is flagged as +.Ic .PHONY , +.Ic .MAKE , +or +.Ic .SPECIAL . +Usage in conjunction with +.Ic .MAKE +is the most likely case. +In "meta" mode, the target is out-of-date if the meta file is missing. +.It Ic .NOMETA +Do not create a meta file for the target. +Meta files are also not created for +.Ic .PHONY , +.Ic .MAKE , +or +.Ic .SPECIAL +targets. +.It Ic .NOMETA_CMP +Ignore differences in commands when deciding if target is out of date. +This is useful if the command contains a value which always changes. +If the number of commands change, though, the target will still be out of date. +The same effect applies to any command line that uses the variable +.Va .OODATE , +which can be used for that purpose even when not otherwise needed or desired: +.Bd -literal -offset indent + +skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + +.Ed +The +.Cm \&:M +pattern suppresses any expansion of the unwanted variable. +.It Ic .NOPATH +Do not search for the target in the directories specified by +.Ic .PATH . +.It Ic .NOTMAIN +Normally +.Nm +selects the first target it encounters as the default target to be built +if no target was specified. +This source prevents this target from being selected. +.It Ic .OPTIONAL +If a target is marked with this attribute and +.Nm +can't figure out how to create it, it will ignore this fact and assume +the file isn't needed or already exists. +.It Ic .PHONY +The target does not +correspond to an actual file; it is always considered to be out of date, +and will not be created with the +.Fl t +option. +Suffix-transformation rules are not applied to +.Ic .PHONY +targets. +.It Ic .PRECIOUS +When +.Nm +is interrupted, it normally removes any partially made targets. +This source prevents the target from being removed. +.It Ic .RECURSIVE +Synonym for +.Ic .MAKE . +.It Ic .SILENT +Do not echo any of the commands associated with this target, exactly +as if they all were preceded by an at sign +.Pq Ql @ . +.It Ic .USE +Turn the target into +.Nm Ns 's +version of a macro. +When the target is used as a source for another target, the other target +acquires the commands, sources, and attributes (except for +.Ic .USE ) +of the +source. +If the target already has commands, the +.Ic .USE +target's commands are appended +to them. +.It Ic .USEBEFORE +Exactly like +.Ic .USE , +but prepend the +.Ic .USEBEFORE +target commands to the target. +.It Ic .WAIT +If +.Ic .WAIT +appears in a dependency line, the sources that precede it are +made before the sources that succeed it in the line. +Since the dependents of files are not made until the file itself +could be made, this also stops the dependents being built unless they +are needed for another branch of the dependency tree. +So given: +.Bd -literal +x: a .WAIT b + echo x +a: + echo a +b: b1 + echo b +b1: + echo b1 + +.Ed +the output is always +.Ql a , +.Ql b1 , +.Ql b , +.Ql x . +.br +The ordering imposed by +.Ic .WAIT +is only relevant for parallel makes. +.El +.Sh SPECIAL TARGETS +Special targets may not be included with other targets, i.e. they must be +the only target specified. +.Bl -tag -width .BEGINx +.It Ic .BEGIN +Any command lines attached to this target are executed before anything +else is done. +.It Ic .DEFAULT +This is sort of a +.Ic .USE +rule for any target (that was used only as a +source) that +.Nm +can't figure out any other way to create. +Only the shell script is used. +The +.Ic .IMPSRC +variable of a target that inherits +.Ic .DEFAULT Ns 's +commands is set +to the target's own name. +.It Ic .DELETE_ON_ERROR +If this target is present in the makefile, it globally causes make to +delete targets whose commands fail. +(By default, only targets whose commands are interrupted during +execution are deleted. +This is the historical behavior.) +This setting can be used to help prevent half-finished or malformed +targets from being left around and corrupting future rebuilds. +.It Ic .END +Any command lines attached to this target are executed after everything +else is done. +.It Ic .ERROR +Any command lines attached to this target are executed when another target fails. +The +.Ic .ERROR_TARGET +variable is set to the target that failed. +See also +.Ic MAKE_PRINT_VAR_ON_ERROR . +.It Ic .IGNORE +Mark each of the sources with the +.Ic .IGNORE +attribute. +If no sources are specified, this is the equivalent of specifying the +.Fl i +option. +.It Ic .INTERRUPT +If +.Nm +is interrupted, the commands for this target will be executed. +.It Ic .MAIN +If no target is specified when +.Nm +is invoked, this target will be built. +.It Ic .MAKEFLAGS +This target provides a way to specify flags for +.Nm +when the makefile is used. +The flags are as if typed to the shell, though the +.Fl f +option will have +no effect. +.\" XXX: NOT YET!!!! +.\" .It Ic .NOTPARALLEL +.\" The named targets are executed in non parallel mode. +.\" If no targets are +.\" specified, then all targets are executed in non parallel mode. +.It Ic .NOPATH +Apply the +.Ic .NOPATH +attribute to any specified sources. +.It Ic .NOTPARALLEL +Disable parallel mode. +.It Ic .NO_PARALLEL +Synonym for +.Ic .NOTPARALLEL , +for compatibility with other pmake variants. +.It Ic .OBJDIR +The source is a new value for +.Ql Va .OBJDIR . +If it exists, +.Nm +will +.Xr chdir 2 +to it and update the value of +.Ql Va .OBJDIR . +.It Ic .ORDER +The named targets are made in sequence. +This ordering does not add targets to the list of targets to be made. +Since the dependents of a target do not get built until the target itself +could be built, unless +.Ql a +is built by another part of the dependency graph, +the following is a dependency loop: +.Bd -literal +\&.ORDER: b a +b: a +.Ed +.Pp +The ordering imposed by +.Ic .ORDER +is only relevant for parallel makes. +.\" XXX: NOT YET!!!! +.\" .It Ic .PARALLEL +.\" The named targets are executed in parallel mode. +.\" If no targets are +.\" specified, then all targets are executed in parallel mode. +.It Ic .PATH +The sources are directories which are to be searched for files not +found in the current directory. +If no sources are specified, any previously specified directories are +deleted. +If the source is the special +.Ic .DOTLAST +target, then the current working +directory is searched last. +.It Ic .PATH. Ns Va suffix +Like +.Ic .PATH +but applies only to files with a particular suffix. +The suffix must have been previously declared with +.Ic .SUFFIXES . +.It Ic .PHONY +Apply the +.Ic .PHONY +attribute to any specified sources. +.It Ic .PRECIOUS +Apply the +.Ic .PRECIOUS +attribute to any specified sources. +If no sources are specified, the +.Ic .PRECIOUS +attribute is applied to every +target in the file. +.It Ic .SHELL +Sets the shell that +.Nm +will use to execute commands. +The sources are a set of +.Ar field=value +pairs. +.Bl -tag -width hasErrCtls +.It Ar name +This is the minimal specification, used to select one of the built-in +shell specs; +.Ar sh , +.Ar ksh , +and +.Ar csh . +.It Ar path +Specifies the path to the shell. +.It Ar hasErrCtl +Indicates whether the shell supports exit on error. +.It Ar check +The command to turn on error checking. +.It Ar ignore +The command to disable error checking. +.It Ar echo +The command to turn on echoing of commands executed. +.It Ar quiet +The command to turn off echoing of commands executed. +.It Ar filter +The output to filter after issuing the +.Ar quiet +command. +It is typically identical to +.Ar quiet . +.It Ar errFlag +The flag to pass the shell to enable error checking. +.It Ar echoFlag +The flag to pass the shell to enable command echoing. +.It Ar newline +The string literal to pass the shell that results in a single newline +character when used outside of any quoting characters. +.El +Example: +.Bd -literal +\&.SHELL: name=ksh path=/bin/ksh hasErrCtl=true \e + check="set \-e" ignore="set +e" \e + echo="set \-v" quiet="set +v" filter="set +v" \e + echoFlag=v errFlag=e newline="'\en'" +.Ed +.It Ic .SILENT +Apply the +.Ic .SILENT +attribute to any specified sources. +If no sources are specified, the +.Ic .SILENT +attribute is applied to every +command in the file. +.It Ic .STALE +This target gets run when a dependency file contains stale entries, having +.Va .ALLSRC +set to the name of that dependency file. +.It Ic .SUFFIXES +Each source specifies a suffix to +.Nm . +If no sources are specified, any previously specified suffixes are deleted. +It allows the creation of suffix-transformation rules. +.Pp +Example: +.Bd -literal +\&.SUFFIXES: .o +\&.c.o: + cc \-o ${.TARGET} \-c ${.IMPSRC} +.Ed +.El +.Sh ENVIRONMENT +.Nm +uses the following environment variables, if they exist: +.Ev MACHINE , +.Ev MACHINE_ARCH , +.Ev MAKE , +.Ev MAKEFLAGS , +.Ev MAKEOBJDIR , +.Ev MAKEOBJDIRPREFIX , +.Ev MAKESYSPATH , +.Ev PWD , +and +.Ev TMPDIR . +.Pp +.Ev MAKEOBJDIRPREFIX +and +.Ev MAKEOBJDIR +may only be set in the environment or on the command line to +.Nm +and not as makefile variables; +see the description of +.Ql Va .OBJDIR +for more details. +.Sh FILES +.Bl -tag -width /usr/share/mk -compact +.It .depend +list of dependencies +.It Makefile +list of dependencies +.It makefile +list of dependencies +.It sys.mk +system makefile +.It /usr/share/mk +system makefile directory +.El +.Sh COMPATIBILITY +The basic make syntax is compatible between different versions of make; +however the special variables, variable modifiers and conditionals are not. +.Ss Older versions +An incomplete list of changes in older versions of +.Nm : +.Pp +The way that .for loop variables are substituted changed after +NetBSD 5.0 +so that they still appear to be variable expansions. +In particular this stops them being treated as syntax, and removes some +obscure problems using them in .if statements. +.Pp +The way that parallel makes are scheduled changed in +NetBSD 4.0 +so that .ORDER and .WAIT apply recursively to the dependent nodes. +The algorithms used may change again in the future. +.Ss Other make dialects +Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not +support most of the features of +.Nm +as described in this manual. +Most notably: +.Bl -bullet -offset indent +.It +The +.Ic .WAIT +and +.Ic .ORDER +declarations and most functionality pertaining to parallelization. +(GNU make supports parallelization but lacks these features needed to +control it effectively.) +.It +Directives, including for loops and conditionals and most of the +forms of include files. +(GNU make has its own incompatible and less powerful syntax for +conditionals.) +.It +All built-in variables that begin with a dot. +.It +Most of the special sources and targets that begin with a dot, +with the notable exception of +.Ic .PHONY , +.Ic .PRECIOUS , +and +.Ic .SUFFIXES . +.It +Variable modifiers, except for the +.Dl :old=new +string substitution, which does not portably support globbing with +.Ql % +and historically only works on declared suffixes. +.It +The +.Ic $> +variable even in its short form; most makes support this functionality +but its name varies. +.El +.Pp +Some features are somewhat more portable, such as assignment with +.Ic += , +.Ic ?= , +and +.Ic != . +The +.Ic .PATH +functionality is based on an older feature +.Ic VPATH +found in GNU make and many versions of SVR4 make; however, +historically its behavior is too ill-defined (and too buggy) to rely +upon. +.Pp +The +.Ic $@ +and +.Ic $< +variables are more or less universally portable, as is the +.Ic $(MAKE) +variable. +Basic use of suffix rules (for files only in the current directory, +not trying to chain transformations together, etc.) is also reasonably +portable. +.Sh SEE ALSO +.Xr mkdep 1 +.Sh HISTORY +.Nm +is derived from NetBSD +.Xr make 1 . +It uses autoconf to facilitate portability to other platforms. +.Pp +A +make +command appeared in +.At v7 . +This +make +implementation is based on Adam De Boor's pmake program which was written +for Sprite at Berkeley. +It was designed to be a parallel distributed make running jobs on different +machines using a daemon called +.Dq customs . +.Pp +Historically the target/dependency +.Dq FRC +has been used to FoRCe rebuilding (since the target/dependency +does not exist... unless someone creates an +.Dq FRC +file). +.Sh BUGS +The +make +syntax is difficult to parse without actually acting on the data. +For instance, finding the end of a variable's use should involve scanning +each of the modifiers, using the correct terminator for each field. +In many places +make +just counts {} and () in order to find the end of a variable expansion. +.Pp +There is no way of escaping a space character in a filename. Property changes on: vendor/NetBSD/bmake/20201101/bmake.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/bmake.cat1 =================================================================== --- vendor/NetBSD/bmake/20201101/bmake.cat1 (nonexistent) +++ vendor/NetBSD/bmake/20201101/bmake.cat1 (revision 367461) @@ -0,0 +1,1571 @@ +BMAKE(1) FreeBSD General Commands Manual BMAKE(1) + +NAME + bmake -- maintain program dependencies + +SYNOPSIS + bmake [-BeikNnqrstWwX] [-C directory] [-D variable] [-d flags] + [-f makefile] [-I directory] [-J private] [-j max_jobs] + [-m directory] [-T file] [-V variable] [-v variable] + [variable=value] [target ...] + +DESCRIPTION + bmake is a program designed to simplify the maintenance of other pro- + grams. Its input is a list of specifications as to the files upon which + programs and other files depend. If no -f makefile makefile option is + given, bmake will try to open `makefile' then `Makefile' in order to find + the specifications. If the file `.depend' exists, it is read (see + mkdep(1)). + + This manual page is intended as a reference document only. For a more + thorough description of bmake and makefiles, please refer to PMake - A + Tutorial. + + bmake will prepend the contents of the MAKEFLAGS environment variable to + the command line arguments before parsing them. + + The options are as follows: + + -B Try to be backwards compatible by executing a single shell per + command and by executing the commands to make the sources of a + dependency line in sequence. + + -C directory + Change to directory before reading the makefiles or doing any- + thing else. If multiple -C options are specified, each is inter- + preted relative to the previous one: -C / -C etc is equivalent to + -C /etc. + + -D variable + Define variable to be 1, in the global context. + + -d [-]flags + Turn on debugging, and specify which portions of bmake are to + print debugging information. Unless the flags are preceded by + `-' they are added to the MAKEFLAGS environment variable and will + be processed by any child make processes. By default, debugging + information is printed to standard error, but this can be changed + using the F debugging flag. The debugging output is always + unbuffered; in addition, if debugging is enabled but debugging + output is not directed to standard output, then the standard out- + put is line buffered. Flags is one or more of the following: + + A Print all possible debugging information; equivalent to + specifying all of the debugging flags. + + a Print debugging information about archive searching and + caching. + + C Print debugging information about current working direc- + tory. + + c Print debugging information about conditional evaluation. + + d Print debugging information about directory searching and + caching. + + e Print debugging information about failed commands and + targets. + + F[+]filename + Specify where debugging output is written. This must be + the last flag, because it consumes the remainder of the + argument. If the character immediately after the `F' + flag is `+', then the file will be opened in append mode; + otherwise the file will be overwritten. If the file name + is `stdout' or `stderr' then debugging output will be + written to the standard output or standard error output + file descriptors respectively (and the `+' option has no + effect). Otherwise, the output will be written to the + named file. If the file name ends `.%d' then the `%d' is + replaced by the pid. + + f Print debugging information about loop evaluation. + + g1 Print the input graph before making anything. + + g2 Print the input graph after making everything, or before + exiting on error. + + g3 Print the input graph before exiting on error. + + h Print debugging information about hash table operations. + + j Print debugging information about running multiple + shells. + + L Turn on lint checks. This will throw errors for variable + assignments that do not parse correctly, at the time of + assignment so the file and line number are available. + + l Print commands in Makefiles regardless of whether or not + they are prefixed by `@' or other "quiet" flags. Also + known as "loud" behavior. + + M Print debugging information about "meta" mode decisions + about targets. + + m Print debugging information about making targets, includ- + ing modification dates. + + n Don't delete the temporary command scripts created when + running commands. These temporary scripts are created in + the directory referred to by the TMPDIR environment vari- + able, or in /tmp if TMPDIR is unset or set to the empty + string. The temporary scripts are created by mkstemp(3), + and have names of the form makeXXXXXX. NOTE: This can + create many files in TMPDIR or /tmp, so use with care. + + p Print debugging information about makefile parsing. + + s Print debugging information about suffix-transformation + rules. + + t Print debugging information about target list mainte- + nance. + + V Force the -V option to print raw values of variables, + overriding the default behavior set via + .MAKE.EXPAND_VARIABLES. + + v Print debugging information about variable assignment. + + x Run shell commands with -x so the actual commands are + printed as they are executed. + + -e Specify that environment variables override macro assignments + within makefiles. + + -f makefile + Specify a makefile to read instead of the default `makefile'. If + makefile is `-', standard input is read. Multiple makefiles may + be specified, and are read in the order specified. + + -I directory + Specify a directory in which to search for makefiles and included + makefiles. The system makefile directory (or directories, see + the -m option) is automatically included as part of this list. + + -i Ignore non-zero exit of shell commands in the makefile. Equiva- + lent to specifying `-' before each command line in the makefile. + + -J private + This option should not be specified by the user. + + When the j option is in use in a recursive build, this option is + passed by a make to child makes to allow all the make processes + in the build to cooperate to avoid overloading the system. + + -j max_jobs + Specify the maximum number of jobs that bmake may have running at + any one time. The value is saved in .MAKE.JOBS. Turns compati- + bility mode off, unless the B flag is also specified. When com- + patibility mode is off, all commands associated with a target are + executed in a single shell invocation as opposed to the tradi- + tional one shell invocation per line. This can break traditional + scripts which change directories on each command invocation and + then expect to start with a fresh environment on the next line. + It is more efficient to correct the scripts rather than turn + backwards compatibility on. + + -k Continue processing after errors are encountered, but only on + those targets that do not depend on the target whose creation + caused the error. + + -m directory + Specify a directory in which to search for sys.mk and makefiles + included via the <file>-style include statement. The -m option + can be used multiple times to form a search path. This path will + override the default system include path: /usr/share/mk. Fur- + thermore the system include path will be appended to the search + path used for "file"-style include statements (see the -I + option). + + If a file or directory name in the -m argument (or the + MAKESYSPATH environment variable) starts with the string ".../" + then bmake will search for the specified file or directory named + in the remaining part of the argument string. The search starts + with the current directory of the Makefile and then works upward + towards the root of the file system. If the search is success- + ful, then the resulting directory replaces the ".../" specifica- + tion in the -m argument. If used, this feature allows bmake to + easily search in the current source tree for customized sys.mk + files (e.g., by using ".../mk/sys.mk" as an argument). + + -n Display the commands that would have been executed, but do not + actually execute them unless the target depends on the .MAKE spe- + cial source (see below) or the command is prefixed with `+'. + + -N Display the commands which would have been executed, but do not + actually execute any of them; useful for debugging top-level + makefiles without descending into subdirectories. + + -q Do not execute any commands, but exit 0 if the specified targets + are up-to-date and 1, otherwise. + + -r Do not use the built-in rules specified in the system makefile. + + -s Do not echo any commands as they are executed. Equivalent to + specifying `@' before each command line in the makefile. + + -T tracefile + When used with the -j flag, append a trace record to tracefile + for each job started and completed. + + -t Rather than re-building a target as specified in the makefile, + create it or update its modification time to make it appear up- + to-date. + + -V variable + Print the value of variable. Do not build any targets. Multiple + instances of this option may be specified; the variables will be + printed one per line, with a blank line for each null or unde- + fined variable. The value printed is extracted from the global + context after all makefiles have been read. By default, the raw + variable contents (which may include additional unexpanded vari- + able references) are shown. If variable contains a `$' then the + value will be recursively expanded to its complete resultant text + before printing. The expanded value will also be printed if + .MAKE.EXPAND_VARIABLES is set to true and the -dV option has not + been used to override it. Note that loop-local and target-local + variables, as well as values taken temporarily by global vari- + ables during makefile processing, are not accessible via this + option. The -dv debug mode can be used to see these at the cost + of generating substantial extraneous output. + + -v variable + Like -V but the variable is always expanded to its complete + value. + + -W Treat any warnings during makefile parsing as errors. + + -w Print entering and leaving directory messages, pre and post pro- + cessing. + + -X Don't export variables passed on the command line to the environ- + ment individually. Variables passed on the command line are + still exported via the MAKEFLAGS environment variable. This + option may be useful on systems which have a small limit on the + size of command arguments. + + variable=value + Set the value of the variable variable to value. Normally, all + values passed on the command line are also exported to sub-makes + in the environment. The -X flag disables this behavior. Vari- + able assignments should follow options for POSIX compatibility + but no ordering is enforced. + + There are seven different types of lines in a makefile: file dependency + specifications, shell commands, variable assignments, include statements, + conditional directives, for loops, and comments. + + In general, lines may be continued from one line to the next by ending + them with a backslash (`\'). The trailing newline character and initial + whitespace on the following line are compressed into a single space. + +FILE DEPENDENCY SPECIFICATIONS + Dependency lines consist of one or more targets, an operator, and zero or + more sources. This creates a relationship where the targets ``depend'' + on the sources and are customarily created from them. A target is con- + sidered out-of-date if it does not exist, or if its modification time is + less than that of any of its sources. An out-of-date target will be re- + created, but not until all sources have been examined and themselves re- + created as needed. Three operators may be used: + + : Many dependency lines may name this target but only one may have + attached shell commands. All sources named in all dependency lines + are considered together, and if needed the attached shell commands + are run to create or re-create the target. If bmake is inter- + rupted, the target is removed. + + ! The same, but the target is always re-created whether or not it is + out of date. + + :: Any dependency line may have attached shell commands, but each one + is handled independently: its sources are considered and the + attached shell commands are run if the target is out of date with + respect to (only) those sources. Thus, different groups of the + attached shell commands may be run depending on the circumstances. + Furthermore, unlike :, for dependency lines with no sources, the + attached shell commands are always run. Also unlike :, the target + will not be removed if bmake is interrupted. + All dependency lines mentioning a particular target must use the same + operator. + + Targets and sources may contain the shell wildcard values `?', `*', `[]', + and `{}'. The values `?', `*', and `[]' may only be used as part of the + final component of the target or source, and must be used to describe + existing files. The value `{}' need not necessarily be used to describe + existing files. Expansion is in directory order, not alphabetically as + done in the shell. + +SHELL COMMANDS + Each target may have associated with it one or more lines of shell com- + mands, normally used to create the target. Each of the lines in this + script must be preceded by a tab. (For historical reasons, spaces are + not accepted.) While targets can appear in many dependency lines if + desired, by default only one of these rules may be followed by a creation + script. If the `::' operator is used, however, all rules may include + scripts and the scripts are executed in the order found. + + Each line is treated as a separate shell command, unless the end of line + is escaped with a backslash (`\') in which case that line and the next + are combined. If the first characters of the command are any combination + of `@', `+', or `-', the command is treated specially. A `@' causes the + command not to be echoed before it is executed. A `+' causes the command + to be executed even when -n is given. This is similar to the effect of + the .MAKE special source, except that the effect can be limited to a sin- + gle line of a script. A `-' in compatibility mode causes any non-zero + exit status of the command line to be ignored. + + When bmake is run in jobs mode with -j max_jobs, the entire script for + the target is fed to a single instance of the shell. In compatibility + (non-jobs) mode, each command is run in a separate process. If the com- + mand contains any shell meta characters (`#=|^(){};&<>*?[]:$`\\n') it + will be passed to the shell; otherwise bmake will attempt direct execu- + tion. If a line starts with `-' and the shell has ErrCtl enabled then + failure of the command line will be ignored as in compatibility mode. + Otherwise `-' affects the entire job; the script will stop at the first + command line that fails, but the target will not be deemed to have + failed. + + Makefiles should be written so that the mode of bmake operation does not + change their behavior. For example, any command which needs to use + ``cd'' or ``chdir'' without potentially changing the directory for subse- + quent commands should be put in parentheses so it executes in a subshell. + To force the use of one shell, escape the line breaks so as to make the + whole script one command. For example: + + avoid-chdir-side-effects: + @echo Building $@ in `pwd` + @(cd ${.CURDIR} && ${MAKE} $@) + @echo Back in `pwd` + + ensure-one-shell-regardless-of-mode: + @echo Building $@ in `pwd`; \ + (cd ${.CURDIR} && ${MAKE} $@); \ + echo Back in `pwd` + + Since bmake will chdir(2) to `.OBJDIR' before executing any targets, each + child process starts with that as its current working directory. + +VARIABLE ASSIGNMENTS + Variables in make are much like variables in the shell, and, by tradi- + tion, consist of all upper-case letters. + + Variable assignment modifiers + The five operators that can be used to assign values to variables are as + follows: + + = Assign the value to the variable. Any previous value is overrid- + den. + + += Append the value to the current value of the variable. + + ?= Assign the value to the variable if it is not already defined. + + := Assign with expansion, i.e. expand the value before assigning it + to the variable. Normally, expansion is not done until the vari- + able is referenced. NOTE: References to undefined variables are + not expanded. This can cause problems when variable modifiers + are used. + + != Expand the value and pass it to the shell for execution and + assign the result to the variable. Any newlines in the result + are replaced with spaces. + + Any white-space before the assigned value is removed; if the value is + being appended, a single space is inserted between the previous contents + of the variable and the appended value. + + Variables are expanded by surrounding the variable name with either curly + braces (`{}') or parentheses (`()') and preceding it with a dollar sign + (`$'). If the variable name contains only a single letter, the surround- + ing braces or parentheses are not required. This shorter form is not + recommended. + + If the variable name contains a dollar, then the name itself is expanded + first. This allows almost arbitrary variable names, however names con- + taining dollar, braces, parentheses, or whitespace are really best + avoided! + + If the result of expanding a variable contains a dollar sign (`$') the + string is expanded again. + + Variable substitution occurs at three distinct times, depending on where + the variable is being used. + + 1. Variables in dependency lines are expanded as the line is read. + + 2. Variables in shell commands are expanded when the shell command is + executed. + + 3. ``.for'' loop index variables are expanded on each loop iteration. + Note that other variables are not expanded inside loops so the fol- + lowing example code: + + + .for i in 1 2 3 + a+= ${i} + j= ${i} + b+= ${j} + .endfor + + all: + @echo ${a} + @echo ${b} + + will print: + + 1 2 3 + 3 3 3 + + Because while ${a} contains ``1 2 3'' after the loop is executed, + ${b} contains ``${j} ${j} ${j}'' which expands to ``3 3 3'' since + after the loop completes ${j} contains ``3''. + + Variable classes + The four different classes of variables (in order of increasing prece- + dence) are: + + Environment variables + Variables defined as part of bmake's environment. + + Global variables + Variables defined in the makefile or in included makefiles. + + Command line variables + Variables defined as part of the command line. + + Local variables + Variables that are defined specific to a certain target. + + Local variables are all built in and their values vary magically from + target to target. It is not currently possible to define new local vari- + ables. The seven local variables are as follows: + + .ALLSRC The list of all sources for this target; also known as + `>'. + + .ARCHIVE The name of the archive file; also known as `!'. + + .IMPSRC In suffix-transformation rules, the name/path of the + source from which the target is to be transformed (the + ``implied'' source); also known as `<'. It is not + defined in explicit rules. + + .MEMBER The name of the archive member; also known as `%'. + + .OODATE The list of sources for this target that were deemed out- + of-date; also known as `?'. + + .PREFIX The file prefix of the target, containing only the file + portion, no suffix or preceding directory components; + also known as `*'. The suffix must be one of the known + suffixes declared with .SUFFIXES or it will not be recog- + nized. + + .TARGET The name of the target; also known as `@'. For compati- + bility with other makes this is an alias for .ARCHIVE in + archive member rules. + + The shorter forms (`>', `!', `<', `%', `?', `*', and `@') are permitted + for backward compatibility with historical makefiles and legacy POSIX + make and are not recommended. + + Variants of these variables with the punctuation followed immediately by + `D' or `F', e.g. `$(@D)', are legacy forms equivalent to using the `:H' + and `:T' modifiers. These forms are accepted for compatibility with AT&T + System V UNIX makefiles and POSIX but are not recommended. + + Four of the local variables may be used in sources on dependency lines + because they expand to the proper value for each target on the line. + These variables are `.TARGET', `.PREFIX', `.ARCHIVE', and `.MEMBER'. + + Additional built-in variables + In addition, bmake sets or knows about the following variables: + + $ A single dollar sign `$', i.e. `$$' expands to a single + dollar sign. + + .ALLTARGETS The list of all targets encountered in the Makefile. If + evaluated during Makefile parsing, lists only those tar- + gets encountered thus far. + + .CURDIR A path to the directory where bmake was executed. Refer + to the description of `PWD' for more details. + + .INCLUDEDFROMDIR + The directory of the file this Makefile was included + from. + + .INCLUDEDFROMFILE + The filename of the file this Makefile was included from. + + MAKE The name that bmake was executed with (argv[0]). For + compatibility bmake also sets .MAKE with the same value. + The preferred variable to use is the environment variable + MAKE because it is more compatible with other versions of + bmake and cannot be confused with the special target with + the same name. + + .MAKE.DEPENDFILE + Names the makefile (default `.depend') from which gener- + ated dependencies are read. + + .MAKE.EXPAND_VARIABLES + A boolean that controls the default behavior of the -V + option. If true, variable values printed with -V are + fully expanded; if false, the raw variable contents + (which may include additional unexpanded variable refer- + ences) are shown. + + .MAKE.EXPORTED The list of variables exported by bmake. + + .MAKE.JOBS The argument to the -j option. + + .MAKE.JOB.PREFIX + If bmake is run with j then output for each target is + prefixed with a token `--- target ---' the first part of + which can be controlled via .MAKE.JOB.PREFIX. If + .MAKE.JOB.PREFIX is empty, no token is printed. + For example: + .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}] + would produce tokens like `---make[1234] target ---' mak- + ing it easier to track the degree of parallelism being + achieved. + + MAKEFLAGS The environment variable `MAKEFLAGS' may contain anything + that may be specified on bmake's command line. Anything + specified on bmake's command line is appended to the + `MAKEFLAGS' variable which is then entered into the envi- + ronment for all programs which bmake executes. + + .MAKE.LEVEL The recursion depth of bmake. The initial instance of + bmake will be 0, and an incremented value is put into the + environment to be seen by the next generation. This + allows tests like: .if ${.MAKE.LEVEL} == 0 to protect + things which should only be evaluated in the initial + instance of bmake. + + .MAKE.MAKEFILE_PREFERENCE + The ordered list of makefile names (default `makefile', + `Makefile') that bmake will look for. + + .MAKE.MAKEFILES + The list of makefiles read by bmake, which is useful for + tracking dependencies. Each makefile is recorded only + once, regardless of the number of times read. + + .MAKE.MODE Processed after reading all makefiles. Can affect the + mode that bmake runs in. It can contain a number of key- + words: + + compat Like -B, puts bmake into "compat" + mode. + + meta Puts bmake into "meta" mode, where + meta files are created for each tar- + get to capture the command run, the + output generated and if filemon(4) + is available, the system calls which + are of interest to bmake. The cap- + tured output can be very useful when + diagnosing errors. + + curdirOk= bf Normally bmake will not create .meta + files in `.CURDIR'. This can be + overridden by setting bf to a value + which represents True. + + missing-meta= bf If bf is True, then a missing .meta + file makes the target out-of-date. + + missing-filemon= bf If bf is True, then missing filemon + data makes the target out-of-date. + + nofilemon Do not use filemon(4). + + env For debugging, it can be useful to + include the environment in the .meta + file. + + verbose If in "meta" mode, print a clue + about the target being built. This + is useful if the build is otherwise + running silently. The message + printed the value of: + .MAKE.META.PREFIX. + + ignore-cmd Some makefiles have commands which + are simply not stable. This keyword + causes them to be ignored for deter- + mining whether a target is out of + date in "meta" mode. See also + .NOMETA_CMP. + + silent= bf If bf is True, when a .meta file is + created, mark the target .SILENT. + + .MAKE.META.BAILIWICK + In "meta" mode, provides a list of prefixes which match + the directories controlled by bmake. If a file that was + generated outside of .OBJDIR but within said bailiwick is + missing, the current target is considered out-of-date. + + .MAKE.META.CREATED + In "meta" mode, this variable contains a list of all the + meta files updated. If not empty, it can be used to + trigger processing of .MAKE.META.FILES. + + .MAKE.META.FILES + In "meta" mode, this variable contains a list of all the + meta files used (updated or not). This list can be used + to process the meta files to extract dependency informa- + tion. + + .MAKE.META.IGNORE_PATHS + Provides a list of path prefixes that should be ignored; + because the contents are expected to change over time. + The default list includes: `/dev /etc /proc /tmp /var/run + /var/tmp' + + .MAKE.META.IGNORE_PATTERNS + Provides a list of patterns to match against pathnames. + Ignore any that match. + + .MAKE.META.IGNORE_FILTER + Provides a list of variable modifiers to apply to each + pathname. Ignore if the expansion is an empty string. + + .MAKE.META.PREFIX + Defines the message printed for each meta file updated in + "meta verbose" mode. The default value is: + Building ${.TARGET:H:tA}/${.TARGET:T} + + .MAKEOVERRIDES This variable is used to record the names of variables + assigned to on the command line, so that they may be + exported as part of `MAKEFLAGS'. This behavior can be + disabled by assigning an empty value to `.MAKEOVERRIDES' + within a makefile. Extra variables can be exported from + a makefile by appending their names to `.MAKEOVERRIDES'. + `MAKEFLAGS' is re-exported whenever `.MAKEOVERRIDES' is + modified. + + .MAKE.PATH_FILEMON + If bmake was built with filemon(4) support, this is set + to the path of the device node. This allows makefiles to + test for this support. + + .MAKE.PID The process-id of bmake. + + .MAKE.PPID The parent process-id of bmake. + + .MAKE.SAVE_DOLLARS + value should be a boolean that controls whether `$$' are + preserved when doing `:=' assignments. The default is + false, for backwards compatibility. Set to true for com- + patability with other makes. If set to false, `$$' + becomes `$' per normal evaluation rules. + + MAKE_PRINT_VAR_ON_ERROR + When bmake stops due to an error, it sets `.ERROR_TARGET' + to the name of the target that failed, `.ERROR_CMD' to + the commands of the failed target, and in "meta" mode, it + also sets `.ERROR_CWD' to the getcwd(3), and + `.ERROR_META_FILE' to the path of the meta file (if any) + describing the failed target. It then prints its name + and the value of `.CURDIR' as well as the value of any + variables named in `MAKE_PRINT_VAR_ON_ERROR'. + + .newline This variable is simply assigned a newline character as + its value. This allows expansions using the :@ modifier + to put a newline between iterations of the loop rather + than a space. For example, the printing of + `MAKE_PRINT_VAR_ON_ERROR' could be done as + ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}. + + .OBJDIR A path to the directory where the targets are built. Its + value is determined by trying to chdir(2) to the follow- + ing directories in order and using the first match: + + 1. ${MAKEOBJDIRPREFIX}${.CURDIR} + + (Only if `MAKEOBJDIRPREFIX' is set in the environ- + ment or on the command line.) + + 2. ${MAKEOBJDIR} + + (Only if `MAKEOBJDIR' is set in the environment or + on the command line.) + + 3. ${.CURDIR}/obj.${MACHINE} + + 4. ${.CURDIR}/obj + + 5. /usr/obj/${.CURDIR} + + 6. ${.CURDIR} + + Variable expansion is performed on the value before it's + used, so expressions such as + ${.CURDIR:S,^/usr/src,/var/obj,} + may be used. This is especially useful with + `MAKEOBJDIR'. + + `.OBJDIR' may be modified in the makefile via the special + target `.OBJDIR'. In all cases, bmake will chdir(2) to + the specified directory if it exists, and set `.OBJDIR' + and `PWD' to that directory before executing any targets. + + .PARSEDIR A path to the directory of the current `Makefile' being + parsed. + + .PARSEFILE The basename of the current `Makefile' being parsed. + This variable and `.PARSEDIR' are both set only while the + `Makefiles' are being parsed. If you want to retain + their current values, assign them to a variable using + assignment with expansion: (`:='). + + .PATH A variable that represents the list of directories that + bmake will search for files. The search list should be + updated using the target `.PATH' rather than the vari- + able. + + PWD Alternate path to the current directory. bmake normally + sets `.CURDIR' to the canonical path given by getcwd(3). + However, if the environment variable `PWD' is set and + gives a path to the current directory, then bmake sets + `.CURDIR' to the value of `PWD' instead. This behavior + is disabled if `MAKEOBJDIRPREFIX' is set or `MAKEOBJDIR' + contains a variable transform. `PWD' is set to the value + of `.OBJDIR' for all programs which bmake executes. + + .SHELL The pathname of the shell used to run target scripts. It + is read-only. + + .TARGETS The list of targets explicitly specified on the command + line, if any. + + VPATH Colon-separated (``:'') lists of directories that bmake + will search for files. The variable is supported for + compatibility with old make programs only, use `.PATH' + instead. + + Variable modifiers + Variable expansion may be modified to select or modify each word of the + variable (where a ``word'' is white-space delimited sequence of charac- + ters). The general format of a variable expansion is as follows: + + ${variable[:modifier[:...]]} + + Each modifier begins with a colon, which may be escaped with a backslash + (`\'). + + A set of modifiers can be specified via a variable, as follows: + + modifier_variable=modifier[:...] + ${variable:${modifier_variable}[:...]} + + In this case the first modifier in the modifier_variable does not start + with a colon, since that must appear in the referencing variable. If any + of the modifiers in the modifier_variable contain a dollar sign (`$'), + these must be doubled to avoid early expansion. + + The supported modifiers are: + + :E Replaces each word in the variable with its suffix. + + :H Replaces each word in the variable with everything but the last com- + ponent. + + :Mpattern + Selects only those words that match pattern. The standard shell + wildcard characters (`*', `?', and `[]') may be used. The wildcard + characters may be escaped with a backslash (`\'). As a consequence + of the way values are split into words, matched, and then joined, a + construct like + ${VAR:M*} + will normalize the inter-word spacing, removing all leading and + trailing space, and converting multiple consecutive spaces to single + spaces. + + :Npattern + This is identical to `:M', but selects all words which do not match + pattern. + + :O Orders every word in variable alphabetically. + + :Or Orders every word in variable in reverse alphabetical order. + + :Ox Shuffles the words in variable. The results will be different each + time you are referring to the modified variable; use the assignment + with expansion (`:=') to prevent such behavior. For example, + + LIST= uno due tre quattro + RANDOM_LIST= ${LIST:Ox} + STATIC_RANDOM_LIST:= ${LIST:Ox} + + all: + @echo "${RANDOM_LIST}" + @echo "${RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" + may produce output similar to: + + quattro due tre uno + tre due quattro uno + due uno quattro tre + due uno quattro tre + + :Q Quotes every shell meta-character in the variable, so that it can be + passed safely to the shell. + + :q Quotes every shell meta-character in the variable, and also doubles + `$' characters so that it can be passed safely through recursive + invocations of bmake. This is equivalent to: `:S/\$/&&/g:Q'. + + :R Replaces each word in the variable with everything but its suffix. + + :range[=count] + The value is an integer sequence representing the words of the orig- + inal value, or the supplied count. + + :gmtime[=utc] + The value is a format string for strftime(3), using gmtime(3). If a + utc value is not provided or is 0, the current time is used. + + :hash + Computes a 32-bit hash of the value and encode it as hex digits. + + :localtime[=utc] + The value is a format string for strftime(3), using localtime(3). + If a utc value is not provided or is 0, the current time is used. + + :tA Attempts to convert variable to an absolute path using realpath(3), + if that fails, the value is unchanged. + + :tl Converts variable to lower-case letters. + + :tsc + Words in the variable are normally separated by a space on expan- + sion. This modifier sets the separator to the character c. If c is + omitted, then no separator is used. The common escapes (including + octal numeric codes) work as expected. + + :tu Converts variable to upper-case letters. + + :tW Causes the value to be treated as a single word (possibly containing + embedded white space). See also `:[*]'. + + :tw Causes the value to be treated as a sequence of words delimited by + white space. See also `:[@]'. + + :S/old_string/new_string/[1gW] + Modifies the first occurrence of old_string in each word of the + variable's value, replacing it with new_string. If a `g' is + appended to the last delimiter of the pattern, all occurrences in + each word are replaced. If a `1' is appended to the last delimiter + of the pattern, only the first occurrence is affected. If a `W' is + appended to the last delimiter of the pattern, then the value is + treated as a single word (possibly containing embedded white space). + If old_string begins with a caret (`^'), old_string is anchored at + the beginning of each word. If old_string ends with a dollar sign + (`$'), it is anchored at the end of each word. Inside new_string, + an ampersand (`&') is replaced by old_string (without any `^' or + `$'). Any character may be used as a delimiter for the parts of the + modifier string. The anchoring, ampersand and delimiter characters + may be escaped with a backslash (`\'). + + Variable expansion occurs in the normal fashion inside both + old_string and new_string with the single exception that a backslash + is used to prevent the expansion of a dollar sign (`$'), not a pre- + ceding dollar sign as is usual. + + :C/pattern/replacement/[1gW] + The :C modifier is just like the :S modifier except that the old and + new strings, instead of being simple strings, are an extended regu- + lar expression (see regex(3)) string pattern and an ed(1)-style + string replacement. Normally, the first occurrence of the pattern + pattern in each word of the value is substituted with replacement. + The `1' modifier causes the substitution to apply to at most one + word; the `g' modifier causes the substitution to apply to as many + instances of the search pattern pattern as occur in the word or + words it is found in; the `W' modifier causes the value to be + treated as a single word (possibly containing embedded white space). + + As for the :S modifier, the pattern and replacement are subjected to + variable expansion before being parsed as regular expressions. + + :T Replaces each word in the variable with its last path component. + + :u Removes adjacent duplicate words (like uniq(1)). + + :?true_string:false_string + If the variable name (not its value), when parsed as a .if condi- + tional expression, evaluates to true, return as its value the + true_string, otherwise return the false_string. Since the variable + name is used as the expression, :? must be the first modifier after + the variable name itself - which will, of course, usually contain + variable expansions. A common error is trying to use expressions + like + ${NUMBERS:M42:?match:no} + which actually tests defined(NUMBERS), to determine if any words + match "42" you need to use something like: + ${"${NUMBERS:M42}" != "":?match:no}. + + :old_string=new_string + This is the AT&T System V UNIX style variable substitution. It must + be the last modifier specified. If old_string or new_string do not + contain the pattern matching character % then it is assumed that + they are anchored at the end of each word, so only suffixes or + entire words may be replaced. Otherwise % is the substring of + old_string to be replaced in new_string. If only old_string con- + tains the pattern matching character %, and old_string matches, then + the result is the new_string. If only the new_string contains the + pattern matching character %, then it is not treated specially and + it is printed as a literal % on match. If there is more than one + pattern matching character (%) in either the new_string or + old_string, only the first instance is treated specially (as the + pattern character); all subsequent instances are treated as regular + characters. + + Variable expansion occurs in the normal fashion inside both + old_string and new_string with the single exception that a backslash + is used to prevent the expansion of a dollar sign (`$'), not a pre- + ceding dollar sign as is usual. + + :@temp@string@ + This is the loop expansion mechanism from the OSF Development Envi- + ronment (ODE) make. Unlike .for loops, expansion occurs at the time + of reference. Assigns temp to each word in the variable and evalu- + ates string. The ODE convention is that temp should start and end + with a period. For example. + ${LINKS:@.LINK.@${LN} ${TARGET} ${.LINK.}@} + + However a single character variable is often more readable: + ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@} + + :_[=var] + Saves the current variable value in `$_' or the named var for later + reference. Example usage: + + M_cmpv.units = 1 1000 1000000 + M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \ + \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh + + .if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}} + + Here `$_' is used to save the result of the `:S' modifier which is + later referenced using the index values from `:range'. + + :Unewval + If the variable is undefined, newval is the value. If the variable + is defined, the existing value is returned. This is another ODE + make feature. It is handy for setting per-target CFLAGS for + instance: + ${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}} + If a value is only required if the variable is undefined, use: + ${VAR:D:Unewval} + + :Dnewval + If the variable is defined, newval is the value. + + :L The name of the variable is the value. + + :P The path of the node which has the same name as the variable is the + value. If no such node exists or its path is null, then the name of + the variable is used. In order for this modifier to work, the name + (node) must at least have appeared on the rhs of a dependency. + + :!cmd! + The output of running cmd is the value. + + :sh If the variable is non-empty it is run as a command and the output + becomes the new value. + + ::=str + The variable is assigned the value str after substitution. This + modifier and its variations are useful in obscure situations such as + wanting to set a variable when shell commands are being parsed. + These assignment modifiers always expand to nothing, so if appearing + in a rule line by themselves should be preceded with something to + keep bmake happy. + + The `::' helps avoid false matches with the AT&T System V UNIX style + := modifier and since substitution always occurs the ::= form is + vaguely appropriate. + + ::?=str + As for ::= but only if the variable does not already have a value. + + ::+=str + Append str to the variable. + + ::!=cmd + Assign the output of cmd to the variable. + + :[range] + Selects one or more words from the value, or performs other opera- + tions related to the way in which the value is divided into words. + + Ordinarily, a value is treated as a sequence of words delimited by + white space. Some modifiers suppress this behavior, causing a value + to be treated as a single word (possibly containing embedded white + space). An empty value, or a value that consists entirely of white- + space, is treated as a single word. For the purposes of the `:[]' + modifier, the words are indexed both forwards using positive inte- + gers (where index 1 represents the first word), and backwards using + negative integers (where index -1 represents the last word). + + The range is subjected to variable expansion, and the expanded + result is then interpreted as follows: + + index Selects a single word from the value. + + start..end + Selects all words from start to end, inclusive. For example, + `:[2..-1]' selects all words from the second word to the last + word. If start is greater than end, then the words are out- + put in reverse order. For example, `:[-1..1]' selects all + the words from last to first. If the list is already + ordered, then this effectively reverses the list, but it is + more efficient to use `:Or' instead of `:O:[-1..1]'. + + * Causes subsequent modifiers to treat the value as a single + word (possibly containing embedded white space). Analogous + to the effect of "$*" in Bourne shell. + + 0 Means the same as `:[*]'. + + @ Causes subsequent modifiers to treat the value as a sequence + of words delimited by white space. Analogous to the effect + of "$@" in Bourne shell. + + # Returns the number of words in the value. + +INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS + Makefile inclusion, conditional structures and for loops reminiscent of + the C programming language are provided in bmake. All such structures + are identified by a line beginning with a single dot (`.') character. + Files are included with either .include <file> or .include "file". Vari- + ables between the angle brackets or double quotes are expanded to form + the file name. If angle brackets are used, the included makefile is + expected to be in the system makefile directory. If double quotes are + used, the including makefile's directory and any directories specified + using the -I option are searched before the system makefile directory. + For compatibility with other versions of bmake `include file ...' is also + accepted. + + If the include statement is written as .-include or as .sinclude then + errors locating and/or opening include files are ignored. + + If the include statement is written as .dinclude not only are errors + locating and/or opening include files ignored, but stale dependencies + within the included file will be ignored just like .MAKE.DEPENDFILE. + + Conditional expressions are also preceded by a single dot as the first + character of a line. The possible conditionals are as follows: + + .error message + The message is printed along with the name of the makefile and + line number, then bmake will exit immediately. + + .export variable ... + Export the specified global variable. If no variable list is + provided, all globals are exported except for internal variables + (those that start with `.'). This is not affected by the -X + flag, so should be used with caution. For compatibility with + other bmake programs `export variable=value' is also accepted. + + Appending a variable name to .MAKE.EXPORTED is equivalent to + exporting a variable. + + .export-env variable ... + The same as `.export', except that the variable is not appended + to .MAKE.EXPORTED. This allows exporting a value to the environ- + ment which is different from that used by bmake internally. + + .export-literal variable ... + The same as `.export-env', except that variables in the value are + not expanded. + + .info message + The message is printed along with the name of the makefile and + line number. + + .undef variable + Un-define the specified global variable. Only global variables + may be un-defined. + + .unexport variable ... + The opposite of `.export'. The specified global variable will be + removed from .MAKE.EXPORTED. If no variable list is provided, + all globals are unexported, and .MAKE.EXPORTED deleted. + + .unexport-env + Unexport all globals previously exported and clear the environ- + ment inherited from the parent. This operation will cause a mem- + ory leak of the original environment, so should be used spar- + ingly. Testing for .MAKE.LEVEL being 0, would make sense. Also + note that any variables which originated in the parent environ- + ment should be explicitly preserved if desired. For example: + + .if ${.MAKE.LEVEL} == 0 + PATH := ${PATH} + .unexport-env + .export PATH + .endif + + Would result in an environment containing only `PATH', which is + the minimal useful environment. Actually `.MAKE.LEVEL' will also + be pushed into the new environment. + + .warning message + The message prefixed by `warning:' is printed along with the name + of the makefile and line number. + + .if [!]expression [operator expression ...] + Test the value of an expression. + + .ifdef [!]variable [operator variable ...] + Test the value of a variable. + + .ifndef [!]variable [operator variable ...] + Test the value of a variable. + + .ifmake [!]target [operator target ...] + Test the target being built. + + .ifnmake [!] target [operator target ...] + Test the target being built. + + .else Reverse the sense of the last conditional. + + .elif [!] expression [operator expression ...] + A combination of `.else' followed by `.if'. + + .elifdef [!]variable [operator variable ...] + A combination of `.else' followed by `.ifdef'. + + .elifndef [!]variable [operator variable ...] + A combination of `.else' followed by `.ifndef'. + + .elifmake [!]target [operator target ...] + A combination of `.else' followed by `.ifmake'. + + .elifnmake [!]target [operator target ...] + A combination of `.else' followed by `.ifnmake'. + + .endif End the body of the conditional. + + The operator may be any one of the following: + + || Logical OR. + + && Logical AND; of higher precedence than ``||''. + + As in C, bmake will only evaluate a conditional as far as is necessary to + determine its value. Parentheses may be used to change the order of + evaluation. The boolean operator `!' may be used to logically negate an + entire conditional. It is of higher precedence than `&&'. + + The value of expression may be any of the following: + + defined Takes a variable name as an argument and evaluates to true if + the variable has been defined. + + make Takes a target name as an argument and evaluates to true if the + target was specified as part of bmake's command line or was + declared the default target (either implicitly or explicitly, + see .MAIN) before the line containing the conditional. + + empty Takes a variable, with possible modifiers, and evaluates to true + if the expansion of the variable would result in an empty + string. + + exists Takes a file name as an argument and evaluates to true if the + file exists. The file is searched for on the system search path + (see .PATH). + + target Takes a target name as an argument and evaluates to true if the + target has been defined. + + commands + Takes a target name as an argument and evaluates to true if the + target has been defined and has commands associated with it. + + Expression may also be an arithmetic or string comparison. Variable + expansion is performed on both sides of the comparison, after which the + numerical values are compared. A value is interpreted as hexadecimal if + it is preceded by 0x, otherwise it is decimal; octal numbers are not sup- + ported. The standard C relational operators are all supported. If after + variable expansion, either the left or right hand side of a `==' or `!=' + operator is not a numerical value, then string comparison is performed + between the expanded variables. If no relational operator is given, it + is assumed that the expanded variable is being compared against 0, or an + empty string in the case of a string comparison. + + When bmake is evaluating one of these conditional expressions, and it + encounters a (white-space separated) word it doesn't recognize, either + the ``make'' or ``defined'' expression is applied to it, depending on the + form of the conditional. If the form is `.ifdef', `.ifndef', or `.if' + the ``defined'' expression is applied. Similarly, if the form is + `.ifmake' or `.ifnmake', the ``make'' expression is applied. + + If the conditional evaluates to true the parsing of the makefile contin- + ues as before. If it evaluates to false, the following lines are + skipped. In both cases this continues until a `.else' or `.endif' is + found. + + For loops are typically used to apply a set of rules to a list of files. + The syntax of a for loop is: + + .for variable [variable ...] in expression + + .endfor + + After the for expression is evaluated, it is split into words. On each + iteration of the loop, one word is taken and assigned to each variable, + in order, and these variables are substituted into the make-lines inside + the body of the for loop. The number of words must come out even; that + is, if there are three iteration variables, the number of words provided + must be a multiple of three. + +COMMENTS + Comments begin with a hash (`#') character, anywhere but in a shell com- + mand line, and continue to the end of an unescaped new line. + +SPECIAL SOURCES (ATTRIBUTES) + .EXEC Target is never out of date, but always execute commands any- + way. + + .IGNORE Ignore any errors from the commands associated with this tar- + get, exactly as if they all were preceded by a dash (`-'). + + .MADE Mark all sources of this target as being up-to-date. + + .MAKE Execute the commands associated with this target even if the -n + or -t options were specified. Normally used to mark recursive + bmakes. + + .META Create a meta file for the target, even if it is flagged as + .PHONY, .MAKE, or .SPECIAL. Usage in conjunction with .MAKE is + the most likely case. In "meta" mode, the target is out-of- + date if the meta file is missing. + + .NOMETA Do not create a meta file for the target. Meta files are also + not created for .PHONY, .MAKE, or .SPECIAL targets. + + .NOMETA_CMP + Ignore differences in commands when deciding if target is out + of date. This is useful if the command contains a value which + always changes. If the number of commands change, though, the + target will still be out of date. The same effect applies to + any command line that uses the variable .OODATE, which can be + used for that purpose even when not otherwise needed or + desired: + + + skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + + The :M pattern suppresses any expansion of the unwanted vari- + able. + + .NOPATH Do not search for the target in the directories specified by + .PATH. + + .NOTMAIN Normally bmake selects the first target it encounters as the + default target to be built if no target was specified. This + source prevents this target from being selected. + + .OPTIONAL + If a target is marked with this attribute and bmake can't fig- + ure out how to create it, it will ignore this fact and assume + the file isn't needed or already exists. + + .PHONY The target does not correspond to an actual file; it is always + considered to be out of date, and will not be created with the + -t option. Suffix-transformation rules are not applied to + .PHONY targets. + + .PRECIOUS + When bmake is interrupted, it normally removes any partially + made targets. This source prevents the target from being + removed. + + .RECURSIVE + Synonym for .MAKE. + + .SILENT Do not echo any of the commands associated with this target, + exactly as if they all were preceded by an at sign (`@'). + + .USE Turn the target into bmake's version of a macro. When the tar- + get is used as a source for another target, the other target + acquires the commands, sources, and attributes (except for + .USE) of the source. If the target already has commands, the + .USE target's commands are appended to them. + + .USEBEFORE + Exactly like .USE, but prepend the .USEBEFORE target commands + to the target. + + .WAIT If .WAIT appears in a dependency line, the sources that precede + it are made before the sources that succeed it in the line. + Since the dependents of files are not made until the file + itself could be made, this also stops the dependents being + built unless they are needed for another branch of the depen- + dency tree. So given: + + x: a .WAIT b + echo x + a: + echo a + b: b1 + echo b + b1: + echo b1 + + the output is always `a', `b1', `b', `x'. + The ordering imposed by .WAIT is only relevant for parallel + makes. + +SPECIAL TARGETS + Special targets may not be included with other targets, i.e. they must be + the only target specified. + + .BEGIN Any command lines attached to this target are executed before + anything else is done. + + .DEFAULT + This is sort of a .USE rule for any target (that was used only + as a source) that bmake can't figure out any other way to cre- + ate. Only the shell script is used. The .IMPSRC variable of a + target that inherits .DEFAULT's commands is set to the target's + own name. + + .DELETE_ON_ERROR + If this target is present in the makefile, it globally causes + make to delete targets whose commands fail. (By default, only + targets whose commands are interrupted during execution are + deleted. This is the historical behavior.) This setting can be + used to help prevent half-finished or malformed targets from + being left around and corrupting future rebuilds. + + .END Any command lines attached to this target are executed after + everything else is done. + + .ERROR Any command lines attached to this target are executed when + another target fails. The .ERROR_TARGET variable is set to the + target that failed. See also MAKE_PRINT_VAR_ON_ERROR. + + .IGNORE Mark each of the sources with the .IGNORE attribute. If no + sources are specified, this is the equivalent of specifying the + -i option. + + .INTERRUPT + If bmake is interrupted, the commands for this target will be + executed. + + .MAIN If no target is specified when bmake is invoked, this target + will be built. + + .MAKEFLAGS + This target provides a way to specify flags for bmake when the + makefile is used. The flags are as if typed to the shell, + though the -f option will have no effect. + + .NOPATH Apply the .NOPATH attribute to any specified sources. + + .NOTPARALLEL + Disable parallel mode. + + .NO_PARALLEL + Synonym for .NOTPARALLEL, for compatibility with other pmake + variants. + + .OBJDIR The source is a new value for `.OBJDIR'. If it exists, bmake + will chdir(2) to it and update the value of `.OBJDIR'. + + .ORDER The named targets are made in sequence. This ordering does not + add targets to the list of targets to be made. Since the depen- + dents of a target do not get built until the target itself could + be built, unless `a' is built by another part of the dependency + graph, the following is a dependency loop: + + .ORDER: b a + b: a + + The ordering imposed by .ORDER is only relevant for parallel + makes. + + .PATH The sources are directories which are to be searched for files + not found in the current directory. If no sources are speci- + fied, any previously specified directories are deleted. If the + source is the special .DOTLAST target, then the current working + directory is searched last. + + .PATH.suffix + Like .PATH but applies only to files with a particular suffix. + The suffix must have been previously declared with .SUFFIXES. + + .PHONY Apply the .PHONY attribute to any specified sources. + + .PRECIOUS + Apply the .PRECIOUS attribute to any specified sources. If no + sources are specified, the .PRECIOUS attribute is applied to + every target in the file. + + .SHELL Sets the shell that bmake will use to execute commands. The + sources are a set of field=value pairs. + + name This is the minimal specification, used to select + one of the built-in shell specs; sh, ksh, and csh. + + path Specifies the path to the shell. + + hasErrCtl Indicates whether the shell supports exit on error. + + check The command to turn on error checking. + + ignore The command to disable error checking. + + echo The command to turn on echoing of commands executed. + + quiet The command to turn off echoing of commands exe- + cuted. + + filter The output to filter after issuing the quiet com- + mand. It is typically identical to quiet. + + errFlag The flag to pass the shell to enable error checking. + + echoFlag The flag to pass the shell to enable command echo- + ing. + + newline The string literal to pass the shell that results in + a single newline character when used outside of any + quoting characters. + Example: + + .SHELL: name=ksh path=/bin/ksh hasErrCtl=true \ + check="set -e" ignore="set +e" \ + echo="set -v" quiet="set +v" filter="set +v" \ + echoFlag=v errFlag=e newline="'\n'" + + .SILENT Apply the .SILENT attribute to any specified sources. If no + sources are specified, the .SILENT attribute is applied to every + command in the file. + + .STALE This target gets run when a dependency file contains stale + entries, having .ALLSRC set to the name of that dependency file. + + .SUFFIXES + Each source specifies a suffix to bmake. If no sources are + specified, any previously specified suffixes are deleted. It + allows the creation of suffix-transformation rules. + + Example: + + .SUFFIXES: .o + .c.o: + cc -o ${.TARGET} -c ${.IMPSRC} + +ENVIRONMENT + bmake uses the following environment variables, if they exist: MACHINE, + MACHINE_ARCH, MAKE, MAKEFLAGS, MAKEOBJDIR, MAKEOBJDIRPREFIX, MAKESYSPATH, + PWD, and TMPDIR. + + MAKEOBJDIRPREFIX and MAKEOBJDIR may only be set in the environment or on + the command line to bmake and not as makefile variables; see the descrip- + tion of `.OBJDIR' for more details. + +FILES + .depend list of dependencies + Makefile list of dependencies + makefile list of dependencies + sys.mk system makefile + /usr/share/mk system makefile directory + +COMPATIBILITY + The basic make syntax is compatible between different versions of make; + however the special variables, variable modifiers and conditionals are + not. + + Older versions + An incomplete list of changes in older versions of bmake: + + The way that .for loop variables are substituted changed after NetBSD 5.0 + so that they still appear to be variable expansions. In particular this + stops them being treated as syntax, and removes some obscure problems + using them in .if statements. + + The way that parallel makes are scheduled changed in NetBSD 4.0 so that + .ORDER and .WAIT apply recursively to the dependent nodes. The algo- + rithms used may change again in the future. + + Other make dialects + Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not sup- + port most of the features of bmake as described in this manual. Most + notably: + + +o The .WAIT and .ORDER declarations and most functionality per- + taining to parallelization. (GNU make supports parallelization + but lacks these features needed to control it effectively.) + + +o Directives, including for loops and conditionals and most of + the forms of include files. (GNU make has its own incompatible + and less powerful syntax for conditionals.) + + +o All built-in variables that begin with a dot. + + +o Most of the special sources and targets that begin with a dot, + with the notable exception of .PHONY, .PRECIOUS, and .SUFFIXES. + + +o Variable modifiers, except for the + :old=new + string substitution, which does not portably support globbing + with `%' and historically only works on declared suffixes. + + +o The $> variable even in its short form; most makes support this + functionality but its name varies. + + Some features are somewhat more portable, such as assignment with +=, ?=, + and !=. The .PATH functionality is based on an older feature VPATH found + in GNU make and many versions of SVR4 make; however, historically its + behavior is too ill-defined (and too buggy) to rely upon. + + The $@ and $< variables are more or less universally portable, as is the + $(MAKE) variable. Basic use of suffix rules (for files only in the cur- + rent directory, not trying to chain transformations together, etc.) is + also reasonably portable. + +SEE ALSO + mkdep(1) + +HISTORY + bmake is derived from NetBSD make(1). It uses autoconf to facilitate + portability to other platforms. + + A make command appeared in Version 7 AT&T UNIX. This make implementation + is based on Adam De Boor's pmake program which was written for Sprite at + Berkeley. It was designed to be a parallel distributed make running jobs + on different machines using a daemon called ``customs''. + + Historically the target/dependency ``FRC'' has been used to FoRCe + rebuilding (since the target/dependency does not exist... unless someone + creates an ``FRC'' file). + +BUGS + The make syntax is difficult to parse without actually acting on the + data. For instance, finding the end of a variable's use should involve + scanning each of the modifiers, using the correct terminator for each + field. In many places make just counts {} and () in order to find the + end of a variable expansion. + + There is no way of escaping a space character in a filename. + +FreeBSD 11.3 November 1, 2020 FreeBSD 11.3 Index: vendor/NetBSD/bmake/20201101/boot-strap =================================================================== --- vendor/NetBSD/bmake/20201101/boot-strap (nonexistent) +++ vendor/NetBSD/bmake/20201101/boot-strap (revision 367461) @@ -0,0 +1,483 @@ +: +# NAME: +# boot-strap +# +# SYNOPSIS: +# boot-strap ["options"] +# boot-strap --prefix=/opt --install +# boot-strap --prefix=$HOME --install-host-target -DWITH_PROG_VERSION +# boot-strap ["options"] op=build +# boot-strap ["options"] op=install +# +# DESCRIPTION: +# This script is used to configure/build bmake it builds for +# each host-target in a different subdir to keep the src clean. +# There is no requirement for an existing make(1). +# +# On successful completion if no '--install' flag is given, +# it echos a command to do installation. +# +# The variable "op" defaults to 'all', and is affected by +# '--install' flag as above. +# Other values include: +# +# configure +# Just run 'configure' +# +# build +# If 'configure' has not been done, do it, then +# run the build script, and finally 'test'. +# +# install +# If 'build' has not been done, do it, 'test' then +# install. +# +# clean +# attempt to clean up +# +# test +# run the unit-tests. Done automatically after 'build' +# and before 'install'. +# +# The above are leveraged by a trivial makefile for the benefit +# of those that have './configure; make; make install' baked +# into them. +# +# Options: +# +# -c "rc" +# Pick up settings from "rc". +# We look for '.bmake-boot-strap.rc' before processing +# options (unless SKIP_RC is set in environment). +# +# --share "share_dir" +# Where to put man pages and mk files. +# If $prefix ends in $HOST_TARGET, and $prefix/../share +# exits, the default will be that rather than $prefix/share. +# +# --mksrc "mksrc" +# Indicate where the mk files can be found. +# Default is $Mydir/mk +# +# --install +# If build and test work, run bmake install. +# BINDIR=$prefix/bin +# SHAREDIR=$prefix/share +# +# --install-host-target +# As for '--install' but BINDIR=$prefix/$HOST_TARGET/bin +# This is useful when $prefix/ is shared by multiple +# machines. +# +# Flags relevant when installing: +# +# -DWITHOUT_INSTALL_MK +# Skip installing mk files. +# By default they will be installed to $prefix/share/mk +# +# -DWITH_PROG_VERSION +# Install 'bmake' as 'bmake-$MAKE_VERSION' +# A symlink will be made as 'bmake' unless +# -DWITHOUT_PROG_LINK is set. +# +# Possibly useful configure_args: +# +# --without-meta +# disable use of meta mode. +# +# --without-filemon +# disable use of filemon(9) which is currently only +# available for NetBSD and FreeBSD. +# +# --with-filemon=ktrace +# on NetBSD or others with fktrace(2), use ktrace +# version of filemon. +# +# --with-filemon="path/to/filemon.h" +# enables use of filemon(9) by meta mode. +# +# --with-machine="machine" +# set "machine" to override that determined by +# machine.sh +# +# --with-force-machine="machine" +# force "machine" even if uname(3) provides a value. +# +# --with-machine_arch="machine_arch" +# set "machine_arch" to override that determined by +# machine.sh +# +# --with-default-sys-path="syspath" +# set an explicit default "syspath" which is where bmake +# will look for sys.mk and friends. +# +# AUTHOR: +# Simon J. Gerraty + +# RCSid: +# $Id: boot-strap,v 1.53 2020/09/16 02:12:01 sjg Exp $ +# +# @(#) Copyright (c) 2001 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +Mydir=`dirname $0` +. "$Mydir/os.sh" +case "$Mydir" in +/*) ;; +*) Mydir=`cd "$Mydir" && 'pwd'`;; +esac + +Usage() { + [ "$1" ] && echo "ERROR: $@" >&2 + echo "Usage:" >&2 + echo "$0 [-- ...][][--install]" >&2 + exit 1 +} + +Error() { + echo "ERROR: $@" >&2 + exit 1 +} + +source_rc() { + rc="$1"; shift + for d in ${*:-""} + do + r="${d:+$d/}$rc" + [ -f "$r" -a -s "$r" ] || continue + echo "NOTE: reading $r" + . "$r" + break + done +} + +cmd_args="$@" + +# clear some things from the environment that we care about +unset MAKEOBJDIR MAKEOBJDIRPREFIX +# or that might be incompatible +unset MAKE MAKEFLAGS + +# --install[-host-target] will set this +INSTALL_PREFIX= +# other things we pass to install step +INSTALL_ARGS= +CONFIGURE_ARGS= +MAKESYSPATH= +# pick a useful default prefix (for me at least ;-) +for prefix in /opt/$HOST_TARGET "$HOME/$HOST_TARGET" /usr/pkg /usr/local "" +do + [ -d "${prefix:-.}" ] || continue + case "$prefix" in + */$HOST_TARGET) + p=`dirname $prefix` + if [ -d $p/share ]; then + INSTALL_BIN=$HOST_TARGET/bin + prefix=$p + fi + ;; + esac + echo "NOTE: default prefix=$prefix ${INSTALL_BIN:+INSTALL_BIN=$INSTALL_BIN}" + break +done +srcdir=$Mydir +mksrc=$Mydir/mk +objdir= +quiet=: + +${SKIP_RC:+:} source_rc .bmake-boot-strap.rc . "$Mydir/.." "$HOME" + +get_optarg() { + expr "x$1" : "x[^=]*=\\(.*\\)" +} + +here=`'pwd'` +if [ $here = $Mydir ]; then + # avoid pollution + OBJROOT=../ +fi + +op=all +BMAKE= + +while : +do + case "$1" in + --) shift; break;; + --help) sed -n -e "1d;/RCSid/,\$d" -e '/^#\.[a-z]/d' -e '/^#/s,^# *,,p' $0; exit 0;; + --prefix) prefix="$2"; shift;; + --prefix=*) prefix=`get_optarg "$1"`;; + --src=*) srcdir=`get_optarg "$1"`;; + --with-mksrc=*|--mksrc=*) mksrc=`get_optarg "$1"`;; + --share=*) share_dir=`get_optarg "$1"`;; + --share) share_dir="$2"; shift;; + --with-default-sys-path=*) + CONFIGURE_ARGS="$1";; + --with-default-sys-path) + CONFIGURE_ARGS="$1 $2";; + --install) INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix};; + --install-host-target) + INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix} + INSTALL_BIN=$HOST_TARGET/bin;; + --install-destdir=*) INSTALL_DESTDIR=`get_optarg "$1"`;; + --install-prefix=*) INSTALL_PREFIX=`get_optarg "$1"`;; + -DWITH*) INSTALL_ARGS="$INSTALL_ARGS $1";; + -s|--src) srcdir="$2"; shift;; + -m|--mksrc) mksrc="$2"; shift;; + -o|--objdir) objdir="$2"; shift;; + -q) quiet=;; + -c) source_rc "$2"; shift;; + --*) CONFIGURE_ARGS="$CONFIGURE_ARGS $1";; + *=*) eval "$1"; export `expr "x$1" : "x\\(.[^=]*\\)=.*"`;; + *) break;; + esac + shift +done + +AddConfigure() { + case " $CONFIGURE_ARGS " in + *" $1"*) ;; + *) CONFIGURE_ARGS="$CONFIGURE_ARGS $1$2";; + esac +} + +GetDir() { + match="$1" + shift + fmatch="$1" + shift + for dir in $* + do + [ -d "$dir" ] || continue + case "/$dir/" in + *$match*) ;; + *) continue;; + esac + case "$fmatch" in + .) ;; + *) [ -s $dir/$fmatch ] || continue;; + esac + case "$dir/" in + *./*) cd "$dir" && 'pwd';; + /*) echo $dir;; + *) cd "$dir" && 'pwd';; + esac + break + done +} + +FindHereOrAbove() { + ( + _t=-s + while : + do + case "$1" in + -C) cd "$2"; shift; shift;; + -?) _t=$1; shift;; + *) break;; + esac + done + case "$1" in + /*) # we shouldn't be here + [ $_t "$1" ] && echo "$1" + return + ;; + .../*) want=`echo "$1" | sed 's,^.../*,,'`;; + *) want="$1";; + esac + here=`'pwd'` + while : + do + if [ $_t "./$want" ]; then + echo "$here/$want" + return + fi + cd .. + here=`'pwd'` + case "$here" in + /) return;; + esac + done + ) +} + +# is $1 missing from $2 (or PATH) ? +no_path() { + eval "__p=\$${2:-PATH}" + case ":$__p:" in *:"$1":*) return 1;; *) return 0;; esac +} + +# if $1 exists and is not in path, append it +add_path () { + case "$1" in + -?) t=$1; shift;; + *) t=-d;; + esac + case "$2,$1" in + MAKESYSPATH,.../*) ;; + *) [ $t ${1:-.} ] || return;; + esac + no_path $* && eval ${2:-PATH}="$__p${__p:+:}$1" +} + + +srcdir=`GetDir /bmake make-bootstrap.sh.in "$srcdir" "$2" "$Mydir" ./bmake* "$Mydir"/../bmake*` +[ -d "${srcdir:-/dev/null}" ] || Usage +case "$mksrc" in +none|-) # we ignore this now + mksrc=$Mydir/mk + ;; +.../*) # find here or above + mksrc=`FindHereOrAbove -C "$Mydir" -s "$mksrc/sys.mk"` + # that found a file + mksrc=`dirname $mksrc` + ;; +*) # guess we want mksrc... + mksrc=`GetDir /mk sys.mk "$mksrc" "$3" ./mk* "$srcdir"/mk* "$srcdir"/../mk*` + [ -d "${mksrc:-/dev/null}" ] || Usage "Use '-m none' to build without mksrc" + ;; +esac + +# Ok, get to work... +objdir="${objdir:-$OBJROOT$HOST_TARGET}" +[ -d "$objdir" ] || mkdir -p "$objdir" +[ -d "$objdir" ] || mkdir "$objdir" +cd "$objdir" || exit 1 +# make it absolute +objdir=`'pwd'` + +ShareDir() { + case "/$1" in + /) [ -d /share ] || return;; + */$HOST_TARGET) + if [ -d "$1/../share" ]; then + echo `dirname "$1"`/share + return + fi + ;; + esac + echo $1/share +} + +# make it easy to force prefix to use $HOST_TARGET +: looking at "$prefix" +case "$prefix" in +*/host?target) prefix=`echo "$prefix" | sed "s,host.target,${HOST_TARGET},"`;; +esac + +share_dir="${share_dir:-`ShareDir $prefix`}" + +AddConfigure --prefix= "$prefix" +case "$CONFIGURE_ARGS" in +*--with-*-sys-path*) ;; # skip +*) [ "$share_dir" ] && AddConfigure --with-default-sys-path= "$share_dir/mk";; +esac +if [ "$mksrc" ]; then + AddConfigure --with-mksrc= "$mksrc" + # not all cc's support this + CFLAGS_MF= CFLAGS_MD= + export CFLAGS_MF CFLAGS_MD +fi + +# this makes it easy to run the bmake we just built +# the :tA dance is needed because 'pwd' and even /bin/pwd +# may not give the same result as realpath(). +Bmake() { + ( + cd $Mydir && + MAKESYSPATH=$mksrc SRCTOP=$Mydir OBJTOP=$objdir \ + MAKEOBJDIR='${.CURDIR:S,${SRCTOP:tA},${OBJTOP:tA},}' \ + ${BMAKE:-$objdir/bmake} -f $Mydir/Makefile "$@" + ) +} + +# there is actually a shell where type is not a builtin +# if type is missing, which(1) had better exists! +if (type cat) > /dev/null 2>&1; then +which() { + type "$@" | sed 's,[()],,g;s,^[^/][^/]*,,;q' +} +fi +# make sure test below uses the same diff that configure did +TOOL_DIFF=`which diff` +export TOOL_DIFF + +op_configure() { + $srcdir/configure $CONFIGURE_ARGS || exit 1 +} + +op_build() { + [ -s make-bootstrap.sh ] || op_configure + chmod 755 make-bootstrap.sh || exit 1 + ./make-bootstrap.sh || exit 1 + case "$op" in + build) op_test;; + esac +} + +op_test() { + [ -x bmake ] || op_build + Bmake test || exit 1 +} + +op_clean() { + if [ -x bmake ]; then + ln bmake bmake$$ + BMAKE=$objdir/bmake$$ Bmake clean + rm -f bmake$$ + elif [ $objdir != $srcdir ]; then + rm -rf * + fi +} + +op_install() { + op_test + case "$INSTALL_PREFIX,$INSTALL_BIN,$prefix" in + ,$HOST_TARGET/bin,*/$HOST_TARGET) + INSTALL_PREFIX=`dirname $prefix` + ;; + esac + INSTALL_PREFIX=${INSTALL_PREFIX:-$prefix} + Bmake install prefix=$INSTALL_PREFIX BINDIR=$INSTALL_PREFIX/${INSTALL_BIN:-bin} ${INSTALL_DESTDIR:+DESTDIR=$INSTALL_DESTDIR} $INSTALL_ARGS || exit 1 +} + +op_all() { + rm -f make-bootstrap.sh bmake *.o + if [ -n "$INSTALL_PREFIX" ]; then + op_install + else + op_test + MAKE_VERSION=`sed -n '/^_MAKE_VERSION/ { s,.*= *,,;p; }' $srcdir/Makefile` + cat << EOM +You can install by running: + +$0 $cmd_args op=install + +Use --install-prefix=/something to install somewhere other than $prefix +Use --install-destdir=/somewhere to set DESTDIR during install +Use --install-host-target to use INSTALL_BIN=$HOST_TARGET/bin +Use -DWITH_PROG_VERSION to install as bmake-$MAKE_VERSION +Use -DWITHOUT_PROG_LINK to suppress bmake -> bmake-$MAKE_VERSION symlink +Use -DWITHOUT_INSTALL_MK to skip installing files to $prefix/share/mk +EOM + fi + cat << EOM + +Note: bmake.cat1 contains ANSI escape sequences. +You may need the -r or -R option to more/less to view it correctly. + +EOM +} + +op_$op +exit 0 Property changes on: vendor/NetBSD/bmake/20201101/boot-strap ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/buf.c =================================================================== --- vendor/NetBSD/bmake/20201101/buf.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/buf.c (revision 367461) @@ -0,0 +1,211 @@ +/* $NetBSD: buf.c,v 1.42 2020/10/24 20:51:49 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* Automatically-expanding null-terminated buffers. */ + +#include +#include "make.h" + +/* "@(#)buf.c 8.1 (Berkeley) 6/6/93" */ +MAKE_RCSID("$NetBSD: buf.c,v 1.42 2020/10/24 20:51:49 rillig Exp $"); + +/* Make space in the buffer for adding a single byte. */ +void +Buf_Expand_1(Buffer *buf) +{ + buf->cap += buf->cap > 16 ? buf->cap : 16; + buf->data = bmake_realloc(buf->data, buf->cap); +} + +/* Add the bytes to the buffer. */ +void +Buf_AddBytes(Buffer *buf, const char *bytes, size_t bytes_len) +{ + size_t old_len = buf->len; + char *end; + + if (__predict_false(old_len + bytes_len >= buf->cap)) { + buf->cap += buf->cap > bytes_len + 16 ? buf->cap : bytes_len + 16; + buf->data = bmake_realloc(buf->data, buf->cap); + } + + end = buf->data + old_len; + buf->len = old_len + bytes_len; + memcpy(end, bytes, bytes_len); + end[bytes_len] = '\0'; +} + +/* Add the bytes between start and end to the buffer. */ +void +Buf_AddBytesBetween(Buffer *buf, const char *start, const char *end) +{ + Buf_AddBytes(buf, start, (size_t)(end - start)); +} + +/* Add the string to the buffer. */ +void +Buf_AddStr(Buffer *buf, const char *str) +{ + Buf_AddBytes(buf, str, strlen(str)); +} + +/* Add the number to the buffer. */ +void +Buf_AddInt(Buffer *buf, int n) +{ + enum { + bits = sizeof(int) * CHAR_BIT, + max_octal_digits = (bits + 2) / 3, + max_decimal_digits = /* at most */ max_octal_digits, + max_sign_chars = 1, + str_size = max_sign_chars + max_decimal_digits + 1 + }; + char str[str_size]; + + size_t len = (size_t)snprintf(str, sizeof str, "%d", n); + Buf_AddBytes(buf, str, len); +} + +/* Get the data (usually a string) from the buffer. + * The returned data is valid until the next modifying operation + * on the buffer. + * + * Returns the data and optionally the length of the data. */ +char * +Buf_GetAll(Buffer *buf, size_t *out_len) +{ + if (out_len != NULL) + *out_len = buf->len; + return buf->data; +} + +/* Mark the buffer as empty, so it can be filled with data again. */ +void +Buf_Empty(Buffer *buf) +{ + buf->len = 0; + buf->data[0] = '\0'; +} + +/* Initialize a buffer. + * If the given initial capacity is 0, a reasonable default is used. */ +void +Buf_Init(Buffer *buf, size_t cap) +{ + if (cap <= 0) + cap = 256; + buf->cap = cap; + buf->len = 0; + buf->data = bmake_malloc(cap); + buf->data[0] = '\0'; +} + +/* Reset the buffer. + * If freeData is TRUE, the data from the buffer is freed as well. + * Otherwise it is kept and returned. */ +char * +Buf_Destroy(Buffer *buf, Boolean freeData) +{ + char *data = buf->data; + if (freeData) { + free(data); + data = NULL; + } + + buf->cap = 0; + buf->len = 0; + buf->data = NULL; + + return data; +} + +#ifndef BUF_COMPACT_LIMIT +# define BUF_COMPACT_LIMIT 128 /* worthwhile saving */ +#endif + +/* Reset the buffer and return its data. + * + * If the buffer size is much greater than its content, + * a new buffer will be allocated and the old one freed. */ +char * +Buf_DestroyCompact(Buffer *buf) +{ +#if BUF_COMPACT_LIMIT > 0 + if (buf->cap - buf->len >= BUF_COMPACT_LIMIT) { + /* We trust realloc to be smart */ + char *data = bmake_realloc(buf->data, buf->len + 1); + data[buf->len] = '\0'; /* XXX: unnecessary */ + Buf_Destroy(buf, FALSE); + return data; + } +#endif + return Buf_Destroy(buf, FALSE); +} Property changes on: vendor/NetBSD/bmake/20201101/buf.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/buf.h =================================================================== --- vendor/NetBSD/bmake/20201101/buf.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/buf.h (revision 367461) @@ -0,0 +1,131 @@ +/* $NetBSD: buf.h,v 1.34 2020/09/27 16:59:02 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)buf.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)buf.h 8.1 (Berkeley) 6/6/93 + */ + +/* Automatically growing null-terminated buffers of characters. */ + +#ifndef MAKE_BUF_H +#define MAKE_BUF_H + +#include + +/* An automatically growing null-terminated buffer of characters. */ +typedef struct Buffer { + size_t cap; /* Allocated size of the buffer, including the null */ + size_t len; /* Number of bytes in buffer, excluding the null */ + char *data; /* The buffer itself (always null-terminated) */ +} Buffer; + +/* If we aren't on NetBSD, __predict_false() might not be defined. */ +#ifndef __predict_false +#define __predict_false(x) (x) +#endif + +void Buf_Expand_1(Buffer *); + +/* Buf_AddByte adds a single byte to a buffer. */ +static inline MAKE_ATTR_UNUSED void +Buf_AddByte(Buffer *buf, char byte) +{ + size_t old_len = buf->len++; + char *end; + if (__predict_false(old_len + 1 >= buf->cap)) + Buf_Expand_1(buf); + end = buf->data + old_len; + end[0] = byte; + end[1] = '\0'; +} + +static inline MAKE_ATTR_UNUSED size_t +Buf_Len(const Buffer *buf) +{ + return buf->len; +} + +static inline MAKE_ATTR_UNUSED Boolean +Buf_EndsWith(const Buffer *buf, char ch) +{ + return buf->len > 0 && buf->data[buf->len - 1] == ch; +} + +void Buf_AddBytes(Buffer *, const char *, size_t); +void Buf_AddBytesBetween(Buffer *, const char *, const char *); +void Buf_AddStr(Buffer *, const char *); +void Buf_AddInt(Buffer *, int); +char *Buf_GetAll(Buffer *, size_t *); +void Buf_Empty(Buffer *); +void Buf_Init(Buffer *, size_t); +char *Buf_Destroy(Buffer *, Boolean); +char *Buf_DestroyCompact(Buffer *); + +#endif /* MAKE_BUF_H */ Property changes on: vendor/NetBSD/bmake/20201101/buf.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/compat.c =================================================================== --- vendor/NetBSD/bmake/20201101/compat.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/compat.c (revision 367461) @@ -0,0 +1,709 @@ +/* $NetBSD: compat.c,v 1.173 2020/11/01 17:47:26 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * compat.c -- + * The routines in this file implement the full-compatibility + * mode of PMake. Most of the special functionality of PMake + * is available in this mode. Things not supported: + * - different shells. + * - friendly variable substitution. + * + * Interface: + * Compat_Run Initialize things for this module and recreate + * thems as need creatin' + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include "wait.h" + +#include +#include + +#include "make.h" +#include "dir.h" +#include "job.h" +#include "metachar.h" +#include "pathnames.h" + +/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: compat.c,v 1.173 2020/11/01 17:47:26 rillig Exp $"); + +static GNode *curTarg = NULL; +static pid_t compatChild; +static int compatSigno; + +/* + * CompatDeleteTarget -- delete a failed, interrupted, or otherwise + * duffed target if not inhibited by .PRECIOUS. + */ +static void +CompatDeleteTarget(GNode *gn) +{ + if (gn != NULL && !Targ_Precious(gn)) { + const char *file = GNode_VarTarget(gn); + + if (!opts.noExecute && eunlink(file) != -1) { + Error("*** %s removed", file); + } + } +} + +/* Interrupt the creation of the current target and remove it if it ain't + * precious. Then exit. + * + * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED. + * + * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've + * left the logic alone for now. - dholland 20160826 + */ +static void +CompatInterrupt(int signo) +{ + GNode *gn; + + CompatDeleteTarget(curTarg); + + if (curTarg != NULL && !Targ_Precious(curTarg)) { + /* + * Run .INTERRUPT only if hit with interrupt signal + */ + if (signo == SIGINT) { + gn = Targ_FindNode(".INTERRUPT"); + if (gn != NULL) { + Compat_Make(gn, gn); + } + } + } + + if (signo == SIGQUIT) + _exit(signo); + + /* + * If there is a child running, pass the signal on. + * We will exist after it has exited. + */ + compatSigno = signo; + if (compatChild > 0) { + KILLPG(compatChild, signo); + } else { + bmake_signal(signo, SIG_DFL); + kill(myPid, signo); + } +} + +/* Execute the next command for a target. If the command returns an error, + * the node's made field is set to ERROR and creation stops. + * + * Input: + * cmdp Command to execute + * gnp Node from which the command came + * + * Results: + * 0 if the command succeeded, 1 if an error occurred. + */ +int +Compat_RunCommand(const char *cmdp, GNode *gn) +{ + 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 */ + WAIT_T reason; /* Reason for child's death */ + int status; /* Description of child's death */ + pid_t cpid; /* Child actually found */ + pid_t retstat; /* Result of wait */ + StringListNode *cmdNode; /* Node where current command is located */ + 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 + * using a shell */ + const char *volatile cmd = cmdp; + + silent = (gn->type & OP_SILENT) != 0; + errCheck = !(gn->type & OP_IGNORE); + doIt = FALSE; + + /* Luckily the commands don't end up in a string pool, otherwise + * this comparison could match too early, in a dependency using "..." + * for delayed commands, run in parallel mode, using the same shell + * command line more than once; see JobPrintCommand. + * TODO: write a unit-test to protect against this potential bug. */ + cmdNode = Lst_FindDatum(gn->commands, cmd); + (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart); + /* TODO: handle errors */ + + if (*cmdStart == '\0') { + free(cmdStart); + return 0; + } + cmd = cmdStart; + LstNode_Set(cmdNode, cmdStart); + + if (gn->type & OP_SAVE_CMDS) { + GNode *endNode = Targ_GetEndNode(); + if (gn != endNode) { + Lst_Append(endNode->commands, cmdStart); + return 0; + } + } + if (strcmp(cmdStart, "...") == 0) { + gn->type |= OP_SAVE_CMDS; + return 0; + } + + while (*cmd == '@' || *cmd == '-' || *cmd == '+') { + switch (*cmd) { + case '@': + silent = !DEBUG(LOUD); + break; + case '-': + errCheck = FALSE; + break; + case '+': + doIt = TRUE; + if (!shellName) /* we came here from jobs */ + Shell_Init(); + break; + } + cmd++; + } + + while (ch_isspace(*cmd)) + cmd++; + + /* + * If we did not end up with a command, just skip it. + */ + if (!*cmd) + return 0; + +#if !defined(MAKE_NATIVE) + /* + * In a non-native build, the host environment might be weird enough + * that it's necessary to go through a shell to get the correct + * behaviour. Or perhaps the shell has been replaced with something + * that does extra logging, and that should not be bypassed. + */ + useShell = TRUE; +#else + /* + * Search for meta characters in the command. If there are no meta + * characters, there's no need to execute a shell to execute the + * command. + * + * Additionally variable assignments and empty commands + * go to the shell. Therefore treat '=' and ':' like shell + * meta characters as documented in make(1). + */ + + useShell = needshell(cmd); +#endif + + /* + * Print the command before echoing if we're not supposed to be quiet for + * this one. We also print the command if -n given. + */ + if (!silent || !GNode_ShouldExecute(gn)) { + printf("%s\n", cmd); + fflush(stdout); + } + + /* + * If we're not supposed to execute any commands, this is as far as + * we go... + */ + if (!doIt && !GNode_ShouldExecute(gn)) { + return 0; + } + DEBUG1(JOB, "Execute: '%s'\n", cmd); + + if (useShell) { + /* + * We need to pass the command off to the shell, typically + * because the command contains a "meta" character. + */ + static const char *shargv[5]; + int shargc; + + shargc = 0; + shargv[shargc++] = shellPath; + /* + * The following work for any of the builtin shell specs. + */ + if (errCheck && shellErrFlag) { + shargv[shargc++] = shellErrFlag; + } + if (DEBUG(SHELL)) + shargv[shargc++] = "-xc"; + else + shargv[shargc++] = "-c"; + shargv[shargc++] = cmd; + shargv[shargc] = NULL; + av = shargv; + bp = NULL; + mav = NULL; + } else { + /* + * No meta-characters, so no need to exec a shell. Break the command + * into words to form an argument vector we can execute. + */ + Words words = Str_Words(cmd, FALSE); + mav = words.words; + bp = words.freeIt; + av = (void *)mav; + } + +#ifdef USE_META + if (useMeta) { + meta_compat_start(); + } +#endif + + /* + * Fork and execute the single command. If the fork fails, we abort. + */ + compatChild = cpid = vFork(); + if (cpid < 0) { + Fatal("Could not fork"); + } + if (cpid == 0) { + Var_ExportVars(); +#ifdef USE_META + if (useMeta) { + meta_compat_child(); + } +#endif + (void)execvp(av[0], (char *const *)UNCONST(av)); + execDie("exec", av[0]); + } + + free(mav); + free(bp); + + /* XXX: Memory management looks suspicious here. */ + /* XXX: Setting a list item to NULL is unexpected. */ + LstNode_SetNull(cmdNode); + +#ifdef USE_META + if (useMeta) { + meta_compat_parent(cpid); + } +#endif + + /* + * The child is off and running. Now all we can do is wait... + */ + while ((retstat = wait(&reason)) != cpid) { + if (retstat > 0) + JobReapChild(retstat, reason, FALSE); /* not ours? */ + if (retstat == -1 && errno != EINTR) { + break; + } + } + + if (retstat < 0) + Fatal("error in wait: %d: %s", retstat, strerror(errno)); + + if (WIFSTOPPED(reason)) { + status = WSTOPSIG(reason); /* stopped */ + } else if (WIFEXITED(reason)) { + status = WEXITSTATUS(reason); /* exited */ +#if defined(USE_META) && defined(USE_FILEMON_ONCE) + if (useMeta) { + meta_cmd_finish(NULL); + } +#endif + if (status != 0) { + if (DEBUG(ERROR)) { + const char *cp; + debug_printf("\n*** Failed target: %s\n*** Failed command: ", + gn->name); + for (cp = cmd; *cp; ) { + if (ch_isspace(*cp)) { + debug_printf(" "); + while (ch_isspace(*cp)) + cp++; + } else { + debug_printf("%c", *cp); + cp++; + } + } + debug_printf("\n"); + } + printf("*** Error code %d", status); + } + } else { + status = WTERMSIG(reason); /* signaled */ + printf("*** Signal %d", status); + } + + + if (!WIFEXITED(reason) || status != 0) { + if (errCheck) { +#ifdef USE_META + if (useMeta) { + meta_job_error(NULL, gn, 0, status); + } +#endif + gn->made = ERROR; + if (opts.keepgoing) { + /* Abort the current target, but let others continue. */ + printf(" (continuing)\n"); + } else { + printf("\n"); + } + if (deleteOnError) + CompatDeleteTarget(gn); + } else { + /* + * Continue executing commands for this target. + * If we return 0, this will happen... + */ + printf(" (ignored)\n"); + status = 0; + } + } + + free(cmdStart); + compatChild = 0; + if (compatSigno) { + bmake_signal(compatSigno, SIG_DFL); + kill(myPid, compatSigno); + } + + return status; +} + +static void +RunCommands(GNode *gn) +{ + StringListNode *ln; + for (ln = gn->commands->first; ln != NULL; ln = ln->next) { + const char *cmd = ln->datum; + if (Compat_RunCommand(cmd, gn) != 0) + break; + } +} + +static void +MakeNodes(GNodeList *gnodes, GNode *pgn) +{ + GNodeListNode *ln; + for (ln = gnodes->first; ln != NULL; ln = ln->next) { + GNode *cohort = ln->datum; + Compat_Make(cohort, pgn); + } +} + +/* Make a target. + * + * If an error is detected and not being ignored, the process exits. + * + * Input: + * gn The node to make + * pgn Parent to abort if necessary + */ +void +Compat_Make(GNode *gn, GNode *pgn) +{ + if (!shellName) /* we came here from jobs */ + Shell_Init(); + if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) { + /* + * 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 FALSE again. + * This is our signal to not attempt to do anything but abort our + * parent as well. + */ + gn->flags |= REMAKE; + gn->made = BEINGMADE; + if (!(gn->type & OP_MADE)) + Suff_FindDeps(gn); + MakeNodes(gn->children, gn); + if (!(gn->flags & REMAKE)) { + gn->made = ABORTED; + pgn->flags &= ~(unsigned)REMAKE; + goto cohorts; + } + + if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) + Var_Set(IMPSRC, GNode_VarTarget(gn), pgn); + + /* + * All the children were made ok. Now youngestChild->mtime contains the + * modification time of the newest child, we need to find out if we + * exist and when we were modified last. The criteria for datedness + * are defined by the Make_OODate function. + */ + DEBUG1(MAKE, "Examining %s...", gn->name); + if (!Make_OODate(gn)) { + gn->made = UPTODATE; + DEBUG0(MAKE, "up-to-date.\n"); + goto cohorts; + } else + DEBUG0(MAKE, "out-of-date.\n"); + + /* + * If the user is just seeing if something is out-of-date, exit now + * to tell him/her "yes". + */ + if (opts.queryFlag) { + exit(1); + } + + /* + * We need to be re-made. We also have to make sure we've got a $? + * variable. To be nice, we also define the $> variable using + * Make_DoAllVar(). + */ + Make_DoAllVar(gn); + + /* + * Alter our type to tell if errors should be ignored or things + * should not be printed so CompatRunCommand knows what to do. + */ + if (Targ_Ignore(gn)) + gn->type |= OP_IGNORE; + if (Targ_Silent(gn)) + gn->type |= OP_SILENT; + + if (Job_CheckCommands(gn, Fatal)) { + /* + * Our commands are ok, but we still have to worry about the -t + * flag... + */ + if (!opts.touchFlag || (gn->type & OP_MAKE)) { + curTarg = gn; +#ifdef USE_META + if (useMeta && GNode_ShouldExecute(gn)) { + meta_job_start(NULL, gn); + } +#endif + RunCommands(gn); + curTarg = NULL; + } else { + Job_Touch(gn, (gn->type & OP_SILENT) != 0); + } + } else { + gn->made = ERROR; + } +#ifdef USE_META + if (useMeta && GNode_ShouldExecute(gn)) { + if (meta_job_finish(NULL) != 0) + gn->made = ERROR; + } +#endif + + if (gn->made != ERROR) { + /* + * If the node was made successfully, mark it so, update + * its modification time and timestamp all its parents. Note + * that for .ZEROTIME targets, the timestamping isn't done. + * This is to keep its state from affecting that of its parent. + */ + gn->made = MADE; + pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0; + if (!(gn->type & OP_EXEC)) { + pgn->flags |= CHILDMADE; + Make_TimeStamp(pgn, gn); + } + } else if (opts.keepgoing) { + pgn->flags &= ~(unsigned)REMAKE; + } else { + PrintOnError(gn, "\nStop."); + exit(1); + } + } else if (gn->made == ERROR) { + /* Already had an error when making this. Tell the parent to abort. */ + pgn->flags &= ~(unsigned)REMAKE; + } else { + if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) { + const char *target = GNode_VarTarget(gn); + Var_Set(IMPSRC, target != NULL ? target : "", pgn); + } + switch(gn->made) { + case BEINGMADE: + Error("Graph cycles through %s", gn->name); + gn->made = ERROR; + pgn->flags &= ~(unsigned)REMAKE; + break; + case MADE: + if ((gn->type & OP_EXEC) == 0) { + pgn->flags |= CHILDMADE; + Make_TimeStamp(pgn, gn); + } + break; + case UPTODATE: + if ((gn->type & OP_EXEC) == 0) { + Make_TimeStamp(pgn, gn); + } + break; + default: + break; + } + } + +cohorts: + MakeNodes(gn->cohorts, pgn); +} + +/* Initialize this module and start making. + * + * Input: + * targs The target nodes to re-create + */ +void +Compat_Run(GNodeList *targs) +{ + GNode *gn = NULL; /* Current root target */ + int errors; /* Number of targets not remade due to errors */ + + if (!shellName) + Shell_Init(); + + if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) + bmake_signal(SIGINT, CompatInterrupt); + if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) + bmake_signal(SIGTERM, CompatInterrupt); + if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) + bmake_signal(SIGHUP, CompatInterrupt); + if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) + bmake_signal(SIGQUIT, CompatInterrupt); + + /* Create the .END node now, to keep the (debug) output of the + * counter.mk test the same as before 2020-09-23. This implementation + * detail probably doesn't matter though. */ + (void)Targ_GetEndNode(); + /* + * If the user has defined a .BEGIN target, execute the commands attached + * to it. + */ + if (!opts.queryFlag) { + gn = Targ_FindNode(".BEGIN"); + if (gn != NULL) { + Compat_Make(gn, gn); + if (gn->made == ERROR) { + PrintOnError(gn, "\nStop."); + exit(1); + } + } + } + + /* + * Expand .USE nodes right now, because they can modify the structure + * of the tree. + */ + Make_ExpandUse(targs); + + /* + * For each entry in the list of targets to create, call Compat_Make on + * it to create the thing. Compat_Make will leave the 'made' field of gn + * in one of several states: + * UPTODATE gn was already up-to-date + * MADE gn was recreated successfully + * ERROR An error occurred while gn was being created + * ABORTED gn was not remade because one of its inferiors + * could not be made due to errors. + */ + errors = 0; + while (!Lst_IsEmpty(targs)) { + gn = Lst_Dequeue(targs); + Compat_Make(gn, gn); + + if (gn->made == UPTODATE) { + printf("`%s' is up to date.\n", gn->name); + } else if (gn->made == ABORTED) { + printf("`%s' not remade because of errors.\n", gn->name); + errors++; + } + } + + /* + * If the user has defined a .END target, run its commands. + */ + if (errors == 0) { + GNode *endNode = Targ_GetEndNode(); + Compat_Make(endNode, endNode); + /* XXX: Did you mean endNode->made instead of gn->made? */ + if (gn->made == ERROR) { + PrintOnError(gn, "\nStop."); + exit(1); + } + } +} Property changes on: vendor/NetBSD/bmake/20201101/compat.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/cond.c =================================================================== --- vendor/NetBSD/bmake/20201101/cond.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/cond.c (revision 367461) @@ -0,0 +1,1234 @@ +/* $NetBSD: cond.c,v 1.173 2020/10/30 20:30:44 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* Handling of conditionals in a makefile. + * + * Interface: + * Cond_EvalLine Evaluate the conditional. + * + * Cond_EvalCondition + * Evaluate the conditional, which is either the argument + * of one of the .if directives or the condition in a + * ':?then:else' variable modifier. + * + * Cond_save_depth + * Cond_restore_depth + * Save and restore the nesting of the conditions, at + * the start and end of including another makefile, to + * ensure that in each makefile the conditional + * directives are well-balanced. + */ + +#include + +#include "make.h" +#include "dir.h" + +/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ +MAKE_RCSID("$NetBSD: cond.c,v 1.173 2020/10/30 20:30:44 rillig Exp $"); + +/* + * The parsing of conditional expressions is based on this grammar: + * E -> F || E + * E -> F + * F -> T && F + * F -> T + * T -> defined(variable) + * T -> make(target) + * T -> exists(file) + * T -> empty(varspec) + * T -> target(name) + * T -> commands(name) + * T -> symbol + * T -> $(varspec) op value + * T -> $(varspec) == "string" + * T -> $(varspec) != "string" + * T -> "string" + * T -> ( E ) + * T -> ! T + * op -> == | != | > | < | >= | <= + * + * 'symbol' is some other symbol to which the default function is applied. + * + * The tokens are scanned by CondToken, which returns: + * TOK_AND for '&' or '&&' + * TOK_OR for '|' or '||' + * TOK_NOT for '!' + * TOK_LPAREN for '(' + * TOK_RPAREN for ')' + * Other terminal symbols are evaluated using either the default function or + * the function given in the terminal, they return either TOK_TRUE or + * TOK_FALSE. + * + * TOK_FALSE is 0 and TOK_TRUE 1 so we can directly assign C comparisons. + * + * All non-terminal functions (CondParser_Expr, CondParser_Factor and + * CondParser_Term) return either TOK_FALSE, TOK_TRUE, or TOK_ERROR on error. + */ +typedef enum Token { + TOK_FALSE = 0, TOK_TRUE = 1, TOK_AND, TOK_OR, TOK_NOT, + TOK_LPAREN, TOK_RPAREN, TOK_EOF, TOK_NONE, TOK_ERROR +} Token; + +typedef struct CondParser { + const struct If *if_info; /* Info for current statement */ + const char *p; /* The remaining condition to parse */ + Token curr; /* Single push-back token used in parsing */ + + /* Whether an error message has already been printed for this condition. + * The first available error message is usually the most specific one, + * therefore it makes sense to suppress the standard "Malformed + * conditional" message. */ + Boolean printedError; +} CondParser; + +static Token CondParser_Expr(CondParser *par, Boolean); + +static unsigned int cond_depth = 0; /* current .if nesting level */ +static unsigned int cond_min_depth = 0; /* depth at makefile open */ + +/* + * Indicate when we should be strict about lhs of comparisons. + * 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 + * since lhs is already expanded and we cannot tell if + * it was a variable reference or not. + */ +static Boolean lhsStrict; + +static int +is_token(const char *str, const char *tok, size_t len) +{ + return strncmp(str, tok, len) == 0 && !ch_isalpha(str[len]); +} + +/* Push back the most recent token read. We only need one level of this. */ +static void +CondParser_PushBack(CondParser *par, Token t) +{ + assert(par->curr == TOK_NONE); + assert(t != TOK_NONE); + + par->curr = t; +} + +static void +CondParser_SkipWhitespace(CondParser *par) +{ + cpp_skip_whitespace(&par->p); +} + +/* Parse the argument of a built-in function. + * + * Arguments: + * *pp initially points at the '(', + * upon successful return it points right after the ')'. + * + * *out_arg receives the argument as string. + * + * func says whether the argument belongs to an actual function, or + * whether the parsed argument is passed to the default function. + * + * Return the length of the argument. */ +static size_t +ParseFuncArg(const char **pp, Boolean doEval, const char *func, + char **out_arg) { + const char *p = *pp; + Buffer argBuf; + int paren_depth; + size_t argLen; + + if (func != NULL) + p++; /* Skip opening '(' - verified by caller */ + + if (*p == '\0') { + /* + * No arguments whatsoever. Because 'make' and 'defined' aren't really + * "reserved words", we don't print a message. I think this is better + * than hitting the user with a warning message every time s/he uses + * the word 'make' or 'defined' at the beginning of a symbol... + */ + *out_arg = NULL; + return 0; + } + + while (*p == ' ' || *p == '\t') { + p++; + } + + Buf_Init(&argBuf, 16); + + paren_depth = 0; + for (;;) { + char ch = *p; + if (ch == 0 || ch == ' ' || ch == '\t') + break; + if ((ch == '&' || ch == '|') && paren_depth == 0) + break; + if (*p == '$') { + /* + * Parse the variable spec and install it as part of the argument + * if it's valid. We tell Var_Parse to complain on an undefined + * variable, so we don't need to do it. Nor do we return an error, + * though perhaps we should... + */ + void *nestedVal_freeIt; + VarEvalFlags eflags = VARE_UNDEFERR | (doEval ? VARE_WANTRES : 0); + const char *nestedVal; + (void)Var_Parse(&p, VAR_CMDLINE, eflags, &nestedVal, + &nestedVal_freeIt); + /* TODO: handle errors */ + Buf_AddStr(&argBuf, nestedVal); + free(nestedVal_freeIt); + continue; + } + if (ch == '(') + paren_depth++; + else if (ch == ')' && --paren_depth < 0) + break; + Buf_AddByte(&argBuf, *p); + p++; + } + + *out_arg = Buf_GetAll(&argBuf, &argLen); + Buf_Destroy(&argBuf, FALSE); + + while (*p == ' ' || *p == '\t') { + p++; + } + + if (func != NULL && *p++ != ')') { + Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", + func); + /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */ + return 0; + } + + *pp = p; + return argLen; +} + +/* Test whether the given variable is defined. */ +static Boolean +FuncDefined(size_t argLen MAKE_ATTR_UNUSED, const char *arg) +{ + void *freeIt; + Boolean result = Var_Value(arg, VAR_CMDLINE, &freeIt) != NULL; + bmake_free(freeIt); + return result; +} + +/* See if the given target is being made. */ +static Boolean +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; +} + +/* See if the given file exists. */ +static Boolean +FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg) +{ + Boolean result; + char *path; + + path = Dir_FindFile(arg, dirSearchPath); + DEBUG2(COND, "exists(%s) result is \"%s\"\n", arg, path ? path : ""); + if (path != NULL) { + result = TRUE; + free(path); + } else { + result = FALSE; + } + return result; +} + +/* See if the given node exists and is an actual target. */ +static Boolean +FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg) +{ + GNode *gn = Targ_FindNode(arg); + return gn != NULL && GNode_IsTarget(gn); +} + +/* See if the given node exists and is an actual target with commands + * associated with it. */ +static Boolean +FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg) +{ + GNode *gn = Targ_FindNode(arg); + return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(gn->commands); +} + +/*- + * Convert the given number into a double. + * We try a base 10 or 16 integer conversion first, if that fails + * then we try a floating point conversion instead. + * + * Results: + * Sets 'value' to double value of string. + * Returns TRUE if the conversion succeeded. + */ +static Boolean +TryParseNumber(const char *str, double *value) +{ + char *eptr, ech; + unsigned long l_val; + double d_val; + + errno = 0; + if (!*str) { + *value = 0.0; + return TRUE; + } + l_val = strtoul(str, &eptr, str[1] == 'x' ? 16 : 10); + ech = *eptr; + if (ech == '\0' && errno != ERANGE) { + d_val = str[0] == '-' ? -(double)-l_val : (double)l_val; + } else { + if (ech != '\0' && ech != '.' && ech != 'e' && ech != 'E') + return FALSE; + d_val = strtod(str, &eptr); + if (*eptr) + return FALSE; + } + + *value = d_val; + return TRUE; +} + +static Boolean +is_separator(char ch) +{ + return ch == '\0' || ch_isspace(ch) || strchr("!=><)", ch) != NULL; +} + +/*- + * Parse a string from a variable reference or an optionally quoted + * string. This is called for the lhs and rhs of string comparisons. + * + * Results: + * Returns the string, absent any quotes, or NULL on error. + * Sets quoted if the string was quoted. + * Sets freeIt if needed. + */ +/* coverity:[+alloc : arg-*4] */ +static const char * +CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS, + Boolean *quoted, void **freeIt) +{ + Buffer buf; + const char *str; + Boolean atStart; + const char *nested_p; + Boolean qt; + const char *start; + VarEvalFlags eflags; + VarParseResult parseResult; + + Buf_Init(&buf, 0); + str = NULL; + *freeIt = NULL; + *quoted = qt = par->p[0] == '"' ? 1 : 0; + start = par->p; + if (qt) + par->p++; + while (par->p[0] && str == NULL) { + switch (par->p[0]) { + case '\\': + par->p++; + if (par->p[0] != '\0') { + Buf_AddByte(&buf, par->p[0]); + par->p++; + } + continue; + case '"': + if (qt) { + par->p++; /* we don't want the quotes */ + goto got_str; + } + Buf_AddByte(&buf, par->p[0]); /* likely? */ + par->p++; + continue; + case ')': + case '!': + case '=': + case '>': + case '<': + case ' ': + case '\t': + if (!qt) + goto got_str; + Buf_AddByte(&buf, par->p[0]); + par->p++; + continue; + case '$': + /* if we are in quotes, an undefined variable is ok */ + eflags = ((!qt && doEval) ? VARE_UNDEFERR : 0) | + (doEval ? VARE_WANTRES : 0); + nested_p = par->p; + atStart = nested_p == start; + parseResult = Var_Parse(&nested_p, VAR_CMDLINE, eflags, &str, + freeIt); + /* TODO: handle errors */ + if (str == var_Error) { + if (parseResult & VPR_ANY_MSG) + par->printedError = TRUE; + if (*freeIt) { + free(*freeIt); + *freeIt = NULL; + } + /* + * Even if !doEval, we still report syntax errors, which + * is what getting var_Error back with !doEval means. + */ + str = NULL; + goto cleanup; + } + par->p = nested_p; + + /* + * If the '$' started the string literal (which means no quotes), + * and the variable expression is followed by a space, looks like + * a comparison operator or is the end of the expression, we are + * done. + */ + if (atStart && is_separator(par->p[0])) + goto cleanup; + + Buf_AddStr(&buf, str); + if (*freeIt) { + free(*freeIt); + *freeIt = NULL; + } + str = NULL; /* not finished yet */ + continue; + default: + if (strictLHS && !qt && *start != '$' && !ch_isdigit(*start)) { + /* lhs must be quoted, a variable reference or number */ + if (*freeIt) { + free(*freeIt); + *freeIt = NULL; + } + str = NULL; + goto cleanup; + } + Buf_AddByte(&buf, par->p[0]); + par->p++; + continue; + } + } +got_str: + *freeIt = Buf_GetAll(&buf, NULL); + str = *freeIt; +cleanup: + Buf_Destroy(&buf, FALSE); + return str; +} + +/* The different forms of .if directives. */ +static const struct If { + const char *form; /* Form of if */ + size_t formlen; /* Length of form */ + Boolean doNot; /* TRUE if default function should be negated */ + Boolean (*defProc)(size_t, const char *); /* Default function to apply */ +} ifs[] = { + { "def", 3, FALSE, FuncDefined }, + { "ndef", 4, TRUE, FuncDefined }, + { "make", 4, FALSE, FuncMake }, + { "nmake", 5, TRUE, FuncMake }, + { "", 0, FALSE, FuncDefined }, + { NULL, 0, FALSE, NULL } +}; + +/* Evaluate a "comparison without operator", such as in ".if ${VAR}" or + * ".if 0". */ +static Token +EvalNotEmpty(CondParser *par, const char *lhs, Boolean lhsQuoted) +{ + double left; + + /* For .ifxxx "..." check for non-empty string. */ + if (lhsQuoted) + return lhs[0] != '\0'; + + /* For .ifxxx compare against zero */ + if (TryParseNumber(lhs, &left)) + return left != 0.0; + + /* For .if ${...} check for non-empty string (defProc is ifdef). */ + if (par->if_info->form[0] == '\0') + return lhs[0] != 0; + + /* Otherwise action default test ... */ + return par->if_info->defProc(strlen(lhs), lhs) == !par->if_info->doNot; +} + +/* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */ +static Token +EvalCompareNum(double lhs, const char *op, double rhs) +{ + DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, op); + + switch (op[0]) { + case '!': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, "Unknown operator"); + /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */ + return TOK_ERROR; + } + return lhs != rhs; + case '=': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, "Unknown operator"); + /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */ + return TOK_ERROR; + } + return lhs == rhs; + case '<': + return op[1] == '=' ? lhs <= rhs : lhs < rhs; + case '>': + return op[1] == '=' ? lhs >= rhs : lhs > rhs; + } + return TOK_ERROR; +} + +static Token +EvalCompareStr(const char *lhs, const char *op, const char *rhs) +{ + if (!((op[0] == '!' || op[0] == '=') && op[1] == '=')) { + Parse_Error(PARSE_WARNING, + "String comparison operator must be either == or !="); + /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */ + return TOK_ERROR; + } + + DEBUG3(COND, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", lhs, rhs, op); + return (*op == '=') == (strcmp(lhs, rhs) == 0); +} + +/* Evaluate a comparison, such as "${VAR} == 12345". */ +static Token +EvalCompare(const char *lhs, Boolean lhsQuoted, const char *op, + const char *rhs, Boolean rhsQuoted) +{ + double left, right; + + if (!rhsQuoted && !lhsQuoted) + if (TryParseNumber(lhs, &left) && TryParseNumber(rhs, &right)) + return EvalCompareNum(left, op, right); + + return EvalCompareStr(lhs, op, rhs); +} + +/* Parse a comparison condition such as: + * + * 0 + * ${VAR:Mpattern} + * ${VAR} == value + * ${VAR:U0} < 12345 + */ +static Token +CondParser_Comparison(CondParser *par, Boolean doEval) +{ + Token t = TOK_ERROR; + const char *lhs, *op, *rhs; + void *lhsFree, *rhsFree; + Boolean lhsQuoted, rhsQuoted; + + rhs = NULL; + lhsFree = rhsFree = NULL; + lhsQuoted = rhsQuoted = FALSE; + + /* + * Parse the variable spec and skip over it, saving its + * value in lhs. + */ + lhs = CondParser_String(par, doEval, lhsStrict, &lhsQuoted, &lhsFree); + if (!lhs) + goto done; + + CondParser_SkipWhitespace(par); + + /* + * Make sure the operator is a valid one. If it isn't a + * known relational operator, pretend we got a + * != 0 comparison. + */ + op = par->p; + switch (par->p[0]) { + case '!': + case '=': + case '<': + case '>': + if (par->p[1] == '=') { + par->p += 2; + } else { + par->p++; + } + break; + default: + t = doEval ? EvalNotEmpty(par, lhs, lhsQuoted) : TOK_FALSE; + goto done; + } + + CondParser_SkipWhitespace(par); + + if (par->p[0] == '\0') { + Parse_Error(PARSE_WARNING, "Missing right-hand-side of operator"); + /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */ + goto done; + } + + rhs = CondParser_String(par, doEval, FALSE, &rhsQuoted, &rhsFree); + if (rhs == NULL) + goto done; + + if (!doEval) { + t = TOK_FALSE; + goto done; + } + + t = EvalCompare(lhs, lhsQuoted, op, rhs, rhsQuoted); + +done: + free(lhsFree); + free(rhsFree); + return t; +} + +static size_t +ParseEmptyArg(const char **linePtr, Boolean doEval, + const char *func MAKE_ATTR_UNUSED, char **argPtr) +{ + void *val_freeIt; + const char *val; + size_t magic_res; + + /* We do all the work here and return the result as the length */ + *argPtr = NULL; + + (*linePtr)--; /* Make (*linePtr)[1] point to the '('. */ + (void)Var_Parse(linePtr, VAR_CMDLINE, doEval ? VARE_WANTRES : 0, + &val, &val_freeIt); + /* TODO: handle errors */ + /* If successful, *linePtr points beyond the closing ')' now. */ + + if (val == var_Error) { + free(val_freeIt); + return (size_t)-1; + } + + /* A variable is empty when it just contains spaces... 4/15/92, christos */ + cpp_skip_whitespace(&val); + + /* + * For consistency with the other functions we can't generate the + * true/false here. + */ + magic_res = *val != '\0' ? 2 : 1; + free(val_freeIt); + return magic_res; +} + +static Boolean +FuncEmpty(size_t arglen, const char *arg MAKE_ATTR_UNUSED) +{ + /* Magic values ahead, see ParseEmptyArg. */ + return arglen == 1; +} + +static Token +CondParser_Func(CondParser *par, Boolean doEval) +{ + static const struct fn_def { + const char *fn_name; + size_t fn_name_len; + size_t (*fn_parse)(const char **, Boolean, const char *, char **); + Boolean (*fn_eval)(size_t, const char *); + } fn_defs[] = { + { "defined", 7, ParseFuncArg, FuncDefined }, + { "make", 4, ParseFuncArg, FuncMake }, + { "exists", 6, ParseFuncArg, FuncExists }, + { "empty", 5, ParseEmptyArg, FuncEmpty }, + { "target", 6, ParseFuncArg, FuncTarget }, + { "commands", 8, ParseFuncArg, FuncCommands }, + { NULL, 0, NULL, NULL }, + }; + const struct fn_def *fn_def; + Token t; + char *arg = NULL; + size_t arglen; + const char *cp = par->p; + const char *cp1; + + for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) { + if (!is_token(cp, fn_def->fn_name, fn_def->fn_name_len)) + continue; + cp += fn_def->fn_name_len; + /* There can only be whitespace before the '(' */ + cpp_skip_whitespace(&cp); + if (*cp != '(') + break; + + arglen = fn_def->fn_parse(&cp, doEval, fn_def->fn_name, &arg); + if (arglen == 0 || arglen == (size_t)-1) { + par->p = cp; + return arglen == 0 ? TOK_FALSE : TOK_ERROR; + } + /* Evaluate the argument using the required function. */ + t = !doEval || fn_def->fn_eval(arglen, arg); + free(arg); + par->p = cp; + return t; + } + + /* Push anything numeric through the compare expression */ + cp = par->p; + if (ch_isdigit(cp[0]) || strchr("+-", cp[0])) + return CondParser_Comparison(par, doEval); + + /* + * Most likely we have a naked token to apply the default function to. + * However ".if a == b" gets here when the "a" is unquoted and doesn't + * start with a '$'. This surprises people. + * If what follows the function argument is a '=' or '!' then the syntax + * would be invalid if we did "defined(a)" - so instead treat as an + * expression. + */ + arglen = ParseFuncArg(&cp, doEval, NULL, &arg); + cp1 = cp; + cpp_skip_whitespace(&cp1); + if (*cp1 == '=' || *cp1 == '!') + return CondParser_Comparison(par, doEval); + par->p = cp; + + /* + * Evaluate the argument using the default function. + * This path always treats .if as .ifdef. To get here, the character + * after .if must have been taken literally, so the argument cannot + * be empty - even if it contained a variable expansion. + */ + t = !doEval || par->if_info->defProc(arglen, arg) == !par->if_info->doNot; + free(arg); + return t; +} + +/* Return the next token or comparison result from the parser. */ +static Token +CondParser_Token(CondParser *par, Boolean doEval) +{ + Token t; + + t = par->curr; + if (t != TOK_NONE) { + par->curr = TOK_NONE; + return t; + } + + while (par->p[0] == ' ' || par->p[0] == '\t') { + par->p++; + } + + switch (par->p[0]) { + + case '(': + par->p++; + return TOK_LPAREN; + + case ')': + par->p++; + return TOK_RPAREN; + + case '|': + par->p++; + if (par->p[0] == '|') { + par->p++; + } + return TOK_OR; + + case '&': + par->p++; + if (par->p[0] == '&') { + par->p++; + } + return TOK_AND; + + case '!': + par->p++; + return TOK_NOT; + + case '#': + case '\n': + case '\0': + return TOK_EOF; + + case '"': + case '$': + return CondParser_Comparison(par, doEval); + + default: + return CondParser_Func(par, doEval); + } +} + +/* Parse a single term in the expression. This consists of a terminal symbol + * or TOK_NOT and a term (not including the binary operators): + * + * T -> defined(variable) | make(target) | exists(file) | symbol + * T -> ! T | ( E ) + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR. + */ +static Token +CondParser_Term(CondParser *par, Boolean doEval) +{ + Token t; + + t = CondParser_Token(par, doEval); + + if (t == TOK_EOF) { + /* + * If we reached the end of the expression, the expression + * is malformed... + */ + t = TOK_ERROR; + } else if (t == TOK_LPAREN) { + /* + * T -> ( E ) + */ + t = CondParser_Expr(par, doEval); + if (t != TOK_ERROR) { + if (CondParser_Token(par, doEval) != TOK_RPAREN) { + t = TOK_ERROR; + } + } + } else if (t == TOK_NOT) { + t = CondParser_Term(par, doEval); + if (t == TOK_TRUE) { + t = TOK_FALSE; + } else if (t == TOK_FALSE) { + t = TOK_TRUE; + } + } + return t; +} + +/* Parse a conjunctive factor (nice name, wot?) + * + * F -> T && F | T + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR + */ +static Token +CondParser_Factor(CondParser *par, Boolean doEval) +{ + Token l, o; + + l = CondParser_Term(par, doEval); + if (l != TOK_ERROR) { + o = CondParser_Token(par, doEval); + + if (o == TOK_AND) { + /* + * F -> T && F + * + * If T is TOK_FALSE, the whole thing will be TOK_FALSE, but we + * have to parse the r.h.s. anyway (to throw it away). + * If T is TOK_TRUE, the result is the r.h.s., be it a TOK_ERROR + * or not. + */ + if (l == TOK_TRUE) { + l = CondParser_Factor(par, doEval); + } else { + (void)CondParser_Factor(par, FALSE); + } + } else { + /* + * F -> T + */ + CondParser_PushBack(par, o); + } + } + return l; +} + +/* Main expression production. + * + * E -> F || E | F + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR. + */ +static Token +CondParser_Expr(CondParser *par, Boolean doEval) +{ + Token l, o; + + l = CondParser_Factor(par, doEval); + if (l != TOK_ERROR) { + o = CondParser_Token(par, doEval); + + if (o == TOK_OR) { + /* + * E -> F || E + * + * A similar thing occurs for ||, except that here we make sure + * the l.h.s. is TOK_FALSE before we bother to evaluate the r.h.s. + * Once again, if l is TOK_FALSE, the result is the r.h.s. and once + * again if l is TOK_TRUE, we parse the r.h.s. to throw it away. + */ + if (l == TOK_FALSE) { + l = CondParser_Expr(par, doEval); + } else { + (void)CondParser_Expr(par, FALSE); + } + } else { + /* + * E -> F + */ + CondParser_PushBack(par, o); + } + } + return l; +} + +static CondEvalResult +CondParser_Eval(CondParser *par, Boolean *value) +{ + Token res; + + DEBUG1(COND, "CondParser_Eval: %s\n", par->p); + + res = CondParser_Expr(par, TRUE); + if (res != TOK_FALSE && res != TOK_TRUE) + return COND_INVALID; + + if (CondParser_Token(par, TRUE /* XXX: Why TRUE? */) != TOK_EOF) + return COND_INVALID; + + *value = res == TOK_TRUE; + return COND_PARSE; +} + +/* Evaluate the condition, including any side effects from the variable + * expressions in the condition. The condition consists of &&, ||, !, + * function(arg), comparisons and parenthetical groupings thereof. + * + * Results: + * COND_PARSE if the condition was valid grammatically + * COND_INVALID if not a valid conditional. + * + * (*value) is set to the boolean value of the condition + */ +static CondEvalResult +CondEvalExpression(const struct If *info, const char *cond, Boolean *value, + Boolean eprint, Boolean strictLHS) +{ + static const struct If *dflt_info; + CondParser par; + int rval; + + lhsStrict = strictLHS; + + while (*cond == ' ' || *cond == '\t') + cond++; + + if (info == NULL && (info = dflt_info) == NULL) { + /* Scan for the entry for .if - it can't be first */ + for (info = ifs;; info++) + if (info->form[0] == 0) + break; + dflt_info = info; + } + assert(info != NULL); + + par.if_info = info; + par.p = cond; + par.curr = TOK_NONE; + par.printedError = FALSE; + + rval = CondParser_Eval(&par, value); + + if (rval == COND_INVALID && eprint && !par.printedError) + Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond); + + return rval; +} + +CondEvalResult +Cond_EvalCondition(const char *cond, Boolean *out_value) +{ + return CondEvalExpression(NULL, cond, out_value, FALSE, FALSE); +} + +/* Evaluate the conditional in the passed line. The line looks like this: + * . + * In this line, is any of if, ifmake, ifnmake, ifdef, ifndef, + * elif, elifmake, elifnmake, elifdef, elifndef. + * In this line, consists of &&, ||, !, function(arg), comparisons + * and parenthetical groupings thereof. + * + * Note that the states IF_ACTIVE and ELSE_ACTIVE are only different in order + * to detect spurious .else lines (as are SKIP_TO_ELSE and SKIP_TO_ENDIF), + * otherwise .else could be treated as '.elif 1'. + * + * Results: + * COND_PARSE to continue parsing the lines after the conditional + * (when .if or .else returns TRUE) + * COND_SKIP to skip the lines after the conditional + * (when .if or .elif returns 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 + * or because the condition could not be evaluated + */ +CondEvalResult +Cond_EvalLine(const char *line) +{ + enum { MAXIF = 128 }; /* maximum depth of .if'ing */ + enum { MAXIF_BUMP = 32 }; /* how much to grow by */ + enum if_states { + IF_ACTIVE, /* .if or .elif part active */ + ELSE_ACTIVE, /* .else part active */ + SEARCH_FOR_ELIF, /* searching for .elif/else to execute */ + SKIP_TO_ELSE, /* has been true, but not seen '.else' */ + SKIP_TO_ENDIF /* nothing else to execute */ + }; + static enum if_states *cond_state = NULL; + static unsigned int max_if_depth = MAXIF; + + const struct If *ifp; + Boolean isElif; + Boolean value; + enum if_states state; + + if (!cond_state) { + cond_state = bmake_malloc(max_if_depth * sizeof(*cond_state)); + cond_state[0] = IF_ACTIVE; + } + /* skip leading character (the '.') and any whitespace */ + for (line++; *line == ' ' || *line == '\t'; line++) + continue; + + /* Find what type of if we're dealing with. */ + if (line[0] == 'e') { + if (line[1] != 'l') { + if (!is_token(line + 1, "ndif", 4)) + return COND_INVALID; + /* End of conditional section */ + if (cond_depth == cond_min_depth) { + Parse_Error(PARSE_FATAL, "if-less endif"); + return COND_PARSE; + } + /* Return state for previous conditional */ + cond_depth--; + return cond_state[cond_depth] <= ELSE_ACTIVE + ? COND_PARSE : COND_SKIP; + } + + /* Quite likely this is 'else' or 'elif' */ + line += 2; + if (is_token(line, "se", 2)) { + /* It is else... */ + if (cond_depth == cond_min_depth) { + Parse_Error(PARSE_FATAL, "if-less else"); + return COND_PARSE; + } + + state = cond_state[cond_depth]; + switch (state) { + case SEARCH_FOR_ELIF: + state = ELSE_ACTIVE; + break; + case ELSE_ACTIVE: + case SKIP_TO_ENDIF: + Parse_Error(PARSE_WARNING, "extra else"); + /* FALLTHROUGH */ + default: + case IF_ACTIVE: + case SKIP_TO_ELSE: + state = SKIP_TO_ENDIF; + break; + } + cond_state[cond_depth] = state; + return state <= ELSE_ACTIVE ? COND_PARSE : COND_SKIP; + } + /* Assume for now it is an elif */ + isElif = TRUE; + } else + isElif = FALSE; + + if (line[0] != 'i' || line[1] != 'f') + /* Not an ifxxx or elifxxx line */ + return COND_INVALID; + + /* + * Figure out what sort of conditional it is -- what its default + * function is, etc. -- by looking in the table of valid "ifs" + */ + line += 2; + for (ifp = ifs;; ifp++) { + if (ifp->form == NULL) + return COND_INVALID; + if (is_token(ifp->form, line, ifp->formlen)) { + line += ifp->formlen; + break; + } + } + + /* Now we know what sort of 'if' it is... */ + + if (isElif) { + if (cond_depth == cond_min_depth) { + Parse_Error(PARSE_FATAL, "if-less elif"); + return COND_PARSE; + } + state = cond_state[cond_depth]; + if (state == SKIP_TO_ENDIF || state == ELSE_ACTIVE) { + Parse_Error(PARSE_WARNING, "extra elif"); + cond_state[cond_depth] = SKIP_TO_ENDIF; + return COND_SKIP; + } + if (state != SEARCH_FOR_ELIF) { + /* Either just finished the 'true' block, or already SKIP_TO_ELSE */ + cond_state[cond_depth] = SKIP_TO_ELSE; + return COND_SKIP; + } + } else { + /* Normal .if */ + if (cond_depth + 1 >= max_if_depth) { + /* + * This is rare, but not impossible. + * In meta mode, dirdeps.mk (only runs at level 0) + * can need more than the default. + */ + max_if_depth += MAXIF_BUMP; + cond_state = bmake_realloc(cond_state, + max_if_depth * sizeof(*cond_state)); + } + state = cond_state[cond_depth]; + cond_depth++; + if (state > ELSE_ACTIVE) { + /* If we aren't parsing the data, treat as always false */ + cond_state[cond_depth] = SKIP_TO_ELSE; + return COND_SKIP; + } + } + + /* And evaluate the conditional expression */ + if (CondEvalExpression(ifp, line, &value, TRUE, TRUE) == COND_INVALID) { + /* Syntax error in conditional, error message already output. */ + /* Skip everything to matching .endif */ + cond_state[cond_depth] = SKIP_TO_ELSE; + return COND_SKIP; + } + + if (!value) { + cond_state[cond_depth] = SEARCH_FOR_ELIF; + return COND_SKIP; + } + cond_state[cond_depth] = IF_ACTIVE; + return COND_PARSE; +} + +void +Cond_restore_depth(unsigned int saved_depth) +{ + unsigned int open_conds = cond_depth - cond_min_depth; + + if (open_conds != 0 || saved_depth > cond_depth) { + Parse_Error(PARSE_FATAL, "%u open conditional%s", open_conds, + open_conds == 1 ? "" : "s"); + cond_depth = cond_min_depth; + } + + cond_min_depth = saved_depth; +} + +unsigned int +Cond_save_depth(void) +{ + unsigned int depth = cond_min_depth; + + cond_min_depth = cond_depth; + return depth; +} Property changes on: vendor/NetBSD/bmake/20201101/cond.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/configure =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-shellscript Property changes on: vendor/NetBSD/bmake/20201101/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/x-shellscript \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/configure.in =================================================================== --- vendor/NetBSD/bmake/20201101/configure.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/configure.in (revision 367461) @@ -0,0 +1,432 @@ +dnl +dnl RCSid: +dnl $Id: configure.in,v 1.67 2020/10/19 19:47:50 sjg Exp $ +dnl +dnl Process this file with autoconf to produce a configure script +dnl +AC_PREREQ(2.50) +AC_INIT([bmake], [20201018], [sjg@NetBSD.org]) +AC_CONFIG_HEADERS(config.h) + +dnl make srcdir absolute +case "$srcdir" in +/*) ;; +*) srcdir=`cd $srcdir && pwd`;; +esac + +dnl get _MAKE_VERSION +. $srcdir/VERSION +OS=`uname -s` + +dnl +AC_ARG_WITH(defshell, +[ --with-defshell=SHELL use SHELL by default - must be sh compatible, use sh or ksh to pick the internal definitions], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for bmake DEFSHELL) ;; +no) ;; +*) case "$with_defshell" in + sh) DEFSHELL_INDEX=DEFSHELL_INDEX_SH;; # it's the default anyway + ksh) DEFSHELL_INDEX=DEFSHELL_INDEX_KSH;; + csh) DEFSHELL_INDEX=DEFSHELL_INDEX_CSH;; # kidding right? + *) defshell_path=$with_defshell;; # better be sh compatible! + esac + ;; + esac]) +dnl +case "$OS" in +CYGWIN*|MINGW*) use_makefile=no;; +*) use_makefile=yes;; +esac +AC_ARG_WITH(makefile, +[ --without-makefile disable use of generated makefile], +[case "${withval}" in +yes|no) use_makefile=${withval};; +*) AC_MSG_ERROR(bad value ${withval} given for makefile) ;; +esac]) +dnl +use_meta=yes +AC_ARG_WITH(meta, +[ --without-meta disable use of meta-mode], +[case "${withval}" in +yes|no) use_meta=${withval};; +*) AC_MSG_ERROR(bad value ${withval} given for meta) ;; +esac]) +dnl +AC_ARG_WITH(filemon, +[ --with-filemon={no,dev,ktrace,path/filemon.h} indicate filemon method for meta-mode. Path to filemon.h implies dev], +[ case "/${withval}" in +/no) use_filemon=no;; +/*trace) filemon_h=no use_filemon="${withval}";; +*/filemon.h) filemon_h="${withval}";; +*/filemon*) filemon_h="${withval}/filemon.h";; +*) AC_MSG_ERROR(bad value ${withval} given for filemon) ;; +esac +case "$use_filemon,$filemon_h" in +,*.h) use_filemon=dev;; +esac +], +[ +case "$OS" in +NetBSD) filemon_h=no use_filemon=ktrace;; +*) + for d in "/usr/include/dev/filemon" "$prefix/include/dev/filemon" "$srcdir/../../sys/dev/filemon" + do + for x in "/$OS" "" + do + filemon_h="$d$x/filemon.h" + test -s "$filemon_h" && break + done + test -s "$filemon_h" && { use_filemon=dev; break; } + done + ;; +esac +use_filemon=${use_filemon:-no} +case "$use_filemon" in +dev) ;; +*) filemon_h=no;; +esac +]) +dnl echo "Note: use_meta=$use_meta use_filemon=$use_filemon filemon_h=$filemon_h" >&6 +case "$use_meta" in +yes) + case "$use_filemon" in + no) ;; + *) echo "Using: filemon_${use_filemon}.c" >&6;; + esac + ;; +esac +dnl +dnl Check for OS problems +dnl Solaris's signal.h only privides sigset_t etc if one of +dnl _EXTENSIONS_ _POSIX_C_SOURCE or _XOPEN_SOURCE are defined. +dnl The later two seem to cause more problems than they solve so if we +dnl see _EXTENSIONS_ we use it. +AC_USE_SYSTEM_EXTENSIONS +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CC_C99 +dnl AC_PROG_GCC_TRADITIONAL +AC_PROG_INSTALL +dnl Executable suffix - normally empty; .exe on os2. +AC_SUBST(ac_exe_suffix)dnl +dnl +dnl Hurd refuses to define PATH_MAX or MAXPATHLEN +if test -x /usr/bin/getconf; then + bmake_path_max=`getconf PATH_MAX / 2> /dev/null` + # only a numeric response is useful + test ${bmake_path_max:-0} -gt 0 2> /dev/null || bmake_path_max= +fi +bmake_path_max=${bmake_path_max:-1024} +if test $bmake_path_max -gt 1024; then + # this is all we expect + bmake_path_max=1024 +fi +echo "Using: BMAKE_PATH_MAX=$bmake_path_max" >&6 +AC_SUBST(bmake_path_max)dnl +dnl +dnl AC_C_CROSS +dnl + +dnl Checks for header files. +AC_HEADER_SYS_WAIT +AC_HEADER_DIRENT +dnl Keep this list sorted +AC_CHECK_HEADERS(sys/param.h) +dnl On BSDi at least we really need sys/param.h for sys/sysctl.h +AC_CHECK_HEADERS([sys/sysctl.h], [], [], +[#ifdef HAVE_SYS_PARAM_H +# include +# endif +]) + +AC_CHECK_HEADERS( \ + ar.h \ + err.h \ + fcntl.h \ + libgen.h \ + limits.h \ + paths.h \ + poll.h \ + ranlib.h \ + sys/mman.h \ + sys/select.h \ + sys/socket.h \ + sys/time.h \ + sys/uio.h \ + utime.h \ + ) + +dnl Both *BSD and Linux have sys/cdefs.h, most do not. +dnl If it is missing, we add -I${srcdir}/missing to CFLAGS +dnl also if sys/cdefs.h does not have __RCSID we need to use ours +dnl but we need to include the host's one too *sigh* +AC_CHECK_HEADER(sys/cdefs.h, +echo $ECHO_N "checking whether sys/cdefs.h is compatible... $ECHO_C" >&6 +AC_EGREP_CPP(yes, +[#include +#ifdef __RCSID +yes +#endif +], +echo yes >&6, +echo no >&6; CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd` -DNEED_HOST_CDEFS_H"), +CPPFLAGS="${CPPFLAGS} -I`cd ${srcdir}/missing && pwd`") + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C___ATTRIBUTE__ +AC_C_BIGENDIAN +AC_C_CONST +AC_TYPE_MODE_T +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_UINT32_T +AC_DECL_SYS_SIGLIST +AC_HEADER_TIME +AC_STRUCT_TM + +dnl Checks for library functions. +AC_TYPE_SIGNAL +AC_FUNC_VFORK +AC_FUNC_VPRINTF +AC_FUNC_WAIT3 +dnl Keep this list sorted +AC_CHECK_FUNCS( \ + err \ + errx \ + getcwd \ + getenv \ + getopt \ + getwd \ + killpg \ + mmap \ + putenv \ + select \ + setenv \ + setpgid \ + setsid \ + sigaction \ + sigvec \ + snprintf \ + strerror \ + strftime \ + strsep \ + strtod \ + strtol \ + sysctl \ + unsetenv \ + vsnprintf \ + wait3 \ + wait4 \ + waitpid \ + warn \ + warnx \ + ) + +dnl functions which we may need to provide +AC_REPLACE_FUNCS( \ + realpath \ + dirname \ + stresep \ + strlcpy \ + ) + +AC_CHECK_LIB([util], [emalloc], + [ AC_CHECK_LIB([util], [erealloc], + [ AC_CHECK_LIB([util], [estrdup], + [ AC_CHECK_LIB([util], [estrndup], + [ LIBS="$LIBS -lutil" + CPPFLAGS="$CPPFLAGS -DUSE_EMALLOC" ])])])]) + +dnl +dnl Structures +dnl +AC_HEADER_STAT +AC_STRUCT_ST_RDEV +dnl +echo "checking if compiler supports __func__" >&6 +AC_LANG(C) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[[const char *func = __func__;]])],, + AC_DEFINE(__func__, __FUNCTION__, C99 function name)) +dnl +dnl we want this for unit-tests/Makefile +echo $ECHO_N "checking if diff -u works... $ECHO_C" >&6 +if diff -u /dev/null /dev/null > /dev/null 2>&1; then + diff_u=-u + echo yes >&6 +else + diff_u= + echo no >&6 +fi +dnl +dnl AC_* don't quite cut it. +dnl +echo "checking for MACHINE & MACHINE_ARCH..." >&6 +cat > conftest.$ac_ext < +#ifdef MACHINE +machine=MACHINE +#endif +#ifdef MACHINE_ARCH +machine_arch=MACHINE_ARCH +#endif +EOF + +default_machine=`(eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep machine= | tr -d ' "'` +rm -rf conftest* +if test "$default_machine"; then + eval "$default_machine" +fi +machine=${machine:-`$srcdir/machine.sh`} +machine_arch=${machine_arch:-`$srcdir/machine.sh arch`} +echo "defaults: MACHINE=$machine, MACHINE_ARCH=$machine_arch" 1>&6 +dnl +dnl now allow overrides +dnl +AC_ARG_WITH(machine, +[ --with-machine=MACHINE explicitly set MACHINE], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for bmake MACHINE) ;; +no) ;; +generic) machine=`$srcdir/machine.sh`;; +*) machine=$with_machine;; +esac]) +force_machine= +AC_ARG_WITH(force_machine, +[ --with-force-machine=MACHINE set FORCE_MACHINE], +[case "${withval}" in +yes) force_machine=FORCE_;; +no) ;; +*) force_machine=FORCE_; machine=$with_force_machine;; +esac]) +dnl +force_machine_arch= +AC_ARG_WITH(force_machine_arch, +[ --with-force-machine-arch=MACHINE set FORCE_MACHINE_ARCH], +[case "${withval}" in +yes) force_machine_arch=FORCE_;; +no) ;; +*) force_machine_arch=FORCE_; machine_arch=$with_force_machine;; +esac]) +dnl +AC_ARG_WITH(machine_arch, +[ --with-machine_arch=MACHINE_ARCH explicitly set MACHINE_ARCH], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for bmake MACHINE_ARCH) ;; +no) ;; +*) machine_arch=$with_machine_arch;; +esac]) +dnl +dnl Tell them what we ended up with +dnl +echo "Using: ${force_machine}MACHINE=$machine, MACHINE_ARCH=$machine_arch" 1>&6 +dnl +dnl Allow folk to control _PATH_DEFSYSPATH +dnl +default_sys_path=\${prefix}/share/mk +AC_ARG_WITH(default-sys-path, +[ --with-default-sys-path=PATH:DIR:LIST use an explicit _PATH_DEFSYSPATH + MAKESYSPATH is a ':' separated list of directories + that bmake will search for system .mk files. + _PATH_DEFSYSPATH is its default value.], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for bmake _PATH_DEFSYSPATH) ;; +no) ;; +*) default_sys_path="$with_default_sys_path" + ;; +esac]) +dnl +dnl Some folk don't like this one +dnl +AC_ARG_WITH(path-objdirprefix, +[ --with-path-objdirprefix=PATH override _PATH_OBJDIRPREFIX], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for bmake _PATH_OBJDIRPREFIX) ;; +no) CPPFLAGS="$CPPFLAGS -DNO_PATH_OBJDIRPREFIX" ;; +*) CPPFLAGS="$CPPFLAGS \"-D_PATH_OBJDIRPREFIX=\\\"$with_path-objdir\\\"\"" ;; +esac]) +dnl +dnl And this can be handy to do with out. +dnl +AC_ARG_ENABLE(pwd-override, +[ --disable-pwd-override disable $PWD overriding getcwd()], +[case "${enableval}" in +yes) ;; +no) CPPFLAGS="$CPPFLAGS -DNO_PWD_OVERRIDE" ;; +*) AC_MSG_ERROR(bad value ${enableval} given for pwd-override option) ;; +esac]) +dnl +dnl Just for grins +dnl +AC_ARG_ENABLE(check-make-chdir, +[ --disable-check-make-chdir disable make trying to guess + when it should automatically cd ${.CURDIR}], +[case "${enableval}" in +yes) ;; +no) CPPFLAGS="$CPPFLAGS -DNO_CHECK_MAKE_CHDIR" ;; +*) AC_MSG_ERROR(bad value ${enableval} given for check-make-chdir option) ;; +esac]) +dnl +dnl On non-BSD systems, bootstrap won't work without mk +dnl +AC_ARG_WITH(mksrc, +[ --with-mksrc=PATH tell makefile.boot where to find mk src], +[case "${withval}" in +""|yes|no) ;; +*) test -s $withval/install-mk && mksrc=$withval || +AC_MSG_ERROR(bad value ${withval} given for mksrc cannot find install-mk) +;; +esac +]) +dnl +dnl Now make sure we have a value +dnl +srcdir=`cd $srcdir && pwd` +for mksrc in $mksrc $srcdir/mk $srcdir/../mk mk +do + test -s $mksrc/install-mk || continue + mksrc=`cd $mksrc && pwd` + break +done +mksrc=`echo $mksrc | sed "s,$srcdir,\\\${srcdir},"` +echo "Using: MKSRC=$mksrc" 1>&6 +dnl On some systems we want a different default shell by default +if test -x /usr/xpg4/bin/sh; then + defshell_path=${defshell_path:-/usr/xpg4/bin/sh} +fi +if test -n "$defshell_path"; then + echo "Using: SHELL=$defshell_path" >&6 + AC_DEFINE_UNQUOTED(DEFSHELL_CUSTOM, "$defshell_path", Path of default shell) +fi +if test -n "$DEFSHELL_INDEX"; then + AC_DEFINE_UNQUOTED(DEFSHELL_INDEX, $DEFSHELL_INDEX, Shell spec to use by default) +fi +dnl +AC_SUBST(machine) +AC_SUBST(force_machine) +AC_SUBST(machine_arch) +AC_SUBST(mksrc) +AC_SUBST(default_sys_path) +AC_SUBST(INSTALL) +AC_SUBST(GCC) +AC_SUBST(diff_u) +AC_SUBST(use_meta) +AC_SUBST(use_filemon) +AC_SUBST(filemon_h) +AC_SUBST(_MAKE_VERSION) +bm_outfiles="Makefile.config unit-tests/Makefile.config make-bootstrap.sh" +if test $use_makefile = yes; then + bm_outfiles="makefile $bm_outfiles" +fi +AC_OUTPUT($bm_outfiles) +cat < +#include + +#include +#include + +#include "make.h" +#include "dir.h" +#include "job.h" + +/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ +MAKE_RCSID("$NetBSD: dir.c,v 1.193 2020/10/31 17:39:20 rillig Exp $"); + +#define DIR_DEBUG0(text) DEBUG0(DIR, text) +#define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1) +#define DIR_DEBUG2(fmt, arg1, arg2) DEBUG2(DIR, fmt, arg1, arg2) + +/* A search path is a list of CachedDir structures. A CachedDir has in it the + * name of the directory and the names of all the files in the directory. + * This is used to cut down on the number of system calls necessary to find + * implicit dependents and their like. Since these searches are made before + * any actions are taken, we need not worry about the directory changing due + * to creation commands. If this hampers the style of some makefiles, they + * must be changed. + * + * All previously-read directories are kept in openDirs, which is checked + * first before a directory is opened. + * + * The need for the caching of whole directories is brought about by the + * multi-level transformation code in suff.c, which tends to search for far + * more files than regular make does. In the initial implementation, the + * amount of time spent performing "stat" calls was truly astronomical. + * The problem with caching at the start is, of course, that pmake doesn't + * then detect changes to these directories during the course of the make. + * Three possibilities suggest themselves: + * + * 1) just use stat to test for a file's existence. As mentioned above, + * this is very inefficient due to the number of checks engendered by + * the multi-level transformation code. + * + * 2) use readdir() and company to search the directories, keeping them + * open between checks. I have tried this and while it didn't slow down + * the process too much, it could severely affect the amount of + * parallelism available as each directory open would take another file + * descriptor out of play for handling I/O for another job. Given that + * it is only recently that UNIX OS's have taken to allowing more than + * 20 or 32 file descriptors for a process, this doesn't seem acceptable + * to me. + * + * 3) record the mtime of the directory in the CachedDir structure and + * verify the directory hasn't changed since the contents were cached. + * This will catch the creation or deletion of files, but not the + * updating of files. However, since it is the creation and deletion + * that is the problem, this could be a good thing to do. Unfortunately, + * if the directory (say ".") were fairly large and changed fairly + * frequently, the constant reloading could seriously degrade + * performance. It might be good in such cases to keep track of the + * number of reloadings and if the number goes over a (small) limit, + * resort to using stat in its place. + * + * An additional thing to consider is that pmake is used primarily to create + * C programs and until recently pcc-based compilers refused to allow you to + * specify where the resulting object file should be placed. This forced all + * objects to be created in the current directory. This isn't meant as a full + * excuse, just an explanation of some of the reasons for the caching used + * here. + * + * One more note: the location of a target's file is only performed on the + * downward traversal of the graph and then only for terminal nodes in the + * graph. This could be construed as wrong in some cases, but prevents + * inadvertent modification of files when the "installed" directory for a + * file is provided in the search path. + * + * Another data structure maintained by this module is an mtime cache used + * when the searching of cached directories fails to find a file. In the past, + * Dir_FindFile would simply perform an access() call in such a case to + * determine if the file could be found using just the name given. When this + * hit, however, all that was gained was the knowledge that the file existed. + * Given that an access() is essentially a stat() without the copyout() call, + * and that the same filesystem overhead would have to be incurred in + * Dir_MTime, it made sense to replace the access() with a stat() and record + * the mtime in a cache for when Dir_MTime was actually called. + */ + +typedef List CachedDirList; +typedef ListNode CachedDirListNode; + +typedef ListNode SearchPathNode; + +SearchPath *dirSearchPath; /* main search path */ + +/* A list of cached directories, with fast lookup by directory name. */ +typedef struct OpenDirs { + CachedDirList *list; + HashTable /* of CachedDirListNode */ table; +} OpenDirs; + +static void +OpenDirs_Init(OpenDirs *odirs) +{ + odirs->list = Lst_New(); + HashTable_Init(&odirs->table); +} + +#ifdef CLEANUP +static void +OpenDirs_Done(OpenDirs *odirs) +{ + CachedDirListNode *ln = odirs->list->first; + while (ln != NULL) { + CachedDirListNode *next = ln->next; + CachedDir *dir = ln->datum; + Dir_Destroy(dir); /* removes the dir from odirs->list */ + ln = next; + } + Lst_Free(odirs->list); + HashTable_Done(&odirs->table); +} +#endif + +static CachedDir * +OpenDirs_Find(OpenDirs *odirs, const char *name) +{ + CachedDirListNode *ln = HashTable_FindValue(&odirs->table, name); + return ln != NULL ? ln->datum : NULL; +} + +static void +OpenDirs_Add(OpenDirs *odirs, CachedDir *cdir) +{ + HashEntry *he = HashTable_FindEntry(&odirs->table, cdir->name); + if (he != NULL) + return; + he = HashTable_CreateEntry(&odirs->table, cdir->name, NULL); + Lst_Append(odirs->list, cdir); + HashEntry_Set(he, odirs->list->last); +} + +static void +OpenDirs_Remove(OpenDirs *odirs, const char *name) +{ + HashEntry *he = HashTable_FindEntry(&odirs->table, name); + CachedDirListNode *ln; + if (he == NULL) + return; + ln = HashEntry_Get(he); + HashTable_DeleteEntry(&odirs->table, he); + Lst_Remove(odirs->list, ln); +} + +static OpenDirs openDirs; /* the list of all open directories */ + +/* + * Variables for gathering statistics on the efficiency of the cashing + * mechanism. + */ +static int hits; /* Found in directory cache */ +static int misses; /* Sad, but not evil misses */ +static int nearmisses; /* Found under search path */ +static int bigmisses; /* Sought by itself */ + +static CachedDir *dot; /* contents of current directory */ +static CachedDir *cur; /* contents of current directory, if not dot */ +static CachedDir *dotLast; /* a fake path entry indicating we need to + * look for . last */ + +/* Results of doing a last-resort stat in Dir_FindFile -- if we have to go to + * the system to find the file, we might as well have its mtime on record. + * + * XXX: If this is done way early, there's a chance other rules will have + * already updated the file, in which case we'll update it again. Generally, + * there won't be two rules to update a single file, so this should be ok, + * but... */ +static HashTable mtimes; + +static HashTable lmtimes; /* same as mtimes but for lstat */ + +/* + * We use stat(2) a lot, cache the results. + * mtime and mode are all we care about. + */ +struct cache_st { + time_t lmtime; /* lstat */ + time_t mtime; /* stat */ + mode_t mode; +}; + +/* minimize changes below */ +typedef enum CachedStatsFlags { + CST_LSTAT = 0x01, /* call lstat(2) instead of stat(2) */ + CST_UPDATE = 0x02 /* ignore existing cached entry */ +} CachedStatsFlags; + +/* Returns 0 and the result of stat(2) or lstat(2) in *mst, or -1 on error. */ +static int +cached_stats(HashTable *htp, const char *pathname, struct make_stat *mst, + CachedStatsFlags flags) +{ + HashEntry *entry; + struct stat sys_st; + struct cache_st *cst; + int rc; + + if (!pathname || !pathname[0]) + return -1; + + entry = HashTable_FindEntry(htp, pathname); + + if (entry && !(flags & CST_UPDATE)) { + cst = HashEntry_Get(entry); + + mst->mst_mode = cst->mode; + mst->mst_mtime = (flags & CST_LSTAT) ? cst->lmtime : cst->mtime; + if (mst->mst_mtime) { + DIR_DEBUG2("Using cached time %s for %s\n", + Targ_FmtTime(mst->mst_mtime), pathname); + return 0; + } + } + + rc = (flags & CST_LSTAT) + ? lstat(pathname, &sys_st) + : stat(pathname, &sys_st); + if (rc == -1) + return -1; + + if (sys_st.st_mtime == 0) + sys_st.st_mtime = 1; /* avoid confusion with missing file */ + + mst->mst_mode = sys_st.st_mode; + mst->mst_mtime = sys_st.st_mtime; + + if (entry == NULL) + entry = HashTable_CreateEntry(htp, pathname, NULL); + if (HashEntry_Get(entry) == NULL) { + HashEntry_Set(entry, bmake_malloc(sizeof(*cst))); + memset(HashEntry_Get(entry), 0, sizeof(*cst)); + } + cst = HashEntry_Get(entry); + if (flags & CST_LSTAT) { + cst->lmtime = sys_st.st_mtime; + } else { + cst->mtime = sys_st.st_mtime; + } + cst->mode = sys_st.st_mode; + DIR_DEBUG2(" Caching %s for %s\n", + Targ_FmtTime(sys_st.st_mtime), pathname); + + return 0; +} + +int +cached_stat(const char *pathname, struct make_stat *st) +{ + return cached_stats(&mtimes, pathname, st, 0); +} + +int +cached_lstat(const char *pathname, struct make_stat *st) +{ + return cached_stats(&lmtimes, pathname, st, CST_LSTAT); +} + +/* Initialize the directories module. */ +void +Dir_Init(void) +{ + dirSearchPath = Lst_New(); + OpenDirs_Init(&openDirs); + HashTable_Init(&mtimes); + HashTable_Init(&lmtimes); +} + +void +Dir_InitDir(const char *cdname) +{ + Dir_InitCur(cdname); + + dotLast = bmake_malloc(sizeof(CachedDir)); + dotLast->refCount = 1; + dotLast->hits = 0; + dotLast->name = bmake_strdup(".DOTLAST"); + HashTable_Init(&dotLast->files); +} + +/* + * Called by Dir_InitDir and whenever .CURDIR is assigned to. + */ +void +Dir_InitCur(const char *cdname) +{ + CachedDir *dir; + + if (cdname != NULL) { + /* + * Our build directory is not the same as our source directory. + * Keep this one around too. + */ + if ((dir = Dir_AddDir(NULL, cdname))) { + dir->refCount++; + if (cur && cur != dir) { + /* + * We've been here before, clean up. + */ + cur->refCount--; + Dir_Destroy(cur); + } + cur = dir; + } + } +} + +/* (Re)initialize "dot" (current/object directory) path hash. + * Some directories may be opened. */ +void +Dir_InitDot(void) +{ + if (dot != NULL) { + /* Remove old entry from openDirs, but do not destroy. */ + OpenDirs_Remove(&openDirs, dot->name); + } + + dot = Dir_AddDir(NULL, "."); + + if (dot == NULL) { + Error("Cannot open `.' (%s)", strerror(errno)); + exit(1); + } + + /* + * We always need to have dot around, so we increment its reference count + * to make sure it's not destroyed. + */ + dot->refCount++; + Dir_SetPATH(); /* initialize */ +} + +/* Clean up the directories module. */ +void +Dir_End(void) +{ +#ifdef CLEANUP + if (cur) { + cur->refCount--; + Dir_Destroy(cur); + } + dot->refCount--; + dotLast->refCount--; + Dir_Destroy(dotLast); + Dir_Destroy(dot); + Dir_ClearPath(dirSearchPath); + Lst_Free(dirSearchPath); + OpenDirs_Done(&openDirs); + HashTable_Done(&mtimes); +#endif +} + +/* + * We want ${.PATH} to indicate the order in which we will actually + * search, so we rebuild it after any .PATH: target. + * This is the simplest way to deal with the effect of .DOTLAST. + */ +void +Dir_SetPATH(void) +{ + CachedDirListNode *ln; + Boolean hasLastDot = FALSE; /* true if we should search dot last */ + + Var_Delete(".PATH", VAR_GLOBAL); + + if ((ln = dirSearchPath->first) != NULL) { + CachedDir *dir = ln->datum; + if (dir == dotLast) { + hasLastDot = TRUE; + Var_Append(".PATH", dotLast->name, VAR_GLOBAL); + } + } + + if (!hasLastDot) { + if (dot) + Var_Append(".PATH", dot->name, VAR_GLOBAL); + if (cur) + Var_Append(".PATH", cur->name, VAR_GLOBAL); + } + + for (ln = dirSearchPath->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + if (dir == dotLast) + continue; + if (dir == dot && hasLastDot) + continue; + Var_Append(".PATH", dir->name, VAR_GLOBAL); + } + + if (hasLastDot) { + if (dot) + Var_Append(".PATH", dot->name, VAR_GLOBAL); + if (cur) + Var_Append(".PATH", cur->name, VAR_GLOBAL); + } +} + +/* See if the given name has any wildcard characters in it and all braces and + * brackets are properly balanced. + * + * XXX: This code is not 100% correct ([^]] fails etc.). I really don't think + * 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. + */ +Boolean +Dir_HasWildcards(const char *name) +{ + const char *p; + Boolean wild = FALSE; + int braces = 0, brackets = 0; + + for (p = name; *p != '\0'; p++) { + switch (*p) { + case '{': + braces++; + wild = TRUE; + break; + case '}': + braces--; + break; + case '[': + brackets++; + wild = TRUE; + break; + case ']': + brackets--; + break; + case '?': + case '*': + wild = TRUE; + break; + default: + break; + } + } + return wild && brackets == 0 && braces == 0; +} + +/* See if any files match the pattern and add their names to the 'expansions' + * list if they do. + * + * This is incomplete -- wildcards are only expanded in the final path + * component, but not in directories like src/lib*c/file*.c, but it + * will do for now (now being 1993 until at least 2020). To expand these, + * use the ':sh' variable modifier such as in ${:!echo src/lib*c/file*.c!}. + * + * Input: + * pattern Pattern to look for + * dir Directory to search + * expansion Place to store the results + */ +static void +DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions) +{ + const char *dirName = dir->name; + Boolean isDot = dirName[0] == '.' && dirName[1] == '\0'; + HashIter hi; + + HashIter_Init(&hi, &dir->files); + while (HashIter_Next(&hi) != NULL) { + const char *base = hi.entry->key; + + if (!Str_Match(base, pattern)) + continue; + + /* + * Follow the UNIX convention that dot files are only found if the + * pattern begins with a dot. The pattern '.*' does not match '.' or + * '..' since these are not included in the directory cache. + * + * This means that the pattern '[a-z.]*' does not find '.file', which + * is consistent with bash, NetBSD sh and csh. + */ + if (base[0] == '.' && pattern[0] != '.') + continue; + + { + char *fullName = isDot + ? bmake_strdup(base) + : str_concat3(dirName, "/", base); + Lst_Append(expansions, fullName); + } + } +} + +/* Find the next closing brace in the string, taking nested braces into + * account. */ +static const char * +closing_brace(const char *p) +{ + int nest = 0; + while (*p != '\0') { + if (*p == '}' && nest == 0) + break; + if (*p == '{') + nest++; + if (*p == '}') + nest--; + p++; + } + return p; +} + +/* Find the next closing brace or comma in the string, taking nested braces + * into account. */ +static const char * +separator_comma(const char *p) +{ + int nest = 0; + while (*p != '\0') { + if ((*p == '}' || *p == ',') && nest == 0) + break; + if (*p == '{') + nest++; + if (*p == '}') + nest--; + p++; + } + return p; +} + +static Boolean +contains_wildcard(const char *p) +{ + for (; *p != '\0'; p++) { + switch (*p) { + case '*': + case '?': + case '{': + case '[': + return TRUE; + } + } + return FALSE; +} + +static char * +concat3(const char *a, size_t a_len, const char *b, size_t b_len, + const char *c, size_t c_len) +{ + size_t s_len = a_len + b_len + c_len; + char *s = bmake_malloc(s_len + 1); + memcpy(s, a, a_len); + memcpy(s + a_len, b, b_len); + memcpy(s + a_len + b_len, c, c_len); + s[s_len] = '\0'; + return s; +} + +/* Expand curly braces like the C shell. Brace expansion by itself is purely + * textual, the expansions are not looked up in the file system. But if an + * expanded word contains wildcard characters, it is expanded further, + * matching only the actually existing files. + * + * Example: "{a{b,c}}" expands to "ab" and "ac". + * Example: "{a}" expands to "a". + * Example: "{a,*.c}" expands to "a" and all "*.c" files that exist. + * + * Input: + * word Entire word to expand + * brace First curly brace in it + * path Search path to use + * expansions Place to store the expansions + */ +static void +DirExpandCurly(const char *word, const char *brace, SearchPath *path, + StringList *expansions) +{ + const char *prefix, *middle, *piece, *middle_end, *suffix; + size_t prefix_len, suffix_len; + + /* Split the word into prefix '{' middle '}' suffix. */ + + middle = brace + 1; + middle_end = closing_brace(middle); + if (*middle_end == '\0') { + Error("Unterminated {} clause \"%s\"", middle); + return; + } + + prefix = word; + prefix_len = (size_t)(brace - prefix); + suffix = middle_end + 1; + suffix_len = strlen(suffix); + + /* Split the middle into pieces, separated by commas. */ + + piece = middle; + while (piece < middle_end + 1) { + const char *piece_end = separator_comma(piece); + size_t piece_len = (size_t)(piece_end - piece); + + char *file = concat3(prefix, prefix_len, piece, piece_len, + suffix, suffix_len); + + if (contains_wildcard(file)) { + Dir_Expand(file, path, expansions); + free(file); + } else { + Lst_Append(expansions, file); + } + + piece = piece_end + 1; /* skip over the comma or closing brace */ + } +} + + +/* Expand the word in each of the directories from the path. */ +static void +DirExpandPath(const char *word, SearchPath *path, StringList *expansions) +{ + SearchPathNode *ln; + for (ln = path->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + DirMatchFiles(word, dir, expansions); + } +} + +static void +PrintExpansions(StringList *expansions) +{ + const char *sep = ""; + StringListNode *ln; + for (ln = expansions->first; ln != NULL; ln = ln->next) { + const char *word = ln->datum; + debug_printf("%s%s", sep, word); + sep = " "; + } + debug_printf("\n"); +} + +/* Expand the given word into a list of words by globbing it, looking in the + * directories on the given search path. + * + * Input: + * word the word to expand + * path the directories in which to find the files + * expansions the list on which to place the results + */ +void +Dir_Expand(const char *word, SearchPath *path, StringList *expansions) +{ + const char *cp; + + assert(path != NULL); + assert(expansions != NULL); + + DIR_DEBUG1("Expanding \"%s\"... ", word); + + cp = strchr(word, '{'); + if (cp) { + DirExpandCurly(word, cp, path, expansions); + } else { + cp = strchr(word, '/'); + if (cp) { + /* + * The thing has a directory component -- find the first wildcard + * in the string. + */ + for (cp = word; *cp; cp++) { + if (*cp == '?' || *cp == '[' || *cp == '*') { + break; + } + } + + if (*cp != '\0') { + /* + * Back up to the start of the component + */ + while (cp > word && *cp != '/') { + cp--; + } + if (cp != word) { + char *prefix = bmake_strsedup(word, cp + 1); + /* + * If the glob isn't in the first component, try and find + * all the components up to the one with a wildcard. + */ + char *dirpath = Dir_FindFile(prefix, path); + free(prefix); + /* + * dirpath is null if can't find the leading component + * XXX: Dir_FindFile won't find internal components. + * i.e. if the path contains ../Etc/Object and we're + * looking for Etc, it won't be found. Ah well. + * Probably not important. + */ + if (dirpath != NULL) { + char *dp = &dirpath[strlen(dirpath) - 1]; + if (*dp == '/') + *dp = '\0'; + path = Lst_New(); + (void)Dir_AddDir(path, dirpath); + DirExpandPath(cp + 1, path, expansions); + Lst_Free(path); + } + } else { + /* + * Start the search from the local directory + */ + DirExpandPath(word, path, expansions); + } + } else { + /* + * Return the file -- this should never happen. + */ + DirExpandPath(word, path, expansions); + } + } else { + /* + * First the files in dot + */ + DirMatchFiles(word, dot, expansions); + + /* + * Then the files in every other directory on the path. + */ + DirExpandPath(word, path, expansions); + } + } + if (DEBUG(DIR)) + PrintExpansions(expansions); +} + +/* Find if the file with the given name exists in the given path. + * Return the freshly allocated path to the file, or NULL. */ +static char * +DirLookup(CachedDir *dir, const char *base) +{ + char *file; /* the current filename to check */ + + DIR_DEBUG1(" %s ...\n", dir->name); + + if (HashTable_FindEntry(&dir->files, base) == NULL) + return NULL; + + file = str_concat3(dir->name, "/", base); + DIR_DEBUG1(" returning %s\n", file); + dir->hits++; + hits++; + return file; +} + + +/* Find if the file with the given name exists in the given directory. + * Return the freshly allocated path to the file, or NULL. */ +static char * +DirLookupSubdir(CachedDir *dir, const char *name) +{ + struct make_stat mst; + char *file = dir == dot ? bmake_strdup(name) + : str_concat3(dir->name, "/", name); + + DIR_DEBUG1("checking %s ...\n", file); + + if (cached_stat(file, &mst) == 0) { + nearmisses++; + return file; + } + free(file); + return NULL; +} + +/* Find if the file with the given name exists in the given path. + * Return the freshly allocated path to the file, the empty string, or NULL. + * Returning the empty string means that the search should be terminated. + */ +static char * +DirLookupAbs(CachedDir *dir, const char *name, const char *cp) +{ + const char *dnp; /* pointer into dir->name */ + const char *np; /* pointer into name */ + + DIR_DEBUG1(" %s ...\n", dir->name); + + /* + * If the file has a leading path component and that component + * exactly matches the entire name of the current search + * directory, we can attempt another cache lookup. And if we don't + * have a hit, we can safely assume the file does not exist at all. + */ + for (dnp = dir->name, np = name; *dnp != '\0' && *dnp == *np; dnp++, np++) + continue; + if (*dnp != '\0' || np != cp - 1) + return NULL; + + if (HashTable_FindEntry(&dir->files, cp) == NULL) { + DIR_DEBUG0(" must be here but isn't -- returning\n"); + return bmake_strdup(""); /* to terminate the search */ + } + + dir->hits++; + hits++; + DIR_DEBUG1(" returning %s\n", name); + return bmake_strdup(name); +} + +/* Find the file given on "." or curdir. + * Return the freshly allocated path to the file, or NULL. */ +static char * +DirFindDot(const char *name, const char *base) +{ + + if (HashTable_FindEntry(&dot->files, base) != NULL) { + DIR_DEBUG0(" in '.'\n"); + hits++; + dot->hits++; + return bmake_strdup(name); + } + + if (cur != NULL && HashTable_FindEntry(&cur->files, base) != NULL) { + DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name); + hits++; + cur->hits++; + return str_concat3(cur->name, "/", base); + } + + return NULL; +} + +/* Find the file with the given name along the given search path. + * + * If the file is found in a directory that is not on the path + * already (either 'name' is absolute or it is a relative path + * [ dir1/.../dirn/file ] which exists below one of the directories + * already on the search path), its directory is added to the end + * of the path, on the assumption that there will be more files in + * that directory later on. Sometimes this is true. Sometimes not. + * + * Input: + * name the file to find + * path the directories to search, or NULL + * + * Results: + * The freshly allocated path to the file, or NULL. + */ +char * +Dir_FindFile(const char *name, SearchPath *path) +{ + SearchPathNode *ln; + char *file; /* the current filename to check */ + const char *base; /* Terminal name of file */ + Boolean hasLastDot = FALSE; /* true if we should search dot last */ + Boolean hasSlash; /* true if 'name' contains a / */ + struct make_stat mst; /* Buffer for stat, if necessary */ + const char *trailing_dot = "."; + + /* + * Find the final component of the name and note whether it has a + * slash in it (the name, I mean) + */ + base = strrchr(name, '/'); + if (base) { + hasSlash = TRUE; + base++; + } else { + hasSlash = FALSE; + base = name; + } + + DIR_DEBUG1("Searching for %s ...", name); + + if (path == NULL) { + DIR_DEBUG0("couldn't open path, file not found\n"); + misses++; + return NULL; + } + + if ((ln = path->first) != NULL) { + CachedDir *dir = ln->datum; + if (dir == dotLast) { + hasLastDot = TRUE; + DIR_DEBUG0("[dot last]..."); + } + } + DIR_DEBUG0("\n"); + + /* + * If there's no leading directory components or if the leading + * directory component is exactly `./', consult the cached contents + * of each of the directories on the search path. + */ + if (!hasSlash || (base - name == 2 && *name == '.')) { + /* + * We look through all the directories on the path seeking one which + * contains the final component of the given name. If such a beast + * is found, we concatenate the directory name and the final + * component and return the resulting string. If we don't find any + * such thing, we go on to phase two... + * + * No matter what, we always look for the file in the current + * directory before anywhere else (unless we found the magic + * DOTLAST path, in which case we search it last) and we *do not* + * add the ./ to it if it exists. + * This is so there are no conflicts between what the user + * specifies (fish.c) and what pmake finds (./fish.c). + */ + if (!hasLastDot && (file = DirFindDot(name, base)) != NULL) + return file; + + for (; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + if (dir == dotLast) + continue; + if ((file = DirLookup(dir, base)) != NULL) + return file; + } + + if (hasLastDot && (file = DirFindDot(name, base)) != NULL) + return file; + } + + /* + * We didn't find the file on any directory in the search path. + * If the name doesn't contain a slash, that means it doesn't exist. + * If it *does* contain a slash, however, there is still hope: it + * could be in a subdirectory of one of the members of the search + * path. (eg. /usr/include and sys/types.h. The above search would + * fail to turn up types.h in /usr/include, but it *is* in + * /usr/include/sys/types.h). + * [ This no longer applies: If we find such a beast, we assume there + * will be more (what else can we assume?) and add all but the last + * component of the resulting name onto the search path (at the + * end).] + * This phase is only performed if the file is *not* absolute. + */ + if (!hasSlash) { + DIR_DEBUG0(" failed.\n"); + misses++; + return NULL; + } + + if (*base == '\0') { + /* we were given a trailing "/" */ + base = trailing_dot; + } + + if (name[0] != '/') { + Boolean checkedDot = FALSE; + + DIR_DEBUG0(" Trying subdirectories...\n"); + + if (!hasLastDot) { + if (dot) { + checkedDot = TRUE; + if ((file = DirLookupSubdir(dot, name)) != NULL) + return file; + } + if (cur && (file = DirLookupSubdir(cur, name)) != NULL) + return file; + } + + for (ln = path->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + if (dir == dotLast) + continue; + if (dir == dot) { + if (checkedDot) + continue; + checkedDot = TRUE; + } + if ((file = DirLookupSubdir(dir, name)) != NULL) + return file; + } + + if (hasLastDot) { + if (dot && !checkedDot) { + checkedDot = TRUE; + if ((file = DirLookupSubdir(dot, name)) != NULL) + return file; + } + if (cur && (file = DirLookupSubdir(cur, name)) != NULL) + return file; + } + + if (checkedDot) { + /* + * Already checked by the given name, since . was in the path, + * so no point in proceeding... + */ + DIR_DEBUG0(" Checked . already, returning NULL\n"); + return NULL; + } + + } else { /* name[0] == '/' */ + + /* + * For absolute names, compare directory path prefix against the + * the directory path of each member on the search path for an exact + * match. If we have an exact match on any member of the search path, + * use the cached contents of that member to lookup the final file + * component. If that lookup fails we can safely assume that the + * file does not exist at all. This is signified by DirLookupAbs() + * returning an empty string. + */ + DIR_DEBUG0(" Trying exact path matches...\n"); + + if (!hasLastDot && cur && + ((file = DirLookupAbs(cur, name, base)) != NULL)) { + if (file[0] == '\0') { + free(file); + return NULL; + } + return file; + } + + for (ln = path->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + if (dir == dotLast) + continue; + if ((file = DirLookupAbs(dir, name, base)) != NULL) { + if (file[0] == '\0') { + free(file); + return NULL; + } + return file; + } + } + + if (hasLastDot && cur && + ((file = DirLookupAbs(cur, name, base)) != NULL)) { + if (file[0] == '\0') { + free(file); + return NULL; + } + return file; + } + } + + /* + * Didn't find it that way, either. Sigh. Phase 3. Add its directory + * onto the search path in any case, just in case, then look for the + * thing in the hash table. If we find it, grand. We return a new + * copy of the name. Otherwise we sadly return a NULL pointer. Sigh. + * Note that if the directory holding the file doesn't exist, this will + * do an extra search of the final directory on the path. Unless something + * weird happens, this search won't succeed and life will be groovy. + * + * Sigh. We cannot add the directory onto the search path because + * of this amusing case: + * $(INSTALLDIR)/$(FILE): $(FILE) + * + * $(FILE) exists in $(INSTALLDIR) but not in the current one. + * When searching for $(FILE), we will find it in $(INSTALLDIR) + * b/c we added it here. This is not good... + */ +#ifdef notdef + if (base == trailing_dot) { + base = strrchr(name, '/'); + base++; + } + base[-1] = '\0'; + (void)Dir_AddDir(path, name); + base[-1] = '/'; + + bigmisses++; + ln = Lst_Last(path); + if (ln == NULL) { + return NULL; + } else { + dir = LstNode_Datum(ln); + } + + if (Hash_FindEntry(&dir->files, base) != NULL) { + return bmake_strdup(name); + } else { + return NULL; + } +#else /* !notdef */ + DIR_DEBUG1(" Looking for \"%s\" ...\n", name); + + bigmisses++; + if (cached_stat(name, &mst) == 0) { + return bmake_strdup(name); + } + + DIR_DEBUG0(" failed. Returning NULL\n"); + return NULL; +#endif /* notdef */ +} + + +/* Search for a path starting at a given directory and then working our way + * up towards the root. + * + * Input: + * here starting directory + * search_path the relative path we are looking for + * + * Results: + * The found path, or NULL. + */ +char * +Dir_FindHereOrAbove(const char *here, const char *search_path) +{ + struct make_stat mst; + char *dirbase, *dirbase_end; + char *try, *try_end; + + /* copy out our starting point */ + dirbase = bmake_strdup(here); + dirbase_end = dirbase + strlen(dirbase); + + /* loop until we determine a result */ + for (;;) { + + /* try and stat(2) it ... */ + try = str_concat3(dirbase, "/", search_path); + if (cached_stat(try, &mst) != -1) { + /* + * success! if we found a file, chop off + * the filename so we return a directory. + */ + if ((mst.mst_mode & S_IFMT) != S_IFDIR) { + try_end = try + strlen(try); + while (try_end > try && *try_end != '/') + try_end--; + if (try_end > try) + *try_end = '\0'; /* chop! */ + } + + free(dirbase); + return try; + } + free(try); + + /* + * nope, we didn't find it. if we used up dirbase we've + * reached the root and failed. + */ + if (dirbase_end == dirbase) + break; /* failed! */ + + /* + * truncate dirbase from the end to move up a dir + */ + while (dirbase_end > dirbase && *dirbase_end != '/') + dirbase_end--; + *dirbase_end = '\0'; /* chop! */ + } + + free(dirbase); + return NULL; +} + +/*- + *----------------------------------------------------------------------- + * Dir_MTime -- + * Find the modification time of the file described by gn along the + * search path dirSearchPath. + * + * Input: + * gn the file whose modification time is desired + * + * Results: + * The modification time or 0 if it doesn't exist + * + * Side Effects: + * The modification time is placed in the node's mtime slot. + * If the node didn't have a path entry before, and Dir_FindFile + * found one for it, the full name is placed in the path slot. + *----------------------------------------------------------------------- + */ +time_t +Dir_MTime(GNode *gn, Boolean recheck) +{ + char *fullName; /* the full pathname of name */ + struct make_stat mst; /* buffer for finding the mod time */ + + if (gn->type & OP_ARCHV) { + return Arch_MTime(gn); + } else if (gn->type & OP_PHONY) { + gn->mtime = 0; + return 0; + } else if (gn->path == NULL) { + if (gn->type & OP_NOPATH) + fullName = NULL; + else { + fullName = Dir_FindFile(gn->name, Suff_FindPath(gn)); + if (fullName == NULL && gn->flags & FROM_DEPEND && + !Lst_IsEmpty(gn->implicitParents)) { + char *cp; + + cp = strrchr(gn->name, '/'); + if (cp) { + /* + * This is an implied source, and it may have moved, + * see if we can find it via the current .PATH + */ + cp++; + + fullName = Dir_FindFile(cp, Suff_FindPath(gn)); + if (fullName) { + /* + * Put the found file in gn->path + * so that we give that to the compiler. + */ + gn->path = bmake_strdup(fullName); + if (!Job_RunTarget(".STALE", gn->fname)) + fprintf(stdout, + "%s: %s, %d: ignoring stale %s for %s, " + "found %s\n", progname, gn->fname, + gn->lineno, + makeDependfile, gn->name, fullName); + } + } + } + DIR_DEBUG2("Found '%s' as '%s'\n", + gn->name, fullName ? fullName : "(not found)"); + } + } else { + fullName = gn->path; + } + + if (fullName == NULL) { + fullName = bmake_strdup(gn->name); + } + + if (cached_stats(&mtimes, fullName, &mst, recheck ? CST_UPDATE : 0) < 0) { + if (gn->type & OP_MEMBER) { + if (fullName != gn->path) + free(fullName); + return Arch_MemMTime(gn); + } else { + mst.mst_mtime = 0; + } + } + + if (fullName != NULL && gn->path == NULL) + gn->path = fullName; + + gn->mtime = mst.mst_mtime; + return gn->mtime; +} + +/* Read the list of filenames in the directory and store the result + * in openDirectories. + * + * If a path is given, append the directory to that path. + * + * Input: + * path The path to which the directory should be + * added, or NULL to only add the directory to + * openDirectories + * name The name of the directory to add. + * The name is not normalized in any way. + */ +CachedDir * +Dir_AddDir(SearchPath *path, const char *name) +{ + CachedDir *dir = NULL; /* the added directory */ + DIR *d; + struct dirent *dp; + + if (path != NULL && strcmp(name, ".DOTLAST") == 0) { + SearchPathNode *ln; + + for (ln = path->first; ln != NULL; ln = ln->next) { + CachedDir *pathDir = ln->datum; + if (strcmp(pathDir->name, name) == 0) + return pathDir; + } + + dotLast->refCount++; + Lst_Prepend(path, dotLast); + } + + if (path != NULL) + dir = OpenDirs_Find(&openDirs, name); + if (dir != NULL) { + if (Lst_FindDatum(path, dir) == NULL) { + dir->refCount++; + Lst_Append(path, dir); + } + return dir; + } + + DIR_DEBUG1("Caching %s ...", name); + + if ((d = opendir(name)) != NULL) { + dir = bmake_malloc(sizeof(CachedDir)); + dir->name = bmake_strdup(name); + dir->hits = 0; + dir->refCount = 1; + HashTable_Init(&dir->files); + + while ((dp = readdir(d)) != NULL) { +#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ + /* + * The sun directory library doesn't check for a 0 inode + * (0-inode slots just take up space), so we have to do + * it ourselves. + */ + if (dp->d_fileno == 0) { + continue; + } +#endif /* sun && d_ino */ + (void)HashTable_CreateEntry(&dir->files, dp->d_name, NULL); + } + (void)closedir(d); + OpenDirs_Add(&openDirs, dir); + if (path != NULL) + Lst_Append(path, dir); + } + DIR_DEBUG0("done\n"); + return dir; +} + +/* Return a copy of dirSearchPath, incrementing the reference counts for + * the contained directories. */ +SearchPath * +Dir_CopyDirSearchPath(void) +{ + SearchPath *path = Lst_New(); + SearchPathNode *ln; + for (ln = dirSearchPath->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + dir->refCount++; + Lst_Append(path, dir); + } + return path; +} + +/*- + *----------------------------------------------------------------------- + * Dir_MakeFlags -- + * Make a string by taking all the directories in the given search + * path and preceding them by the given flag. Used by the suffix + * module to create variables for compilers based on suffix search + * paths. + * + * Input: + * flag flag which should precede each directory + * path list of directories + * + * Results: + * The string mentioned above. Note that there is no space between + * the given flag and each directory. The empty string is returned if + * Things don't go well. + * + * Side Effects: + * None + *----------------------------------------------------------------------- + */ +char * +Dir_MakeFlags(const char *flag, SearchPath *path) +{ + Buffer buf; + SearchPathNode *ln; + + Buf_Init(&buf, 0); + + if (path != NULL) { + for (ln = path->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + Buf_AddStr(&buf, " "); + Buf_AddStr(&buf, flag); + Buf_AddStr(&buf, dir->name); + } + } + + return Buf_Destroy(&buf, FALSE); +} + +/* Nuke a directory descriptor, if possible. Callback procedure for the + * suffixes module when destroying a search path. + * + * Input: + * dirp The directory descriptor to nuke + */ +void +Dir_Destroy(void *dirp) +{ + CachedDir *dir = dirp; + dir->refCount--; + + if (dir->refCount == 0) { + OpenDirs_Remove(&openDirs, dir->name); + + HashTable_Done(&dir->files); + free(dir->name); + free(dir); + } +} + +/* Clear out all elements from the given search path. + * The path is set to the empty list but is not destroyed. */ +void +Dir_ClearPath(SearchPath *path) +{ + while (!Lst_IsEmpty(path)) { + CachedDir *dir = Lst_Dequeue(path); + Dir_Destroy(dir); + } +} + + +/* Concatenate two paths, adding the second to the end of the first, + * skipping duplicates. */ +void +Dir_Concat(SearchPath *dst, SearchPath *src) +{ + SearchPathNode *ln; + + for (ln = src->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + if (Lst_FindDatum(dst, dir) == NULL) { + dir->refCount++; + Lst_Append(dst, dir); + } + } +} + +static int +percentage(int num, int den) +{ + return den != 0 ? num * 100 / den : 0; +} + +/********** DEBUG INFO **********/ +void +Dir_PrintDirectories(void) +{ + CachedDirListNode *ln; + + debug_printf("#*** Directory Cache:\n"); + debug_printf("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", + hits, misses, nearmisses, bigmisses, + percentage(hits, hits + bigmisses + nearmisses)); + debug_printf("# %-20s referenced\thits\n", "directory"); + + for (ln = openDirs.list->first; ln != NULL; ln = ln->next) { + CachedDir *dir = ln->datum; + debug_printf("# %-20s %10d\t%4d\n", dir->name, dir->refCount, + dir->hits); + } +} + +void +Dir_PrintPath(SearchPath *path) +{ + SearchPathNode *node; + for (node = path->first; node != NULL; node = node->next) { + const CachedDir *dir = node->datum; + debug_printf("%s ", dir->name); + } +} Property changes on: vendor/NetBSD/bmake/20201101/dir.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/dir.h =================================================================== --- vendor/NetBSD/bmake/20201101/dir.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/dir.h (revision 367461) @@ -0,0 +1,123 @@ +/* $NetBSD: dir.h,v 1.32 2020/10/25 10:00:20 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)dir.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)dir.h 8.1 (Berkeley) 6/6/93 + */ + +#ifndef MAKE_DIR_H +#define MAKE_DIR_H + +/* A cache for the filenames in a directory. */ +typedef struct CachedDir { + char *name; /* Name of directory, either absolute or + * relative to the current directory. + * The name is not normalized in any way, + * that is, "." and "./." are different. + * + * Not sure what happens when .CURDIR is + * assigned a new value; see Parse_DoVar. */ + int refCount; /* Number of SearchPaths with this directory */ + int hits; /* The number of times a file in this + * directory has been found */ + HashTable files; /* Hash set of files in directory; + * all values are NULL. */ +} CachedDir; + +void Dir_Init(void); +void Dir_InitDir(const char *); +void Dir_InitCur(const char *); +void Dir_InitDot(void); +void Dir_End(void); +void Dir_SetPATH(void); +Boolean Dir_HasWildcards(const char *); +void Dir_Expand(const char *, SearchPath *, StringList *); +char *Dir_FindFile(const char *, SearchPath *); +char *Dir_FindHereOrAbove(const char *, const char *); +time_t Dir_MTime(GNode *, Boolean); +CachedDir *Dir_AddDir(SearchPath *, const char *); +char *Dir_MakeFlags(const char *, SearchPath *); +void Dir_ClearPath(SearchPath *); +void Dir_Concat(SearchPath *, SearchPath *); +void Dir_PrintDirectories(void); +void Dir_PrintPath(SearchPath *); +void Dir_Destroy(void *); +SearchPath *Dir_CopyDirSearchPath(void); + +/* Stripped-down variant of struct stat. */ +struct make_stat { + time_t mst_mtime; + mode_t mst_mode; +}; + +int cached_lstat(const char *, struct make_stat *); +int cached_stat(const char *, struct make_stat *); + +#endif /* MAKE_DIR_H */ Property changes on: vendor/NetBSD/bmake/20201101/dir.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/enum.c =================================================================== --- vendor/NetBSD/bmake/20201101/enum.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/enum.c (revision 367461) @@ -0,0 +1,89 @@ +/* $NetBSD: enum.c,v 1.12 2020/10/05 19:27:47 rillig Exp $ */ + +/* + Copyright (c) 2020 Roland Illig + 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. + */ + +#include "make.h" + +MAKE_RCSID("$NetBSD: enum.c,v 1.12 2020/10/05 19:27:47 rillig Exp $"); + +/* Convert a bitset into a string representation, showing the names of the + * individual bits. + * + * Optionally, shortcuts for groups of bits can be added. To have an effect, + * they need to be listed before their individual bits. */ +const char * +Enum_FlagsToString(char *buf, size_t buf_size, + int value, const EnumToStringSpec *spec) +{ + const char *buf_start = buf; + const char *sep = ""; + size_t sep_len = 0; + + for (; spec->es_value != 0; spec++) { + size_t name_len; + + if ((value & spec->es_value) != spec->es_value) + continue; + value &= ~spec->es_value; + + assert(buf_size >= sep_len + 1); + memcpy(buf, sep, sep_len); + buf += sep_len; + buf_size -= sep_len; + + name_len = strlen(spec->es_name); + assert(buf_size >= name_len + 1); + memcpy(buf, spec->es_name, name_len); + buf += name_len; + buf_size -= name_len; + + sep = ENUM__SEP; + sep_len = sizeof ENUM__SEP - 1; + } + + /* If this assertion fails, the listed enum values are incomplete. */ + assert(value == 0); + + if (buf == buf_start) + return "none"; + + assert(buf_size >= 1); + buf[0] = '\0'; + return buf_start; +} + +/* Convert a fixed-value enum into a string representation. */ +const char * +Enum_ValueToString(int value, const EnumToStringSpec *spec) +{ + for (; spec->es_name[0] != '\0'; spec++) { + if (value == spec->es_value) + return spec->es_name; + } + abort(/* unknown enum value */); +} Property changes on: vendor/NetBSD/bmake/20201101/enum.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/enum.h =================================================================== --- vendor/NetBSD/bmake/20201101/enum.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/enum.h (revision 367461) @@ -0,0 +1,215 @@ +/* $NetBSD: enum.h,v 1.12 2020/09/25 15:54:50 rillig Exp $ */ + +/* + Copyright (c) 2020 Roland Illig + 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. + */ + +#ifndef MAKE_ENUM_H +#define MAKE_ENUM_H + +/* Generate string representations for bitmasks and simple enums. */ + +#include + +typedef struct EnumToStringSpec { + int es_value; + const char *es_name; +} EnumToStringSpec; + +const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *); +const char *Enum_ValueToString(int, const EnumToStringSpec *); + +/* For Enum_FlagsToString, the separator between flags. */ +#define ENUM__SEP "|" + +/* Generate the string that joins all possible flags, to see how large the + * buffer must be. */ +#define ENUM__JOIN_STR_1(v1) \ + #v1 +#define ENUM__JOIN_STR_2(v1, v2) \ + ENUM__JOIN_STR_1(v1) ENUM__SEP \ + ENUM__JOIN_STR_1(v2) +#define ENUM__JOIN_STR_4(v1, v2, v3, v4) \ + ENUM__JOIN_STR_2(v1, v2) ENUM__SEP \ + ENUM__JOIN_STR_2(v3, v4) +#define ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8) \ + ENUM__JOIN_STR_4(v1, v2, v3, v4) ENUM__SEP \ + ENUM__JOIN_STR_4(v5, v6, v7, v8) +#define ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \ + v09, v10, v11, v12, v13, v14, v15, v16) \ + ENUM__JOIN_STR_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \ + ENUM__JOIN_STR_8(v09, v10, v11, v12, v13, v14, v15, v16) + +#define ENUM__JOIN_2(part1, part2) \ + part1 ENUM__SEP part2 +#define ENUM__JOIN_3(part1, part2, part3) \ + part1 ENUM__SEP part2 ENUM__SEP part3 +#define ENUM__JOIN_4(part1, part2, part3, part4) \ + part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 +#define ENUM__JOIN_5(part1, part2, part3, part4, part5) \ + part1 ENUM__SEP part2 ENUM__SEP part3 ENUM__SEP part4 ENUM__SEP part5 + +/* List the pairs of enum value and corresponding name. */ +#define ENUM__SPEC_1(v1) \ + { v1, #v1 } +#define ENUM__SPEC_2(v1, v2) \ + ENUM__SPEC_1(v1), \ + ENUM__SPEC_1(v2) +#define ENUM__SPEC_4(v1, v2, v3, v4) \ + ENUM__SPEC_2(v1, v2), \ + ENUM__SPEC_2(v3, v4) +#define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \ + ENUM__SPEC_4(v1, v2, v3, v4), \ + ENUM__SPEC_4(v5, v6, v7, v8) +#define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \ + v09, v10, v11, v12, v13, v14, v15, v16) \ + ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \ + ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16) + +#define ENUM__SPECS_2(part1, part2) \ + { part1, part2, { 0, "" } } +#define ENUM__SPECS_3(part1, part2, part3) \ + { part1, part2, part3, { 0, "" } } +#define ENUM__SPECS_4(part1, part2, part3, part4) \ + { part1, part2, part3, part4, { 0, "" } } +#define ENUM__SPECS_5(part1, part2, part3, part4, part5) \ + { part1, part2, part3, part4, part5, { 0, "" } } + +/* Declare the necessary data structures for calling Enum_ValueToString. */ +#define ENUM__VALUE_RTTI(typnam, specs) \ + static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs + +/* Declare the necessary data structures for calling Enum_FlagsToString. */ +#define ENUM__FLAGS_RTTI(typnam, specs, joined) \ + static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \ + enum { typnam ## _ ## ToStringSize = sizeof joined } + +/* 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. */ +#define ENUM_FLAGS_RTTI_3(typnam, v1, v2, v3) \ + ENUM__FLAGS_RTTI(typnam, \ + ENUM__SPECS_2( \ + ENUM__SPEC_2(v1, v2), \ + ENUM__SPEC_1(v3)), \ + ENUM__JOIN_2( \ + ENUM__JOIN_STR_2(v1, v2), \ + ENUM__JOIN_STR_1(v3))) + +/* Declare the necessary data structures for calling Enum_FlagsToString + * for an enum with 6 flags. */ +#define ENUM_FLAGS_RTTI_6(typnam, v1, v2, v3, v4, v5, v6) \ + ENUM__FLAGS_RTTI(typnam, \ + ENUM__SPECS_2( \ + ENUM__SPEC_4(v1, v2, v3, v4), \ + ENUM__SPEC_2(v5, v6)), \ + ENUM__JOIN_2( \ + 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_ValueToString + * for an enum with 8 constants. */ +#define ENUM_VALUE_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \ + ENUM__VALUE_RTTI(typnam, \ + ENUM__SPECS_2( \ + ENUM__SPEC_4(v1, v2, v3, v4), \ + ENUM__SPEC_4(v5, v6, v7, v8))) + +/* Declare the necessary data structures for calling Enum_FlagsToString + * for an enum with 10 flags. */ +#define ENUM_FLAGS_RTTI_10(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \ + ENUM__FLAGS_RTTI(typnam, \ + ENUM__SPECS_2( \ + ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \ + ENUM__SPEC_2(v9, v10)), \ + ENUM__JOIN_2( \ + ENUM__JOIN_STR_8(v1, v2, v3, v4, v5, v6, v7, v8), \ + ENUM__JOIN_STR_2(v9, v10))) + +/* Declare the necessary data structures for calling Enum_FlagsToString + * for an enum with 31 flags. */ +#define ENUM_FLAGS_RTTI_31(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) \ + ENUM__FLAGS_RTTI(typnam, \ + ENUM__SPECS_5( \ + ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \ + v09, v10, v11, v12, v13, v14, v15, v16), \ + ENUM__SPEC_8(v17, v18, v19, v20, v21, v22, v23, v24), \ + ENUM__SPEC_4(v25, v26, v27, v28), \ + ENUM__SPEC_2(v29, v30), \ + ENUM__SPEC_1(v31)), \ + ENUM__JOIN_5( \ + ENUM__JOIN_STR_16(v01, v02, v03, v04, v05, v06, v07, v08, \ + v09, v10, v11, v12, v13, v14, v15, v16), \ + ENUM__JOIN_STR_8(v17, v18, v19, v20, v21, v22, v23, v24), \ + ENUM__JOIN_STR_4(v25, v26, v27, v28), \ + 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 Property changes on: vendor/NetBSD/bmake/20201101/enum.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/filemon/filemon.h =================================================================== --- vendor/NetBSD/bmake/20201101/filemon/filemon.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/filemon/filemon.h (revision 367461) @@ -0,0 +1,53 @@ +/* $NetBSD: filemon.h,v 1.3 2020/10/18 11:49:47 rillig Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef MAKE_FILEMON_H +#define MAKE_FILEMON_H + +#include + +struct filemon; + +const char * + filemon_path(void); + +struct filemon * + filemon_open(void); +int filemon_close(struct filemon *); + +int filemon_setfd(struct filemon *, int); +void filemon_setpid_parent(struct filemon *, pid_t); +int filemon_setpid_child(const struct filemon *, pid_t); + +int filemon_readfd(const struct filemon *); +int filemon_process(struct filemon *); + +#endif /* MAKE_FILEMON_H */ Property changes on: vendor/NetBSD/bmake/20201101/filemon/filemon.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/filemon/filemon_ktrace.c =================================================================== --- vendor/NetBSD/bmake/20201101/filemon/filemon_ktrace.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/filemon/filemon_ktrace.c (revision 367461) @@ -0,0 +1,878 @@ +/* $NetBSD: filemon_ktrace.c,v 1.3 2020/10/18 11:54:43 rillig Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#define _KERNTYPES /* register_t */ + +#include "filemon.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef AT_CWD +#define AT_CWD -1 +#endif + +struct filemon; +struct filemon_key; +struct filemon_state; + +typedef struct filemon_state *filemon_syscall_t(struct filemon *, + const struct filemon_key *, const struct ktr_syscall *); + +static filemon_syscall_t filemon_sys_chdir; +static filemon_syscall_t filemon_sys_execve; +static filemon_syscall_t filemon_sys_exit; +static filemon_syscall_t filemon_sys_fork; +static filemon_syscall_t filemon_sys_link; +static filemon_syscall_t filemon_sys_open; +static filemon_syscall_t filemon_sys_openat; +static filemon_syscall_t filemon_sys_symlink; +static filemon_syscall_t filemon_sys_unlink; +static filemon_syscall_t filemon_sys_rename; + +static filemon_syscall_t *const filemon_syscalls[] = { + [SYS_chdir] = &filemon_sys_chdir, + [SYS_execve] = &filemon_sys_execve, + [SYS_exit] = &filemon_sys_exit, + [SYS_fork] = &filemon_sys_fork, + [SYS_link] = &filemon_sys_link, + [SYS_open] = &filemon_sys_open, + [SYS_openat] = &filemon_sys_openat, + [SYS_symlink] = &filemon_sys_symlink, + [SYS_unlink] = &filemon_sys_unlink, + [SYS_rename] = &filemon_sys_rename, +}; + +struct filemon { + int ktrfd; /* kernel writes ktrace events here */ + FILE *in; /* we read ktrace events from here */ + FILE *out; /* we write filemon events to here */ + rb_tree_t active; + pid_t child; + + /* I/O state machine. */ + enum { + FILEMON_START = 0, + FILEMON_HEADER, + FILEMON_PAYLOAD, + FILEMON_ERROR, + } state; + unsigned char *p; + size_t resid; + + /* I/O buffer. */ + struct ktr_header hdr; + union { + struct ktr_syscall syscall; + struct ktr_sysret sysret; + char namei[PATH_MAX]; + unsigned char buf[4096]; + } payload; +}; + +struct filemon_state { + struct filemon_key { + pid_t pid; + lwpid_t lid; + } key; + struct rb_node node; + int syscode; + void (*show)(struct filemon *, const struct filemon_state *, + const struct ktr_sysret *); + unsigned i; + unsigned npath; + char *path[/*npath*/]; +}; + +static int +compare_filemon_states(void *cookie, const void *na, const void *nb) +{ + const struct filemon_state *Sa = na; + const struct filemon_state *Sb = nb; + + if (Sa->key.pid < Sb->key.pid) + return -1; + if (Sa->key.pid > Sb->key.pid) + return +1; + if (Sa->key.lid < Sb->key.lid) + return -1; + if (Sa->key.lid > Sb->key.lid) + return +1; + return 0; +} + +static int +compare_filemon_key(void *cookie, const void *n, const void *k) +{ + const struct filemon_state *S = n; + const struct filemon_key *key = k; + + if (S->key.pid < key->pid) + return -1; + if (S->key.pid > key->pid) + return +1; + if (S->key.lid < key->lid) + return -1; + if (S->key.lid > key->lid) + return +1; + return 0; +} + +static const rb_tree_ops_t filemon_rb_ops = { + .rbto_compare_nodes = &compare_filemon_states, + .rbto_compare_key = &compare_filemon_key, + .rbto_node_offset = offsetof(struct filemon_state, node), + .rbto_context = NULL, +}; + +/* + * filemon_path() + * + * Return a pointer to a constant string denoting the `path' of + * the filemon. + */ +const char * +filemon_path(void) +{ + + return "ktrace"; +} + +/* + * filemon_open() + * + * Allocate a filemon descriptor. Returns NULL and sets errno on + * failure. + */ +struct filemon * +filemon_open(void) +{ + struct filemon *F; + int ktrpipe[2]; + int error; + + /* Allocate and zero a struct filemon object. */ + F = calloc(1, sizeof(*F)); + if (F == NULL) + return NULL; + + /* Create a pipe for ktrace events. */ + if (pipe2(ktrpipe, O_CLOEXEC|O_NONBLOCK) == -1) { + error = errno; + goto fail0; + } + + /* Create a file stream for reading the ktrace events. */ + if ((F->in = fdopen(ktrpipe[0], "r")) == NULL) { + error = errno; + goto fail1; + } + ktrpipe[0] = -1; /* claimed by fdopen */ + + /* + * Set the fd for writing ktrace events and initialize the + * rbtree. The rest can be safely initialized to zero. + */ + F->ktrfd = ktrpipe[1]; + rb_tree_init(&F->active, &filemon_rb_ops); + + /* Success! */ + return F; + +fail2: __unused + (void)fclose(F->in); +fail1: (void)close(ktrpipe[0]); + (void)close(ktrpipe[1]); +fail0: free(F); + errno = error; + return NULL; +} + +/* + * filemon_closefd(F) + * + * Internal subroutine to try to flush and close the output file. + * If F is not open for output, do nothing. Never leaves F open + * for output even on failure. Returns 0 on success; sets errno + * and return -1 on failure. + */ +static int +filemon_closefd(struct filemon *F) +{ + int error = 0; + + /* If we're not open, nothing to do. */ + if (F->out == NULL) + return 0; + + /* + * Flush it, close it, and null it unconditionally, but be + * careful to return the earliest error in errno. + */ + if (fflush(F->out) == EOF && error == 0) + error = errno; + if (fclose(F->out) == EOF && error == 0) + error = errno; + F->out = NULL; + + /* Set errno and return -1 if anything went wrong. */ + if (error) { + errno = error; + return -1; + } + + /* Success! */ + return 0; +} + +/* + * filemon_setfd(F, fd) + * + * Cause filemon activity on F to be sent to fd. Claims ownership + * of fd; caller should not use fd afterward, and any duplicates + * of fd may see their file positions changed. + */ +int +filemon_setfd(struct filemon *F, int fd) +{ + + /* + * Close an existing output file if done. Fail now if there's + * an error closing. + */ + if ((filemon_closefd(F)) == -1) + return -1; + assert(F->out == NULL); + + /* Open a file stream and claim ownership of the fd. */ + if ((F->out = fdopen(fd, "a")) == NULL) + return -1; + + /* + * Print the opening output. Any failure will be deferred + * until closing. For hysterical raisins, we show the parent + * pid, not the child pid. + */ + fprintf(F->out, "# filemon version 4\n"); + fprintf(F->out, "# Target pid %jd\n", (intmax_t)getpid()); + fprintf(F->out, "V 4\n"); + + /* Success! */ + return 0; +} + +/* + * filemon_setpid_parent(F, pid) + * + * Set the traced pid, from the parent. Never fails. + */ +void +filemon_setpid_parent(struct filemon *F, pid_t pid) +{ + + F->child = pid; +} + +/* + * filemon_setpid_child(F, pid) + * + * Set the traced pid, from the child. Returns 0 on success; sets + * errno and returns -1 on failure. + */ +int +filemon_setpid_child(const struct filemon *F, pid_t pid) +{ + int ops, trpoints; + + ops = KTROP_SET|KTRFLAG_DESCEND; + trpoints = KTRFACv2; + trpoints |= KTRFAC_SYSCALL|KTRFAC_NAMEI|KTRFAC_SYSRET; + trpoints |= KTRFAC_INHERIT; + if (fktrace(F->ktrfd, ops, trpoints, pid) == -1) + return -1; + + return 0; +} + +/* + * filemon_close(F) + * + * Close F for output if necessary, and free a filemon descriptor. + * Returns 0 on success; sets errno and returns -1 on failure, but + * frees the filemon descriptor either way; + */ +int +filemon_close(struct filemon *F) +{ + struct filemon_state *S; + int error = 0; + + /* Close for output. */ + if (filemon_closefd(F) == -1 && error == 0) + error = errno; + + /* Close the ktrace pipe. */ + if (fclose(F->in) == EOF && error == 0) + error = errno; + if (close(F->ktrfd) == -1 && error == 0) + error = errno; + + /* Free any active records. */ + while ((S = RB_TREE_MIN(&F->active)) != NULL) { + rb_tree_remove_node(&F->active, S); + free(S); + } + + /* Free the filemon descriptor. */ + free(F); + + /* Set errno and return -1 if anything went wrong. */ + if (error) { + errno = error; + return -1; + } + + /* Success! */ + return 0; +} + +/* + * filemon_readfd(F) + * + * Returns a file descriptor which will select/poll ready for read + * when there are filemon events to be processed by + * filemon_process, or -1 if anything has gone wrong. + */ +int +filemon_readfd(const struct filemon *F) +{ + + if (F->state == FILEMON_ERROR) + return -1; + return fileno(F->in); +} + +/* + * filemon_dispatch(F) + * + * Internal subroutine to dispatch a filemon ktrace event. + * Silently ignore events that we don't recognize. + */ +static void +filemon_dispatch(struct filemon *F) +{ + const struct filemon_key key = { + .pid = F->hdr.ktr_pid, + .lid = F->hdr.ktr_lid, + }; + struct filemon_state *S; + + switch (F->hdr.ktr_type) { + case KTR_SYSCALL: { + struct ktr_syscall *call = &F->payload.syscall; + struct filemon_state *S1; + + /* Validate the syscall code. */ + if (call->ktr_code < 0 || + (size_t)call->ktr_code >= __arraycount(filemon_syscalls) || + filemon_syscalls[call->ktr_code] == NULL) + break; + + /* + * Invoke the syscall-specific logic to create a new + * active state. + */ + S = (*filemon_syscalls[call->ktr_code])(F, &key, call); + if (S == NULL) + break; + + /* + * Insert the active state, or ignore it if there + * already is one. + * + * Collisions shouldn't happen because the states are + * keyed by , in which syscalls should happen + * sequentially in CALL/RET pairs, but let's be + * defensive. + */ + S1 = rb_tree_insert_node(&F->active, S); + if (S1 != S) { + /* XXX Which one to drop? */ + free(S); + break; + } + break; + } + case KTR_NAMEI: + /* Find an active syscall state, or drop it. */ + S = rb_tree_find_node(&F->active, &key); + if (S == NULL) + break; + /* Find the position of the next path, or drop it. */ + if (S->i >= S->npath) + break; + /* Record the path. */ + S->path[S->i++] = strndup(F->payload.namei, + sizeof F->payload.namei); + break; + case KTR_SYSRET: { + struct ktr_sysret *ret = &F->payload.sysret; + unsigned i; + + /* Find and remove an active syscall state, or drop it. */ + S = rb_tree_find_node(&F->active, &key); + if (S == NULL) + break; + rb_tree_remove_node(&F->active, S); + + /* + * If the active syscall state matches this return, + * invoke the syscall-specific logic to show a filemon + * event. + */ + /* XXX What to do if syscall code doesn't match? */ + if (S->i == S->npath && S->syscode == ret->ktr_code) + S->show(F, S, ret); + + /* Free the state now that it is no longer active. */ + for (i = 0; i < S->i; i++) + free(S->path[i]); + free(S); + break; + } + default: + /* Ignore all other ktrace events. */ + break; + } +} + +/* + * filemon_process(F) + * + * Process all pending events after filemon_readfd(F) has + * selected/polled ready for read. + * + * Returns -1 on failure, 0 on end of events, and anything else if + * there may be more events. + * + * XXX What about fairness to other activities in the event loop? + * If we stop while there's events buffered in F->in, then select + * or poll may not return ready even though there's work queued up + * in the buffer of F->in, but if we don't stop then ktrace events + * may overwhelm all other activity in the event loop. + */ +int +filemon_process(struct filemon *F) +{ + size_t nread; + +top: /* If the child has exited, nothing to do. */ + /* XXX What if one thread calls exit while another is running? */ + if (F->child == 0) + return 0; + + /* If we're waiting for input, read some. */ + if (F->resid) { + nread = fread(F->p, 1, F->resid, F->in); + if (nread == 0) { + if (feof(F->in)) + return 0; + assert(ferror(F->in)); + /* + * If interrupted or would block, there may be + * more events. Otherwise fail. + */ + if (errno == EAGAIN || errno == EINTR) + return 1; + F->state = FILEMON_ERROR; + F->p = NULL; + F->resid = 0; + return -1; + } + assert(nread <= F->resid); + F->p += nread; + F->resid -= nread; + if (F->resid) /* may be more events */ + return 1; + } + + /* Process a state transition now that we've read a buffer. */ + switch (F->state) { + case FILEMON_START: /* just started filemon; read header next */ + F->state = FILEMON_HEADER; + F->p = (void *)&F->hdr; + F->resid = sizeof F->hdr; + goto top; + case FILEMON_HEADER: /* read header */ + /* Sanity-check ktrace header; then read payload. */ + if (F->hdr.ktr_len < 0 || + (size_t)F->hdr.ktr_len > sizeof F->payload) { + F->state = FILEMON_ERROR; + F->p = NULL; + F->resid = 0; + errno = EIO; + return -1; + } + F->state = FILEMON_PAYLOAD; + F->p = (void *)&F->payload; + F->resid = (size_t)F->hdr.ktr_len; + goto top; + case FILEMON_PAYLOAD: /* read header and payload */ + /* Dispatch ktrace event; then read next header. */ + filemon_dispatch(F); + F->state = FILEMON_HEADER; + F->p = (void *)&F->hdr; + F->resid = sizeof F->hdr; + goto top; + default: /* paranoia */ + F->state = FILEMON_ERROR; + /*FALLTHROUGH*/ + case FILEMON_ERROR: /* persistent error indicator */ + F->p = NULL; + F->resid = 0; + errno = EIO; + return -1; + } +} + +static struct filemon_state * +syscall_enter(struct filemon *F, + const struct filemon_key *key, const struct ktr_syscall *call, + unsigned npath, + void (*show)(struct filemon *, const struct filemon_state *, + const struct ktr_sysret *)) +{ + struct filemon_state *S; + unsigned i; + + S = calloc(1, offsetof(struct filemon_state, path[npath])); + if (S == NULL) + return NULL; + S->key = *key; + S->show = show; + S->syscode = call->ktr_code; + S->i = 0; + S->npath = npath; + for (i = 0; i < npath; i++) + S->path[i] = NULL; /* paranoia */ + + return S; +} + +static void +show_paths(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret, const char *prefix) +{ + unsigned i; + + /* Caller must ensure all paths have been specified. */ + assert(S->i == S->npath); + + /* + * Ignore it if it failed or yielded EJUSTRETURN (-2), or if + * we're not producing output. + */ + if (ret->ktr_error && ret->ktr_error != -2) + return; + if (F->out == NULL) + return; + + /* + * Print the prefix, pid, and paths -- with the paths quoted if + * there's more than one. + */ + fprintf(F->out, "%s %jd", prefix, (intmax_t)S->key.pid); + for (i = 0; i < S->npath; i++) { + const char *q = S->npath > 1 ? "'" : ""; + fprintf(F->out, " %s%s%s", q, S->path[i], q); + } + fprintf(F->out, "\n"); +} + +static void +show_retval(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret, const char *prefix) +{ + + /* + * Ignore it if it failed or yielded EJUSTRETURN (-2), or if + * we're not producing output. + */ + if (ret->ktr_error && ret->ktr_error != -2) + return; + if (F->out == NULL) + return; + + fprintf(F->out, "%s %jd %jd\n", prefix, (intmax_t)S->key.pid, + (intmax_t)ret->ktr_retval); +} + +static void +show_chdir(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "C"); +} + +static void +show_execve(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + return show_paths(F, S, ret, "E"); +} + +static void +show_fork(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_retval(F, S, ret, "F"); +} + +static void +show_link(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "L"); /* XXX same as symlink */ +} + +static void +show_open_read(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "R"); +} + +static void +show_open_write(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "W"); +} + +static void +show_open_readwrite(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "R"); + show_paths(F, S, ret, "W"); +} + +static void +show_openat_read(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + if (S->path[0][0] != '/') + show_paths(F, S, ret, "A"); + show_paths(F, S, ret, "R"); +} + +static void +show_openat_write(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + if (S->path[0][0] != '/') + show_paths(F, S, ret, "A"); + show_paths(F, S, ret, "W"); +} + +static void +show_openat_readwrite(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + if (S->path[0][0] != '/') + show_paths(F, S, ret, "A"); + show_paths(F, S, ret, "R"); + show_paths(F, S, ret, "W"); +} + +static void +show_symlink(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "L"); /* XXX same as link */ +} + +static void +show_unlink(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "D"); +} + +static void +show_rename(struct filemon *F, const struct filemon_state *S, + const struct ktr_sysret *ret) +{ + show_paths(F, S, ret, "M"); +} + +static struct filemon_state * +filemon_sys_chdir(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 1, &show_chdir); +} + +static struct filemon_state * +filemon_sys_execve(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 1, &show_execve); +} + +static struct filemon_state * +filemon_sys_exit(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + const register_t *args = (const void *)&call[1]; + int status = (int)args[0]; + + if (F->out) { + fprintf(F->out, "X %jd %d\n", (intmax_t)key->pid, status); + if (key->pid == F->child) { + fprintf(F->out, "# Bye bye\n"); + F->child = 0; + } + } + return NULL; +} + +static struct filemon_state * +filemon_sys_fork(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 0, &show_fork); +} + +static struct filemon_state * +filemon_sys_link(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 2, &show_link); +} + +static struct filemon_state * +filemon_sys_open(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + const register_t *args = (const void *)&call[1]; + int flags; + + if (call->ktr_argsize < 2) + return NULL; + flags = (int)args[1]; + + if ((flags & O_RDWR) == O_RDWR) + return syscall_enter(F, key, call, 1, &show_open_readwrite); + else if ((flags & O_WRONLY) == O_WRONLY) + return syscall_enter(F, key, call, 1, &show_open_write); + else if ((flags & O_RDONLY) == O_RDONLY) + return syscall_enter(F, key, call, 1, &show_open_read); + else + return NULL; /* XXX Do we care if no read or write? */ +} + +static struct filemon_state * +filemon_sys_openat(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + const register_t *args = (const void *)&call[1]; + int flags, fd; + + if (call->ktr_argsize < 3) + return NULL; + fd = (int)args[0]; + flags = (int)args[2]; + + if (fd == AT_CWD) { + if ((flags & O_RDWR) == O_RDWR) + return syscall_enter(F, key, call, 1, + &show_open_readwrite); + else if ((flags & O_WRONLY) == O_WRONLY) + return syscall_enter(F, key, call, 1, + &show_open_write); + else if ((flags & O_RDONLY) == O_RDONLY) + return syscall_enter(F, key, call, 1, &show_open_read); + else + return NULL; + } else { + if ((flags & O_RDWR) == O_RDWR) + return syscall_enter(F, key, call, 1, + &show_openat_readwrite); + else if ((flags & O_WRONLY) == O_WRONLY) + return syscall_enter(F, key, call, 1, + &show_openat_write); + else if ((flags & O_RDONLY) == O_RDONLY) + return syscall_enter(F, key, call, 1, + &show_openat_read); + else + return NULL; + } +} + +static struct filemon_state * +filemon_sys_symlink(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 2, &show_symlink); +} + +static struct filemon_state * +filemon_sys_unlink(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 1, &show_unlink); +} + +static struct filemon_state * +filemon_sys_rename(struct filemon *F, const struct filemon_key *key, + const struct ktr_syscall *call) +{ + return syscall_enter(F, key, call, 2, &show_rename); +} Property changes on: vendor/NetBSD/bmake/20201101/filemon/filemon_ktrace.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/filemon/filemon_dev.c =================================================================== --- vendor/NetBSD/bmake/20201101/filemon/filemon_dev.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/filemon/filemon_dev.c (revision 367461) @@ -0,0 +1,151 @@ +/* $NetBSD: filemon_dev.c,v 1.3 2020/07/10 15:53:30 sjg Exp $ */ + +/*- + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include "filemon.h" + +#include + +#include +#include +#include +#include + +#ifdef HAVE_FILEMON_H +# include +#endif + +#ifndef _PATH_FILEMON +#define _PATH_FILEMON "/dev/filemon" +#endif + +struct filemon { + int fd; +}; + +const char * +filemon_path(void) +{ + + return _PATH_FILEMON; +} + +struct filemon * +filemon_open(void) +{ + struct filemon *F; + unsigned i; + int error; + + /* Allocate and zero a struct filemon object. */ + F = calloc(1, sizeof(*F)); + if (F == NULL) + return NULL; + + /* Try opening /dev/filemon, up to six times (cargo cult!). */ + for (i = 0; (F->fd = open(_PATH_FILEMON, O_RDWR|O_CLOEXEC)) == -1; i++) { + if (i == 5) { + error = errno; + goto fail0; + } + } + + /* Success! */ + return F; + +fail0: free(F); + errno = error; + return NULL; +} + +int +filemon_setfd(struct filemon *F, int fd) +{ + + /* Point the kernel at this file descriptor. */ + if (ioctl(F->fd, FILEMON_SET_FD, &fd) == -1) + return -1; + + /* No need for it in userland any more; close it. */ + (void)close(fd); + + /* Success! */ + return 0; +} + +void +filemon_setpid_parent(struct filemon *F, pid_t pid) +{ + /* Nothing to do! */ +} + +int +filemon_setpid_child(const struct filemon *F, pid_t pid) +{ + + /* Just pass it on to the kernel. */ + return ioctl(F->fd, FILEMON_SET_PID, &pid); +} + +int +filemon_close(struct filemon *F) +{ + int error = 0; + + /* Close the filemon device fd. */ + if (close(F->fd) == -1 && error == 0) + error = errno; + + /* Free the filemon descriptor. */ + free(F); + + /* Set errno and return -1 if anything went wrong. */ + if (error) { + errno = error; + return -1; + } + + /* Success! */ + return 0; +} + +int +filemon_readfd(const struct filemon *F) +{ + + return -1; +} + +int +filemon_process(struct filemon *F) +{ + + return 0; +} Property changes on: vendor/NetBSD/bmake/20201101/filemon/filemon_dev.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/for.c =================================================================== --- vendor/NetBSD/bmake/20201101/for.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/for.c (revision 367461) @@ -0,0 +1,499 @@ +/* $NetBSD: for.c,v 1.112 2020/10/31 18:41:07 rillig Exp $ */ + +/* + * Copyright (c) 1992, The Regents of the University of California. + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * Handling of .for/.endfor loops in a makefile. + * + * For loops are of the form: + * + * .for in + * ... + * .endfor + * + * When a .for line is parsed, all following lines are accumulated into a + * buffer, up to but excluding the corresponding .endfor line. To find the + * corresponding .endfor, the number of nested .for and .endfor directives + * are counted. + * + * During parsing, any nested .for loops are just passed through; they get + * handled recursively in For_Eval when the enclosing .for loop is evaluated + * in For_Run. + * + * When the .for loop has been parsed completely, the variable expressions + * for the iteration variables are replaced with expressions of the form + * ${:Uvalue}, and then this modified body is "included" as a special file. + * + * Interface: + * For_Eval Evaluate the loop in the passed line. + * + * For_Run Run accumulated loop + */ + +#include "make.h" + +/* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ +MAKE_RCSID("$NetBSD: for.c,v 1.112 2020/10/31 18:41:07 rillig Exp $"); + +/* The .for loop substitutes the items as ${:U...}, which means + * that characters that break this syntax must be backslash-escaped. */ +typedef enum ForEscapes { + FOR_SUB_ESCAPE_CHAR = 0x0001, + FOR_SUB_ESCAPE_BRACE = 0x0002, + FOR_SUB_ESCAPE_PAREN = 0x0004 +} ForEscapes; + +static int forLevel = 0; /* Nesting level */ + +/* One of the variables to the left of the "in" in a .for loop. */ +typedef struct ForVar { + char *name; + size_t len; +} ForVar; + +/* + * State of a for loop. + */ +typedef struct For { + Buffer body; /* Unexpanded body of the loop */ + Vector /* of ForVar */ vars; /* Iteration variables */ + Words items; /* Substitution items */ + Buffer curBody; /* Expanded body of the current iteration */ + /* 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; + unsigned int sub_next; /* Where to continue iterating */ +} For; + +static For *accumFor; /* Loop being accumulated */ + +static void +ForAddVar(For *f, const char *name, size_t len) +{ + ForVar *var = Vector_Push(&f->vars); + var->name = bmake_strldup(name, len); + var->len = len; +} + +static void +For_Free(For *f) +{ + Buf_Destroy(&f->body, TRUE); + + while (f->vars.len > 0) { + ForVar *var = Vector_Pop(&f->vars); + free(var->name); + } + Vector_Done(&f->vars); + + Words_Free(f->items); + Buf_Destroy(&f->curBody, TRUE); + + free(f); +} + +static ForEscapes +GetEscapes(const char *word) +{ + const char *p; + ForEscapes escapes = 0; + + for (p = word; *p != '\0'; p++) { + switch (*p) { + case ':': + case '$': + case '\\': + escapes |= FOR_SUB_ESCAPE_CHAR; + break; + case ')': + escapes |= FOR_SUB_ESCAPE_PAREN; + break; + case '}': + escapes |= FOR_SUB_ESCAPE_BRACE; + break; + } + } + return escapes; +} + +static Boolean +IsFor(const char *p) +{ + return p[0] == 'f' && p[1] == 'o' && p[2] == 'r' && ch_isspace(p[3]); +} + +static Boolean +IsEndfor(const char *p) +{ + return p[0] == 'e' && strncmp(p, "endfor", 6) == 0 && + (p[6] == '\0' || ch_isspace(p[6])); +} + +/* Evaluate the for loop in the passed line. The line looks like this: + * .for in + * + * Input: + * line Line to parse + * + * Results: + * 0: Not a .for statement, parse the line + * 1: We found a for loop + * -1: A .for statement with a bad syntax error, discard. + */ +int +For_Eval(const char *line) +{ + For *f; + const char *p; + + p = line + 1; /* skip the '.' */ + cpp_skip_whitespace(&p); + + if (!IsFor(p)) { + if (IsEndfor(p)) { + Parse_Error(PARSE_FATAL, "for-less endfor"); + return -1; + } + return 0; + } + p += 3; + + /* + * we found a for loop, and now we are going to parse it. + */ + + f = bmake_malloc(sizeof *f); + Buf_Init(&f->body, 0); + Vector_Init(&f->vars, sizeof(ForVar)); + f->items.words = NULL; + f->items.freeIt = NULL; + Buf_Init(&f->curBody, 0); + f->short_var = FALSE; + f->sub_next = 0; + + /* Grab the variables. Terminate on "in". */ + for (;;) { + size_t len; + + cpp_skip_whitespace(&p); + if (*p == '\0') { + Parse_Error(PARSE_FATAL, "missing `in' in for"); + For_Free(f); + return -1; + } + + /* XXX: This allows arbitrary variable names; see directive-for.mk. */ + for (len = 1; p[len] != '\0' && !ch_isspace(p[len]); len++) + continue; + + if (len == 2 && p[0] == 'i' && p[1] == 'n') { + p += 2; + break; + } + if (len == 1) + f->short_var = TRUE; + + ForAddVar(f, p, len); + p += len; + } + + if (f->vars.len == 0) { + Parse_Error(PARSE_FATAL, "no iteration variables in for"); + For_Free(f); + return -1; + } + + cpp_skip_whitespace(&p); + + { + char *items; + (void)Var_Subst(p, VAR_GLOBAL, VARE_WANTRES, &items); + /* TODO: handle errors */ + f->items = Str_Words(items, FALSE); + free(items); + + if (f->items.len == 1 && f->items.words[0][0] == '\0') + f->items.len = 0; /* .for var in ${:U} */ + } + + { + size_t nitems, nvars; + + if ((nitems = f->items.len) > 0 && nitems % (nvars = f->vars.len)) { + Parse_Error(PARSE_FATAL, + "Wrong number of words (%zu) in .for substitution list" + " with %zu variables", nitems, nvars); + /* + * Return 'success' so that the body of the .for loop is + * accumulated. + * Remove all items so that the loop doesn't iterate. + */ + f->items.len = 0; + } + } + + accumFor = f; + forLevel = 1; + return 1; +} + +/* + * Add another line to a .for loop. + * Returns FALSE when the matching .endfor is reached. + */ +Boolean +For_Accum(const char *line) +{ + const char *ptr = line; + + if (*ptr == '.') { + ptr++; + cpp_skip_whitespace(&ptr); + + if (IsEndfor(ptr)) { + DEBUG1(FOR, "For: end for %d\n", forLevel); + if (--forLevel <= 0) + return FALSE; + } else if (IsFor(ptr)) { + forLevel++; + DEBUG1(FOR, "For: new loop %d\n", forLevel); + } + } + + Buf_AddStr(&accumFor->body, line); + Buf_AddByte(&accumFor->body, '\n'); + return TRUE; +} + + +static size_t +for_var_len(const char *var) +{ + char ch, var_start, var_end; + int depth; + size_t len; + + var_start = *var; + if (var_start == 0) + /* just escape the $ */ + return 0; + + if (var_start == '(') + var_end = ')'; + else if (var_start == '{') + var_end = '}'; + else + /* Single char variable */ + return 1; + + depth = 1; + for (len = 1; (ch = var[len++]) != 0;) { + if (ch == var_start) + depth++; + else if (ch == var_end && --depth == 0) + return len; + } + + /* Variable end not found, escape the $ */ + return 0; +} + +/* While expanding the body of a .for loop, write the item in the ${:U...} + * expression, escaping characters as needed. See ApplyModifier_Defined. */ +static void +Buf_AddEscaped(Buffer *cmds, const char *item, char ech) +{ + ForEscapes escapes = GetEscapes(item); + char ch; + + /* If there were no escapes, or the only escape is the other variable + * terminator, then just substitute the full string */ + if (!(escapes & (ech == ')' ? ~(unsigned)FOR_SUB_ESCAPE_BRACE + : ~(unsigned)FOR_SUB_ESCAPE_PAREN))) { + Buf_AddStr(cmds, item); + return; + } + + /* Escape ':', '$', '\\' and 'ech' - these will be removed later by + * :U processing, see ApplyModifier_Defined. */ + while ((ch = *item++) != '\0') { + if (ch == '$') { + size_t len = for_var_len(item); + if (len != 0) { + Buf_AddBytes(cmds, item - 1, len + 1); + item += len; + continue; + } + Buf_AddByte(cmds, '\\'); + } else if (ch == ':' || ch == '\\' || ch == ech) + Buf_AddByte(cmds, '\\'); + Buf_AddByte(cmds, ch); + } +} + +/* While expanding the body of a .for loop, replace expressions like + * ${i}, ${i:...}, $(i) or $(i:...) with their ${:U...} expansion. */ +static void +SubstVarLong(For *f, const char **pp, const char **inout_mark, char ech) +{ + size_t i; + const char *p = *pp; + + for (i = 0; i < f->vars.len; i++) { + ForVar *forVar = Vector_Get(&f->vars, i); + char *var = forVar->name; + size_t vlen = forVar->len; + + /* XXX: undefined behavior for p if vlen is longer than p? */ + if (memcmp(p, var, vlen) != 0) + continue; + /* XXX: why test for backslash here? */ + if (p[vlen] != ':' && p[vlen] != ech && p[vlen] != '\\') + continue; + + /* Found a variable match. Replace with :U */ + Buf_AddBytesBetween(&f->curBody, *inout_mark, p); + Buf_AddStr(&f->curBody, ":U"); + Buf_AddEscaped(&f->curBody, f->items.words[f->sub_next + i], ech); + + p += vlen; + *inout_mark = p; + break; + } + + *pp = p; +} + +/* While expanding the body of a .for loop, replace single-character + * variable expressions like $i with their ${:U...} expansion. */ +static void +SubstVarShort(For *f, char const ch, const char **pp, const char **inout_mark) +{ + const char *p = *pp; + size_t i; + + /* Probably a single character name, ignore $$ and stupid ones. */ + if (!f->short_var || strchr("}):$", ch) != NULL) { + p++; + *pp = p; + return; + } + + for (i = 0; i < f->vars.len; i++) { + ForVar *var = Vector_Get(&f->vars, i); + const char *varname = var->name; + if (varname[0] != ch || varname[1] != '\0') + continue; + + /* Found a variable match. Replace with ${:U} */ + Buf_AddBytesBetween(&f->curBody, *inout_mark, p); + Buf_AddStr(&f->curBody, "{:U"); + Buf_AddEscaped(&f->curBody, f->items.words[f->sub_next + i], '}'); + Buf_AddByte(&f->curBody, '}'); + + *inout_mark = ++p; + break; + } + + *pp = p; +} + +/* + * Scan the for loop body and replace references to the loop variables + * with variable references that expand to the required text. + * + * Using variable expansions ensures that the .for loop can't generate + * syntax, and that the later parsing will still see a variable. + * We assume that the null variable will never be defined. + * + * The detection of substitutions of the loop control variable is naive. + * Many of the modifiers use \ to escape $ (not $) so it is possible + * to contrive a makefile where an unwanted substitution happens. + */ +static char * +ForIterate(void *v_arg, size_t *out_len) +{ + For *f = v_arg; + const char *p; + const char *mark; /* where the last replacement left off */ + const char *body_end; + char *cmds_str; + + if (f->sub_next + f->vars.len > f->items.len) { + /* No more iterations */ + For_Free(f); + return NULL; + } + + Buf_Empty(&f->curBody); + + mark = Buf_GetAll(&f->body, NULL); + body_end = mark + Buf_Len(&f->body); + for (p = mark; (p = strchr(p, '$')) != NULL;) { + char ch, ech; + ch = *++p; + if ((ch == '(' && (ech = ')', 1)) || (ch == '{' && (ech = '}', 1))) { + p++; + /* Check variable name against the .for loop variables */ + SubstVarLong(f, &p, &mark, ech); + continue; + } + if (ch == '\0') + break; + + SubstVarShort(f, ch, &p, &mark); + } + Buf_AddBytesBetween(&f->curBody, mark, body_end); + + *out_len = Buf_Len(&f->curBody); + cmds_str = Buf_GetAll(&f->curBody, NULL); + DEBUG1(FOR, "For: loop body:\n%s", cmds_str); + + f->sub_next += f->vars.len; + + return cmds_str; +} + +/* Run the for loop, imitating the actions of an include file. */ +void +For_Run(int lineno) +{ + For *f = accumFor; + accumFor = NULL; + + if (f->items.len == 0) { + /* Nothing to expand - possibly due to an earlier syntax error. */ + For_Free(f); + return; + } + + Parse_SetInput(NULL, lineno, -1, ForIterate, f); +} Property changes on: vendor/NetBSD/bmake/20201101/for.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/hash.c =================================================================== --- vendor/NetBSD/bmake/20201101/hash.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/hash.c (revision 367461) @@ -0,0 +1,310 @@ +/* $NetBSD: hash.c,v 1.55 2020/10/25 19:28:44 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* Hash tables with string keys. */ + +#include "make.h" + +/* "@(#)hash.c 8.1 (Berkeley) 6/6/93" */ +MAKE_RCSID("$NetBSD: hash.c,v 1.55 2020/10/25 19:28:44 rillig Exp $"); + +/* + * The ratio of # entries to # buckets at which we rebuild the table to + * make it larger. + */ +#define rebuildLimit 3 + +/* This hash function matches Gosling's emacs and java.lang.String. */ +static unsigned int +hash(const char *key, size_t *out_keylen) +{ + unsigned int h = 0; + const char *p = key; + while (*p != '\0') + h = (h << 5) - h + (unsigned char)*p++; + if (out_keylen != NULL) + *out_keylen = (size_t)(p - key); + return h; +} + +unsigned int +Hash_Hash(const char *key) +{ + return hash(key, NULL); +} + +static HashEntry * +HashTable_Find(HashTable *t, unsigned int h, const char *key) +{ + HashEntry *e; + unsigned int chainlen = 0; + +#ifdef DEBUG_HASH_LOOKUP + DEBUG4(HASH, "%s: %p h=%08x key=%s\n", __func__, t, h, key); +#endif + + for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) { + chainlen++; + if (e->key_hash == h && strcmp(e->key, key) == 0) + break; + } + + if (chainlen > t->maxchain) + t->maxchain = chainlen; + + return e; +} + +/* Set up the hash table. */ +void +HashTable_Init(HashTable *t) +{ + unsigned int n = 16, i; + HashEntry **buckets = bmake_malloc(sizeof(*buckets) * n); + for (i = 0; i < n; i++) + buckets[i] = NULL; + + t->buckets = buckets; + t->bucketsSize = n; + t->numEntries = 0; + t->bucketsMask = n - 1; + t->maxchain = 0; +} + +/* Remove everything from the hash table and frees up the memory. */ +void +HashTable_Done(HashTable *t) +{ + HashEntry **buckets = t->buckets; + size_t i, n = t->bucketsSize; + + for (i = 0; i < n; i++) { + HashEntry *he = buckets[i]; + while (he != NULL) { + HashEntry *next = he->next; + free(he); + he = next; + } + } + free(t->buckets); + +#ifdef CLEANUP + t->buckets = NULL; +#endif +} + +/* Find the entry corresponding to the key, or return NULL. */ +HashEntry * +HashTable_FindEntry(HashTable *t, const char *key) +{ + unsigned int h = hash(key, NULL); + return HashTable_Find(t, h, key); +} + +/* Find the value corresponding to the key, or return NULL. */ +void * +HashTable_FindValue(HashTable *t, const char *key) +{ + HashEntry *he = HashTable_FindEntry(t, key); + return he != NULL ? he->value : NULL; +} + +/* Find the value corresponding to the key and the precomputed hash, + * or return NULL. */ +void * +HashTable_FindValueHash(HashTable *t, const char *key, unsigned int h) +{ + HashEntry *he = HashTable_Find(t, h, key); + return he != NULL ? he->value : NULL; +} + +/* Make the hash table larger. Any bucket numbers from the old table become + * invalid; the hash codes stay valid though. */ +static void +HashTable_Enlarge(HashTable *t) +{ + unsigned int oldSize = t->bucketsSize; + HashEntry **oldBuckets = t->buckets; + unsigned int newSize = 2 * oldSize; + unsigned int newMask = newSize - 1; + HashEntry **newBuckets = bmake_malloc(sizeof(*newBuckets) * newSize); + size_t i; + + for (i = 0; i < newSize; i++) + newBuckets[i] = NULL; + + for (i = 0; i < oldSize; i++) { + HashEntry *he = oldBuckets[i]; + while (he != NULL) { + HashEntry *next = he->next; + he->next = newBuckets[he->key_hash & newMask]; + newBuckets[he->key_hash & newMask] = he; + he = next; + } + } + + free(oldBuckets); + + t->bucketsSize = newSize; + 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); + t->maxchain = 0; +} + +/* Find or create an entry corresponding to the key. + * Return in out_isNew whether a new entry has been created. */ +HashEntry * +HashTable_CreateEntry(HashTable *t, const char *key, Boolean *out_isNew) +{ + size_t keylen; + unsigned int h = hash(key, &keylen); + HashEntry *he = HashTable_Find(t, h, key); + + if (he != NULL) { + if (out_isNew != NULL) + *out_isNew = FALSE; + return he; + } + + if (t->numEntries >= rebuildLimit * t->bucketsSize) + HashTable_Enlarge(t); + + he = bmake_malloc(sizeof(*he) + keylen); + he->value = NULL; + he->key_hash = h; + memcpy(he->key, key, keylen + 1); + + he->next = t->buckets[h & t->bucketsMask]; + t->buckets[h & t->bucketsMask] = he; + t->numEntries++; + + if (out_isNew != NULL) + *out_isNew = TRUE; + return he; +} + +/* Delete the entry from the table and free the associated memory. */ +void +HashTable_DeleteEntry(HashTable *t, HashEntry *he) +{ + HashEntry **ref = &t->buckets[he->key_hash & t->bucketsMask]; + HashEntry *p; + + for (; (p = *ref) != NULL; ref = &p->next) { + if (p == he) { + *ref = p->next; + free(p); + t->numEntries--; + return; + } + } + abort(); +} + +/* Set things up for iterating over all entries in the hash table. */ +void +HashIter_Init(HashIter *hi, HashTable *t) +{ + hi->table = t; + hi->nextBucket = 0; + hi->entry = NULL; +} + +/* Return the next entry in the hash table, or NULL if the end of the table + * is reached. */ +HashEntry * +HashIter_Next(HashIter *hi) +{ + HashTable *t = hi->table; + HashEntry *he = hi->entry; + HashEntry **buckets = t->buckets; + unsigned int bucketsSize = t->bucketsSize; + + if (he != NULL) + he = he->next; /* skip the most recently returned entry */ + + while (he == NULL) { /* find the next nonempty chain */ + if (hi->nextBucket >= bucketsSize) + return NULL; + he = buckets[hi->nextBucket++]; + } + hi->entry = he; + return he; +} + +void +HashTable_DebugStats(HashTable *t, const char *name) +{ + DEBUG4(HASH, "HashTable %s: size=%u numEntries=%u maxchain=%u\n", + name, t->bucketsSize, t->numEntries, t->maxchain); +} Property changes on: vendor/NetBSD/bmake/20201101/hash.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/hash.h =================================================================== --- vendor/NetBSD/bmake/20201101/hash.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/hash.h (revision 367461) @@ -0,0 +1,131 @@ +/* $NetBSD: hash.h,v 1.31 2020/10/25 19:19:07 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)hash.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)hash.h 8.1 (Berkeley) 6/6/93 + */ + +/* Hash tables with strings as keys and arbitrary pointers as values. */ + +#ifndef MAKE_HASH_H +#define MAKE_HASH_H + +/* A single key-value entry in the hash table. */ +typedef struct HashEntry { + struct HashEntry *next; /* Used to link together all the entries + * associated with the same bucket. */ + void *value; + unsigned int key_hash; /* hash value of the key */ + char key[1]; /* key string, variable length */ +} HashEntry; + +/* The hash table containing the entries. */ +typedef struct HashTable { + HashEntry **buckets; /* Pointers to HashEntry, one + * for each bucket in the table. */ + unsigned int bucketsSize; + unsigned int numEntries; /* Number of entries in the table. */ + unsigned int bucketsMask; /* Used to select the bucket for a hash. */ + unsigned int maxchain; /* max length of chain detected */ +} HashTable; + +/* State of an iteration over all entries in a table. */ +typedef struct HashIter { + HashTable *table; /* Table being searched. */ + unsigned int nextBucket; /* Next bucket to check (after current). */ + HashEntry *entry; /* Next entry to check in current bucket. */ +} HashIter; + +static inline MAKE_ATTR_UNUSED void * +HashEntry_Get(HashEntry *h) +{ + return h->value; +} + +static inline MAKE_ATTR_UNUSED void +HashEntry_Set(HashEntry *h, void *datum) +{ + h->value = datum; +} + +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 *); +void HashTable_DeleteEntry(HashTable *, HashEntry *); +void HashTable_DebugStats(HashTable *, const char *); + +void HashIter_Init(HashIter *, HashTable *); +HashEntry *HashIter_Next(HashIter *); + +#endif /* MAKE_HASH_H */ Property changes on: vendor/NetBSD/bmake/20201101/hash.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/job.c =================================================================== --- vendor/NetBSD/bmake/20201101/job.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/job.c (revision 367461) @@ -0,0 +1,2882 @@ +/* $NetBSD: job.c,v 1.302 2020/11/01 18:45:49 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * job.c -- + * handle the creation etc. of our child processes. + * + * Interface: + * Job_Init Called to initialize this module. In addition, + * any commands attached to the .BEGIN target + * are executed before this function returns. + * Hence, the makefiles must have been parsed + * before this function is called. + * + * Job_End Clean up any memory used. + * + * Job_Make Start the creation of the given target. + * + * Job_CatchChildren + * Check for and handle the termination of any + * children. This must be called reasonably + * frequently to keep the whole make going at + * a decent clip, since job table entries aren't + * removed until their process is caught this way. + * + * Job_CatchOutput + * Print any output our children have produced. + * Should also be called fairly frequently to + * keep the user informed of what's going on. + * If no output is waiting, it will block for + * a time given by the SEL_* constants, below, + * or until output is ready. + * + * Job_ParseShell Given the line following a .SHELL target, parse + * the line as a shell specification. Returns + * FALSE if the spec was incorrect. + * + * Job_Finish Perform any final processing which needs doing. + * This includes the execution of any commands + * which have been/were attached to the .END + * target. It should only be called when the + * job table is empty. + * + * Job_AbortAll Abort all currently running jobs. It doesn't + * handle output or do anything for the jobs, + * just kills them. It should only be called in + * an emergency. + * + * Job_CheckCommands + * Verify that the commands for a target are + * ok. Provide them if necessary and possible. + * + * Job_Touch Update a target without really updating it. + * + * Job_Wait Wait for all currently-running jobs to finish. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#include "wait.h" + +#include +#if !defined(USE_SELECT) && defined(HAVE_POLL_H) +#include +#else +#ifndef USE_SELECT /* no poll.h */ +# define USE_SELECT +#endif +#if defined(HAVE_SYS_SELECT_H) +# include +#endif +#endif +#include +#include +#if defined(HAVE_SYS_SOCKET_H) +# include +#endif + +#include "make.h" +#include "dir.h" +#include "job.h" +#include "pathnames.h" +#include "trace.h" + +/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: job.c,v 1.302 2020/11/01 18:45:49 rillig Exp $"); + +/* A shell defines how the commands are run. All commands for a target are + * written into a single file, which is then given to the shell to execute + * the commands from it. The commands are written to the file using a few + * templates for echo control and error control. + * + * The name of the shell is the basename for the predefined shells, such as + * "sh", "csh", "bash". For custom shells, it is the full pathname, and its + * basename is used to select the type of shell; the longest match wins. + * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. + * + * The echoing of command lines is controlled using hasEchoCtl, echoOff, + * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it + * still outputs something, but this something is not interesting, therefore + * it is filtered out using noPrint and noPrintLen. + * + * The error checking for individual commands is controlled using hasErrCtl, + * errOnOrEcho, errOffOrExecIgnore and errExit. + * + * If a shell doesn't have error control, errOnOrEcho becomes a printf template + * for echoing the command, should echoing be on; errOffOrExecIgnore becomes + * another printf template for executing the command while ignoring the return + * status. Finally errExit is a printf template for running the command and + * causing the shell to exit on error. If any of these strings are empty when + * hasErrCtl is FALSE, the command will be executed anyway as is, and if it + * causes an error, so be it. Any templates setup to echo the command will + * escape any '$ ` \ "' characters in the command string to avoid common + * problems with echo "%s\n" as a template. + * + * The command-line flags "echo" and "exit" also control the behavior. The + * "echo" flag causes the shell to start echoing commands right away. The + * "exit" flag causes the shell to exit when an error is detected in one of + * the commands. + */ +typedef struct Shell { + + /* The name of the shell. For Bourne and C shells, this is used only to + * find the shell description when used as the single source of a .SHELL + * target. For user-defined shells, this is the full path of the shell. */ + const char *name; + + Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */ + const char *echoOff; /* command to turn off echo */ + const char *echoOn; /* command to turn it back on again */ + const char *noPrint; /* text to skip when printing output from + * shell. This is usually the same as echoOff */ + size_t noPrintLen; /* length of noPrint command */ + + Boolean hasErrCtl; /* set if can control error checking for + * individual commands */ + /* XXX: split into errOn and echoCmd */ + const char *errOnOrEcho; /* template to turn on error checking */ + /* XXX: split into errOff and execIgnore */ + const char *errOffOrExecIgnore; /* template to turn off error checking */ + const char *errExit; /* template to use for testing exit code */ + + /* string literal that results in a newline character when it appears + * outside of any 'quote' or "quote" characters */ + const char *newline; + char commentChar; /* character used by shell for comment lines */ + + /* + * command-line flags + */ + const char *echo; /* echo commands */ + const char *exit; /* exit on error */ +} Shell; + +/* + * error handling variables + */ +static int errors = 0; /* number of errors reported */ +typedef enum AbortReason { /* why is the make aborting? */ + ABORT_NONE, + ABORT_ERROR, /* Because of an error */ + ABORT_INTERRUPT, /* Because it was interrupted */ + ABORT_WAIT /* Waiting for jobs to finish */ +} AbortReason; +static AbortReason aborting = ABORT_NONE; +#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */ + +/* + * this tracks the number of tokens currently "out" to build jobs. + */ +int jobTokensRunning = 0; + +/* The number of commands actually printed to the shell commands file for + * the current job. Should this number be 0, no shell will be executed. */ +static int numCommands; + +typedef enum JobStartResult { + JOB_RUNNING, /* Job is running */ + JOB_ERROR, /* Error in starting the job */ + JOB_FINISHED /* The job is already finished */ +} JobStartResult; + +/* + * Descriptions for various shells. + * + * The build environment may set DEFSHELL_INDEX to one of + * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to + * select one of the predefined shells as the default shell. + * + * Alternatively, the build environment may set DEFSHELL_CUSTOM to the + * name or the full path of a sh-compatible shell, which will be used as + * the default shell. + * + * ".SHELL" lines in Makefiles can choose the default shell from the + * set defined here, or add additional shells. + */ + +#ifdef DEFSHELL_CUSTOM +#define DEFSHELL_INDEX_CUSTOM 0 +#define DEFSHELL_INDEX_SH 1 +#define DEFSHELL_INDEX_KSH 2 +#define DEFSHELL_INDEX_CSH 3 +#else /* !DEFSHELL_CUSTOM */ +#define DEFSHELL_INDEX_SH 0 +#define DEFSHELL_INDEX_KSH 1 +#define DEFSHELL_INDEX_CSH 2 +#endif /* !DEFSHELL_CUSTOM */ + +#ifndef DEFSHELL_INDEX +#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */ +#endif /* !DEFSHELL_INDEX */ + +static Shell shells[] = { +#ifdef DEFSHELL_CUSTOM + /* + * An sh-compatible shell with a non-standard name. + * + * Keep this in sync with the "sh" description below, but avoid + * non-portable features that might not be supplied by all + * sh-compatible shells. + */ +{ + DEFSHELL_CUSTOM, /* .name */ + FALSE, /* .hasEchoCtl */ + "", /* .echoOff */ + "", /* .echoOn */ + "", /* .noPrint */ + 0, /* .noPrintLen */ + FALSE, /* .hasErrCtl */ + "echo \"%s\"\n", /* .errOnOrEcho */ + "%s\n", /* .errOffOrExecIgnore */ + "{ %s \n} || exit $?\n", /* .errExit */ + "'\n'", /* .newline */ + '#', /* .commentChar */ + "", /* .echo */ + "", /* .exit */ +}, +#endif /* DEFSHELL_CUSTOM */ + /* + * SH description. Echo control is also possible and, under + * sun UNIX anyway, one can even control error checking. + */ +{ + "sh", /* .name */ + FALSE, /* .hasEchoCtl */ + "", /* .echoOff */ + "", /* .echoOn */ + "", /* .noPrint */ + 0, /* .noPrintLen */ + FALSE, /* .hasErrCtl */ + "echo \"%s\"\n", /* .errOnOrEcho */ + "%s\n", /* .errOffOrExecIgnore */ + "{ %s \n} || exit $?\n", /* .errExit */ + "'\n'", /* .newline */ + '#', /* .commentChar*/ +#if defined(MAKE_NATIVE) && defined(__NetBSD__) + "q", /* .echo */ +#else + "", /* .echo */ +#endif + "", /* .exit */ +}, + /* + * KSH description. + */ +{ + "ksh", /* .name */ + TRUE, /* .hasEchoCtl */ + "set +v", /* .echoOff */ + "set -v", /* .echoOn */ + "set +v", /* .noPrint */ + 6, /* .noPrintLen */ + FALSE, /* .hasErrCtl */ + "echo \"%s\"\n", /* .errOnOrEcho */ + "%s\n", /* .errOffOrExecIgnore */ + "{ %s \n} || exit $?\n", /* .errExit */ + "'\n'", /* .newline */ + '#', /* .commentChar */ + "v", /* .echo */ + "", /* .exit */ +}, + /* + * CSH description. The csh can do echo control by playing + * with the setting of the 'echo' shell variable. Sadly, + * however, it is unable to do error control nicely. + */ +{ + "csh", /* .name */ + TRUE, /* .hasEchoCtl */ + "unset verbose", /* .echoOff */ + "set verbose", /* .echoOn */ + "unset verbose", /* .noPrint */ + 13, /* .noPrintLen */ + FALSE, /* .hasErrCtl */ + "echo \"%s\"\n", /* .errOnOrEcho */ + /* XXX: Mismatch between errOn and execIgnore */ + "csh -c \"%s || exit 0\"\n", /* .errOffOrExecIgnore */ + "", /* .errExit */ + "'\\\n'", /* .newline */ + '#', /* .commentChar */ + "v", /* .echo */ + "e", /* .exit */ +} +}; + +/* This is the shell to which we pass all commands in the Makefile. + * It is set by the Job_ParseShell function. */ +static Shell *commandShell = &shells[DEFSHELL_INDEX]; +const char *shellPath = NULL; /* full pathname of executable image */ +const char *shellName = NULL; /* last component of shellPath */ +char *shellErrFlag = NULL; +static char *shellArgv = NULL; /* Custom shell args */ + + +static Job *job_table; /* The structures that describe them */ +static Job *job_table_end; /* job_table + maxJobs */ +static unsigned int wantToken; /* we want a token */ +static int lurking_children = 0; +static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */ + +/* + * Set of descriptors of pipes connected to + * the output channels of children + */ +static struct pollfd *fds = NULL; +static Job **jobfds = NULL; +static nfds_t nfds = 0; +static void watchfd(Job *); +static void clearfd(Job *); +static int readyfd(Job *); + +static GNode *lastNode; /* The node for which output was most recently + * produced. */ +static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */ +static Job tokenWaitJob; /* token wait pseudo-job */ + +static Job childExitJob; /* child exit pseudo-job */ +#define CHILD_EXIT "." +#define DO_JOB_RESUME "R" + +enum { npseudojobs = 2 }; /* number of pseudo-jobs */ + +#define TARG_FMT "%s %s ---\n" /* Default format */ +#define MESSAGE(fp, gn) \ + if (opts.maxJobs != 1 && targPrefix && *targPrefix) \ + (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) + +static sigset_t caught_signals; /* Set of signals we handle */ + +static void JobDoOutput(Job *, Boolean); +static void JobInterrupt(int, int) MAKE_ATTR_DEAD; +static void JobRestartJobs(void); +static void JobSigReset(void); + +static unsigned +nfds_per_job(void) +{ +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) + return 2; +#endif + return 1; +} + +static void +job_table_dump(const char *where) +{ + Job *job; + + debug_printf("job table @ %s\n", where); + for (job = job_table; job < job_table_end; job++) { + debug_printf("job %d, status %d, flags %d, pid %d\n", + (int)(job - job_table), job->job_state, job->flags, job->pid); + } +} + +/* + * Delete the target of a failed, interrupted, or otherwise + * unsuccessful job unless inhibited by .PRECIOUS. + */ +static void +JobDeleteTarget(GNode *gn) +{ + const char *file; + + if (gn->type & OP_JOIN) + return; + if (gn->type & OP_PHONY) + return; + if (Targ_Precious(gn)) + return; + if (opts.noExecute) + return; + + file = GNode_Path(gn); + if (eunlink(file) != -1) + Error("*** %s removed", file); +} + +/* + * JobSigLock/JobSigUnlock + * + * Signal lock routines to get exclusive access. Currently used to + * protect `jobs' and `stoppedJobs' list manipulations. + */ +static void JobSigLock(sigset_t *omaskp) +{ + if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) { + Punt("JobSigLock: sigprocmask: %s", strerror(errno)); + sigemptyset(omaskp); + } +} + +static void JobSigUnlock(sigset_t *omaskp) +{ + (void)sigprocmask(SIG_SETMASK, omaskp, NULL); +} + +static void +JobCreatePipe(Job *job, int minfd) +{ + int i, fd, flags; + int pipe_fds[2]; + + if (pipe(pipe_fds) == -1) + Punt("Cannot create pipe: %s", strerror(errno)); + + for (i = 0; i < 2; i++) { + /* Avoid using low numbered fds */ + fd = fcntl(pipe_fds[i], F_DUPFD, minfd); + if (fd != -1) { + close(pipe_fds[i]); + pipe_fds[i] = fd; + } + } + + job->inPipe = pipe_fds[0]; + job->outPipe = pipe_fds[1]; + + /* Set close-on-exec flag for both */ + if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1) + Punt("Cannot set close-on-exec: %s", strerror(errno)); + if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1) + Punt("Cannot set close-on-exec: %s", strerror(errno)); + + /* + * We mark the input side of the pipe non-blocking; we poll(2) the + * pipe when we're waiting for a job token, but we might lose the + * race for the token when a new one becomes available, so the read + * from the pipe should not block. + */ + flags = fcntl(job->inPipe, F_GETFL, 0); + if (flags == -1) + Punt("Cannot get flags: %s", strerror(errno)); + flags |= O_NONBLOCK; + if (fcntl(job->inPipe, F_SETFL, flags) == -1) + Punt("Cannot set flags: %s", strerror(errno)); +} + +/* Pass the signal to each running job. */ +static void +JobCondPassSig(int signo) +{ + Job *job; + + DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo); + + for (job = job_table; job < job_table_end; job++) { + if (job->job_state != JOB_ST_RUNNING) + continue; + DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n", + signo, job->pid); + KILLPG(job->pid, signo); + } +} + +/* SIGCHLD handler. + * + * Sends a token on the child exit pipe to wake us up from select()/poll(). */ +static void +JobChildSig(int signo MAKE_ATTR_UNUSED) +{ + while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN) + continue; +} + + +/* Resume all stopped jobs. */ +static void +JobContinueSig(int signo MAKE_ATTR_UNUSED) +{ + /* + * Defer sending SIGCONT to our stopped children until we return + * from the signal handler. + */ + while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && + errno == EAGAIN) + continue; +} + +/* Pass a signal on to all jobs, then resend to ourselves. + * We die by the same signal. */ +MAKE_ATTR_DEAD static void +JobPassSig_int(int signo) +{ + /* Run .INTERRUPT target then exit */ + JobInterrupt(TRUE, signo); +} + +/* Pass a signal on to all jobs, then resend to ourselves. + * We die by the same signal. */ +MAKE_ATTR_DEAD static void +JobPassSig_term(int signo) +{ + /* Dont run .INTERRUPT target then exit */ + JobInterrupt(FALSE, signo); +} + +static void +JobPassSig_suspend(int signo) +{ + sigset_t nmask, omask; + struct sigaction act; + + /* Suppress job started/continued messages */ + make_suspended = 1; + + /* Pass the signal onto every job */ + JobCondPassSig(signo); + + /* + * Send ourselves the signal now we've given the message to everyone else. + * Note we block everything else possible while we're getting the signal. + * This ensures that all our jobs get continued when we wake up before + * we take any other signal. + */ + sigfillset(&nmask); + sigdelset(&nmask, signo); + (void)sigprocmask(SIG_SETMASK, &nmask, &omask); + + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + (void)sigaction(signo, &act, NULL); + + if (DEBUG(JOB)) + debug_printf("JobPassSig passing signal %d to self.\n", signo); + + (void)kill(getpid(), signo); + + /* + * We've been continued. + * + * A whole host of signals continue to happen! + * SIGCHLD for any processes that actually suspended themselves. + * SIGCHLD for any processes that exited while we were alseep. + * The SIGCONT that actually caused us to wakeup. + * + * Since we defer passing the SIGCONT on to our children until + * the main processing loop, we can be sure that all the SIGCHLD + * events will have happened by then - and that the waitpid() will + * collect the child 'suspended' events. + * For correct sequencing we just need to ensure we process the + * waitpid() before passing on the SIGCONT. + * + * In any case nothing else is needed here. + */ + + /* Restore handler and signal mask */ + act.sa_handler = JobPassSig_suspend; + (void)sigaction(signo, &act, NULL); + (void)sigprocmask(SIG_SETMASK, &omask, NULL); +} + +static Job * +JobFindPid(int pid, JobState status, Boolean isJobs) +{ + Job *job; + + for (job = job_table; job < job_table_end; job++) { + if ((job->job_state == status) && job->pid == pid) + return job; + } + if (DEBUG(JOB) && isJobs) + job_table_dump("no pid"); + return NULL; +} + +/* Parse leading '@', '-' and '+', which control the exact execution mode. */ +static void +ParseRunOptions( + char **pp, + Boolean *out_shutUp, Boolean *out_errOff, Boolean *out_runAlways) +{ + char *p = *pp; + *out_shutUp = FALSE; + *out_errOff = FALSE; + *out_runAlways = FALSE; + + for (;;) { + if (*p == '@') + *out_shutUp = !DEBUG(LOUD); + else if (*p == '-') + *out_errOff = TRUE; + else if (*p == '+') + *out_runAlways = TRUE; + else + break; + p++; + } + + pp_skip_whitespace(&p); + + *pp = p; +} + +/* Escape a string for a double-quoted string literal in sh, csh and ksh. */ +static char * +EscapeShellDblQuot(const char *cmd) +{ + size_t i, j; + + /* Worst that could happen is every char needs escaping. */ + char *esc = bmake_malloc(strlen(cmd) * 2 + 1); + for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) { + if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || cmd[i] == '"') + esc[j++] = '\\'; + esc[j] = cmd[i]; + } + esc[j] = '\0'; + + return esc; +} + +/*- + *----------------------------------------------------------------------- + * JobPrintCommand -- + * Put out another command for the given job. If the command starts + * with an @ or a - we process it specially. In the former case, + * so long as the -s and -n flags weren't given to make, we stick + * a shell-specific echoOff command in the script. In the latter, + * we ignore errors for the entire job, unless the shell has error + * control. + * If the command is just "..." we take all future commands for this + * job to be commands to be executed once the entire graph has been + * made and return non-zero to signal that the end of the commands + * was reached. These commands are later attached to the postCommands + * node and executed by Job_End when all things are done. + * + * Side Effects: + * If the command begins with a '-' and the shell has no error control, + * the JOB_IGNERR flag is set in the job descriptor. + * numCommands is incremented if the command is actually printed. + *----------------------------------------------------------------------- + */ +static void +JobPrintCommand(Job *job, char *cmd) +{ + const char *const cmdp = cmd; + Boolean noSpecials; /* true if we shouldn't worry about + * inserting special commands into + * the input stream. */ + Boolean shutUp; /* true if we put a no echo command + * into the command file */ + Boolean errOff; /* true if we turned error checking + * off before printing the command + * and need to turn it back on */ + Boolean runAlways; + const char *cmdTemplate; /* Template to use when printing the + * command */ + char *cmdStart; /* Start of expanded command */ + char *escCmd = NULL; /* Command with quotes/backticks escaped */ + + noSpecials = !GNode_ShouldExecute(job->node); + +#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ + debug_printf(fmt, arg); \ + } \ + (void)fprintf(job->cmdFILE, fmt, arg); \ + (void)fflush(job->cmdFILE); + + numCommands++; + + Var_Subst(cmd, job->node, VARE_WANTRES, &cmd); + /* TODO: handle errors */ + cmdStart = cmd; + + cmdTemplate = "%s\n"; + + ParseRunOptions(&cmd, &shutUp, &errOff, &runAlways); + + if (runAlways && noSpecials) { + /* + * We're not actually executing anything... + * but this one needs to be - use compat mode just for it. + */ + Compat_RunCommand(cmdp, job->node); + free(cmdStart); + return; + } + + /* + * If the shell doesn't have error control the alternate echo'ing will + * be done (to avoid showing additional error checking code) + * and this will need the characters '$ ` \ "' escaped + */ + + if (!commandShell->hasErrCtl) + escCmd = EscapeShellDblQuot(cmd); + + if (shutUp) { + if (!(job->flags & JOB_SILENT) && !noSpecials && + commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOff); + } else { + if (commandShell->hasErrCtl) + shutUp = FALSE; + } + } + + if (errOff) { + if (!noSpecials) { + if (commandShell->hasErrCtl) { + /* + * we don't want the error-control commands showing + * up either, so we turn off echoing while executing + * them. We could put another field in the shell + * structure to tell JobDoOutput to look for this + * string too, but why make it any more complex than + * it already is? + */ + if (!(job->flags & JOB_SILENT) && !shutUp && + commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOff); + DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); + DBPRINTF("%s\n", commandShell->echoOn); + } else { + DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); + } + } else if (commandShell->errOffOrExecIgnore && + commandShell->errOffOrExecIgnore[0] != '\0') + { + /* + * The shell has no error control, so we need to be + * weird to get it to ignore any errors from the command. + * If echoing is turned on, we turn it off and use the + * errOnOrEcho template to echo the command. Leave echoing + * off so the user doesn't see the weirdness we go through + * to ignore errors. Set cmdTemplate to use the weirdness + * instead of the simple "%s\n" template. + */ + job->flags |= JOB_IGNERR; + if (!(job->flags & JOB_SILENT) && !shutUp) { + if (commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOff); + } + DBPRINTF(commandShell->errOnOrEcho, escCmd); + shutUp = TRUE; + } else { + if (!shutUp) { + DBPRINTF(commandShell->errOnOrEcho, escCmd); + } + } + cmdTemplate = commandShell->errOffOrExecIgnore; + /* + * The error ignoration (hee hee) is already taken care + * of by the errOffOrExecIgnore template, so pretend error + * checking is still on. + */ + errOff = FALSE; + } else { + errOff = FALSE; + } + } else { + errOff = FALSE; + } + } else { + + /* + * If errors are being checked and the shell doesn't have error control + * but does supply an errExit template, then setup commands to run + * through it. + */ + + if (!commandShell->hasErrCtl && commandShell->errExit && + commandShell->errExit[0] != '\0') { + if (!(job->flags & JOB_SILENT) && !shutUp) { + if (commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOff); + } + DBPRINTF(commandShell->errOnOrEcho, escCmd); + shutUp = TRUE; + } + /* If it's a comment line or blank, treat as an ignored error */ + if ((escCmd[0] == commandShell->commentChar) || + (escCmd[0] == 0)) + cmdTemplate = commandShell->errOffOrExecIgnore; + else + cmdTemplate = commandShell->errExit; + errOff = FALSE; + } + } + + if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 && + (job->flags & JOB_TRACED) == 0) { + DBPRINTF("set -%s\n", "x"); + job->flags |= JOB_TRACED; + } + + DBPRINTF(cmdTemplate, cmd); + free(cmdStart); + free(escCmd); + if (errOff) { + /* + * If echoing is already off, there's no point in issuing the + * echoOff command. Otherwise we issue it and pretend it was on + * for the whole command... + */ + if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ + DBPRINTF("%s\n", commandShell->echoOff); + shutUp = TRUE; + } + DBPRINTF("%s\n", commandShell->errOnOrEcho); + } + if (shutUp && commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOn); + } +} + +/* Print all commands to the shell file that is later executed. + * + * The special command "..." stops printing and saves the remaining commands + * to be executed later. */ +static void +JobPrintCommands(Job *job) +{ + StringListNode *ln; + + for (ln = job->node->commands->first; ln != NULL; ln = ln->next) { + const char *cmd = ln->datum; + + if (strcmp(cmd, "...") == 0) { + job->node->type |= OP_SAVE_CMDS; + if ((job->flags & JOB_IGNDOTS) == 0) { + job->tailCmds = ln->next; + break; + } + } else + JobPrintCommand(job, ln->datum); + } +} + +/* Save the delayed commands, to be executed when everything else is done. */ +static void +JobSaveCommands(Job *job) +{ + StringListNode *node; + + for (node = job->tailCmds; node != NULL; node = node->next) { + const char *cmd = node->datum; + char *expanded_cmd; + /* XXX: This Var_Subst is only intended to expand the dynamic + * variables such as .TARGET, .IMPSRC. It is not intended to + * expand the other variables as well; see deptgt-end.mk. */ + (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd); + /* TODO: handle errors */ + Lst_Append(Targ_GetEndNode()->commands, expanded_cmd); + } +} + + +/* Called to close both input and output pipes when a job is finished. */ +static void +JobClose(Job *job) +{ + clearfd(job); + (void)close(job->outPipe); + job->outPipe = -1; + + JobDoOutput(job, TRUE); + (void)close(job->inPipe); + job->inPipe = -1; +} + +/*- + *----------------------------------------------------------------------- + * JobFinish -- + * Do final processing for the given job including updating + * parents and starting new jobs as available/necessary. Note + * that we pay no attention to the JOB_IGNERR flag here. + * This is because when we're called because of a noexecute flag + * or something, jstat.w_status is 0 and when called from + * Job_CatchChildren, the status is zeroed if it s/b ignored. + * + * Input: + * job job to finish + * status sub-why job went away + * + * Side Effects: + * Final commands for the job are placed on postCommands. + * + * If we got an error and are aborting (aborting == ABORT_ERROR) and + * the job list is now empty, we are done for the day. + * If we recognized an error (errors !=0), we set the aborting flag + * to ABORT_ERROR so no more jobs will be started. + *----------------------------------------------------------------------- + */ +static void +JobFinish (Job *job, WAIT_T status) +{ + Boolean done, return_job_token; + + DEBUG3(JOB, "JobFinish: %d [%s], status %d\n", + job->pid, job->node->name, status); + + if ((WIFEXITED(status) && + (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) || + WIFSIGNALED(status)) + { + /* + * If it exited non-zero and either we're doing things our + * way or we're not ignoring errors, the job is finished. + * Similarly, if the shell died because of a signal + * the job is also finished. In these + * cases, finish out the job's output before printing the exit + * status... + */ + JobClose(job); + if (job->cmdFILE != NULL && job->cmdFILE != stdout) { + (void)fclose(job->cmdFILE); + job->cmdFILE = NULL; + } + done = TRUE; + } else if (WIFEXITED(status)) { + /* + * Deal with ignored errors in -B mode. We need to print a message + * telling of the ignored error as well as setting status.w_status + * to 0 so the next command gets run. To do this, we set done to be + * TRUE if in -B mode and the job exited non-zero. + */ + done = WEXITSTATUS(status) != 0; + /* + * Old comment said: "Note we don't + * want to close down any of the streams until we know we're at the + * end." + * But we do. Otherwise when are we going to print the rest of the + * stuff? + */ + JobClose(job); + } else { + /* + * No need to close things down or anything. + */ + done = FALSE; + } + + if (done) { + if (WIFEXITED(status)) { + DEBUG2(JOB, "Process %d [%s] exited.\n", + job->pid, job->node->name); + if (WEXITSTATUS(status) != 0) { + if (job->node != lastNode) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } +#ifdef USE_META + if (useMeta) { + meta_job_error(job, job->node, job->flags, WEXITSTATUS(status)); + } +#endif + if (!dieQuietly(job->node, -1)) + (void)printf("*** [%s] Error code %d%s\n", + job->node->name, + WEXITSTATUS(status), + (job->flags & JOB_IGNERR) ? " (ignored)" : ""); + if (job->flags & JOB_IGNERR) { + WAIT_STATUS(status) = 0; + } else { + if (deleteOnError) { + JobDeleteTarget(job->node); + } + PrintOnError(job->node, NULL); + } + } else if (DEBUG(JOB)) { + if (job->node != lastNode) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } + (void)printf("*** [%s] Completed successfully\n", + job->node->name); + } + } else { + if (job->node != lastNode) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } + (void)printf("*** [%s] Signal %d\n", + job->node->name, WTERMSIG(status)); + if (deleteOnError) { + JobDeleteTarget(job->node); + } + } + (void)fflush(stdout); + } + +#ifdef USE_META + if (useMeta) { + int x; + + if ((x = meta_job_finish(job)) != 0 && status == 0) { + status = x; + } + } +#endif + + return_job_token = FALSE; + + Trace_Log(JOBEND, job); + if (!(job->flags & JOB_SPECIAL)) { + if ((WAIT_STATUS(status) != 0) || + (aborting == ABORT_ERROR) || + (aborting == ABORT_INTERRUPT)) + return_job_token = TRUE; + } + + if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && + (WAIT_STATUS(status) == 0)) { + /* + * As long as we aren't aborting and the job didn't return a non-zero + * status that we shouldn't ignore, we call Make_Update to update + * the parents. + */ + JobSaveCommands(job); + job->node->made = MADE; + if (!(job->flags & JOB_SPECIAL)) + return_job_token = TRUE; + Make_Update(job->node); + job->job_state = JOB_ST_FREE; + } else if (WAIT_STATUS(status)) { + errors++; + job->job_state = JOB_ST_FREE; + } + + /* + * Set aborting if any error. + */ + if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) { + /* + * If we found any errors in this batch of children and the -k flag + * wasn't given, we set the aborting flag so no more jobs get + * started. + */ + aborting = ABORT_ERROR; + } + + if (return_job_token) + Job_TokenReturn(); + + if (aborting == ABORT_ERROR && jobTokensRunning == 0) { + /* + * If we are aborting and the job table is now empty, we finish. + */ + Finish(errors); + } +} + +/* Touch the given target. Called by JobStart when the -t flag was given. + * + * The modification date of the file is changed. + * If the file did not exist, it is created. */ +void +Job_Touch(GNode *gn, Boolean silent) +{ + int streamID; /* ID of stream opened to do the touch */ + struct utimbuf times; /* Times for utime() call */ + + if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL| + OP_SPECIAL|OP_PHONY)) { + /* + * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets + * and, as such, shouldn't really be created. + */ + return; + } + + if (!silent || !GNode_ShouldExecute(gn)) { + (void)fprintf(stdout, "touch %s\n", gn->name); + (void)fflush(stdout); + } + + if (!GNode_ShouldExecute(gn)) { + return; + } + + if (gn->type & OP_ARCHV) { + Arch_Touch(gn); + } else if (gn->type & OP_LIB) { + Arch_TouchLib(gn); + } else { + const char *file = GNode_Path(gn); + + times.actime = times.modtime = now; + if (utime(file, ×) < 0){ + streamID = open(file, O_RDWR | O_CREAT, 0666); + + if (streamID >= 0) { + char c; + + /* + * Read and write a byte to the file to change the + * modification time, then close the file. + */ + if (read(streamID, &c, 1) == 1) { + (void)lseek(streamID, (off_t)0, SEEK_SET); + while (write(streamID, &c, 1) == -1 && errno == EAGAIN) + continue; + } + + (void)close(streamID); + } else { + (void)fprintf(stdout, "*** couldn't touch %s: %s", + file, strerror(errno)); + (void)fflush(stdout); + } + } + } +} + +/* Make sure the given node has all the commands it needs. + * + * The node will have commands from the .DEFAULT rule added to it if it + * needs them. + * + * Input: + * gn The target whose commands need verifying + * abortProc Function to abort with message + * + * Results: + * TRUE if the commands list is/was ok. + */ +Boolean +Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) +{ + if (GNode_IsTarget(gn)) + return TRUE; + if (!Lst_IsEmpty(gn->commands)) + return TRUE; + if ((gn->type & OP_LIB) && !Lst_IsEmpty(gn->children)) + return TRUE; + + /* + * No commands. Look for .DEFAULT rule from which we might infer + * commands + */ + if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) && + (gn->type & OP_SPECIAL) == 0) { + /* + * Make only looks for a .DEFAULT if the node was never the + * target of an operator, so that's what we do too. If + * a .DEFAULT was given, we substitute its commands for gn's + * commands and set the IMPSRC variable to be the target's name + * The DEFAULT node acts like a transformation rule, in that + * gn also inherits any attributes or sources attached to + * .DEFAULT itself. + */ + Make_HandleUse(DEFAULT, gn); + Var_Set(IMPSRC, GNode_VarTarget(gn), gn); + return TRUE; + } + + if (Dir_MTime(gn, 0) != 0 || (gn->type & OP_SPECIAL)) + return TRUE; + + /* + * The node wasn't the target of an operator. We have no .DEFAULT + * rule to go on and the target doesn't already exist. There's + * nothing more we can do for this branch. If the -k flag wasn't + * given, we stop in our tracks, otherwise we just don't update + * this node's parents so they never get examined. + */ + + if (gn->flags & FROM_DEPEND) { + if (!Job_RunTarget(".STALE", gn->fname)) + fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n", + progname, gn->fname, gn->lineno, makeDependfile, + gn->name); + return TRUE; + } + + if (gn->type & OP_OPTIONAL) { + (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", + progname, gn->name, "ignored"); + (void)fflush(stdout); + return TRUE; + } + + if (opts.keepgoing) { + (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", + progname, gn->name, "continuing"); + (void)fflush(stdout); + return FALSE; + } + + abortProc("%s: don't know how to make %s. Stop", progname, gn->name); + return FALSE; +} + +/* Execute the shell for the given job. + * + * A shell is executed, its output is altered and the Job structure added + * to the job table. + */ +static void +JobExec(Job *job, char **argv) +{ + int cpid; /* ID of new child */ + sigset_t mask; + + job->flags &= ~JOB_TRACED; + + if (DEBUG(JOB)) { + int i; + + debug_printf("Running %s %sly\n", job->node->name, "local"); + debug_printf("\tCommand: "); + for (i = 0; argv[i] != NULL; i++) { + debug_printf("%s ", argv[i]); + } + debug_printf("\n"); + } + + /* + * Some jobs produce no output and it's disconcerting to have + * no feedback of their running (since they produce no output, the + * banner with their name in it never appears). This is an attempt to + * provide that feedback, even if nothing follows it. + */ + if ((lastNode != job->node) && !(job->flags & JOB_SILENT)) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } + + /* No interruptions until this job is on the `jobs' list */ + JobSigLock(&mask); + + /* Pre-emptively mark job running, pid still zero though */ + job->job_state = JOB_ST_RUNNING; + + cpid = vFork(); + if (cpid == -1) + Punt("Cannot vfork: %s", strerror(errno)); + + if (cpid == 0) { + /* Child */ + sigset_t tmask; + +#ifdef USE_META + if (useMeta) { + meta_job_child(job); + } +#endif + /* + * Reset all signal handlers; this is necessary because we also + * need to unblock signals before we exec(2). + */ + JobSigReset(); + + /* Now unblock signals */ + sigemptyset(&tmask); + JobSigUnlock(&tmask); + + /* + * Must duplicate the input stream down to the child's input and + * reset it to the beginning (again). Since the stream was marked + * close-on-exec, we must clear that bit in the new input. + */ + if (dup2(fileno(job->cmdFILE), 0) == -1) + execDie("dup2", "job->cmdFILE"); + if (fcntl(0, F_SETFD, 0) == -1) + execDie("fcntl clear close-on-exec", "stdin"); + if (lseek(0, (off_t)0, SEEK_SET) == -1) + execDie("lseek to 0", "stdin"); + + if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { + /* + * Pass job token pipe to submakes. + */ + if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) + execDie("clear close-on-exec", "tokenWaitJob.inPipe"); + if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) + execDie("clear close-on-exec", "tokenWaitJob.outPipe"); + } + + /* + * Set up the child's output to be routed through the pipe + * we've created for it. + */ + if (dup2(job->outPipe, 1) == -1) + execDie("dup2", "job->outPipe"); + + /* + * The output channels are marked close on exec. This bit was + * duplicated by the dup2(on some systems), so we have to clear + * it before routing the shell's error output to the same place as + * its standard output. + */ + if (fcntl(1, F_SETFD, 0) == -1) + execDie("clear close-on-exec", "stdout"); + if (dup2(1, 2) == -1) + execDie("dup2", "1, 2"); + + /* + * We want to switch the child into a different process family so + * we can kill it and all its descendants in one fell swoop, + * by killing its process family, but not commit suicide. + */ +#if defined(HAVE_SETPGID) + (void)setpgid(0, getpid()); +#else +#if defined(HAVE_SETSID) + /* XXX: dsl - I'm sure this should be setpgrp()... */ + (void)setsid(); +#else + (void)setpgrp(0, getpid()); +#endif +#endif + + Var_ExportVars(); + + (void)execv(shellPath, argv); + execDie("exec", shellPath); + } + + /* Parent, continuing after the child exec */ + job->pid = cpid; + + Trace_Log(JOBSTART, job); + +#ifdef USE_META + if (useMeta) { + meta_job_parent(job, cpid); + } +#endif + + /* + * Set the current position in the buffer to the beginning + * and mark another stream to watch in the outputs mask + */ + job->curPos = 0; + + watchfd(job); + + if (job->cmdFILE != NULL && job->cmdFILE != stdout) { + (void)fclose(job->cmdFILE); + job->cmdFILE = NULL; + } + + /* + * Now the job is actually running, add it to the table. + */ + if (DEBUG(JOB)) { + debug_printf("JobExec(%s): pid %d added to jobs table\n", + job->node->name, job->pid); + job_table_dump("job started"); + } + JobSigUnlock(&mask); +} + +/* Create the argv needed to execute the shell for a given job. */ +static void +JobMakeArgv(Job *job, char **argv) +{ + int argc; + static char args[10]; /* For merged arguments */ + + argv[0] = UNCONST(shellName); + argc = 1; + + if ((commandShell->exit && commandShell->exit[0] != '-') || + (commandShell->echo && commandShell->echo[0] != '-')) + { + /* + * At least one of the flags doesn't have a minus before it, so + * merge them together. Have to do this because the *(&(@*#*&#$# + * Bourne shell thinks its second argument is a file to source. + * Grrrr. Note the ten-character limitation on the combined arguments. + */ + (void)snprintf(args, sizeof(args), "-%s%s", + ((job->flags & JOB_IGNERR) ? "" : + (commandShell->exit ? commandShell->exit : "")), + ((job->flags & JOB_SILENT) ? "" : + (commandShell->echo ? commandShell->echo : ""))); + + if (args[1]) { + argv[argc] = args; + argc++; + } + } else { + if (!(job->flags & JOB_IGNERR) && commandShell->exit) { + argv[argc] = UNCONST(commandShell->exit); + argc++; + } + if (!(job->flags & JOB_SILENT) && commandShell->echo) { + argv[argc] = UNCONST(commandShell->echo); + argc++; + } + } + argv[argc] = NULL; +} + +/*- + *----------------------------------------------------------------------- + * JobStart -- + * Start a target-creation process going for the target described + * by the graph node gn. + * + * Input: + * gn target to create + * flags flags for the job to override normal ones. + * e.g. JOB_SPECIAL or JOB_IGNDOTS + * previous The previous Job structure for this node, if any. + * + * Results: + * JOB_ERROR if there was an error in the commands, JOB_FINISHED + * if there isn't actually anything left to do for the job and + * JOB_RUNNING if the job has been started. + * + * Side Effects: + * A new Job node is created and added to the list of running + * jobs. PMake is forked and a child shell created. + * + * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set + * JOB_IGNDOTS is never set (dsl) + * Also the return value is ignored by everyone. + *----------------------------------------------------------------------- + */ +static JobStartResult +JobStart(GNode *gn, int flags) +{ + Job *job; /* new job descriptor */ + char *argv[10]; /* Argument vector to shell */ + Boolean cmdsOK; /* true if the nodes commands were all right */ + Boolean noExec; /* Set true if we decide not to run the job */ + int tfd; /* File descriptor to the temp file */ + + for (job = job_table; job < job_table_end; job++) { + if (job->job_state == JOB_ST_FREE) + break; + } + if (job >= job_table_end) + Punt("JobStart no job slots vacant"); + + memset(job, 0, sizeof *job); + job->job_state = JOB_ST_SETUP; + if (gn->type & OP_SPECIAL) + flags |= JOB_SPECIAL; + + job->node = gn; + job->tailCmds = NULL; + + /* + * Set the initial value of the flags for this job based on the global + * ones and the node's attributes... Any flags supplied by the caller + * are also added to the field. + */ + job->flags = 0; + if (Targ_Ignore(gn)) { + job->flags |= JOB_IGNERR; + } + if (Targ_Silent(gn)) { + job->flags |= JOB_SILENT; + } + job->flags |= flags; + + /* + * Check the commands now so any attributes from .DEFAULT have a chance + * to migrate to the node + */ + cmdsOK = Job_CheckCommands(gn, Error); + + job->inPollfd = NULL; + /* + * If the -n flag wasn't given, we open up OUR (not the child's) + * temporary file to stuff commands in it. The thing is rd/wr so we don't + * need to reopen it to feed it to the shell. If the -n flag *was* given, + * we just set the file to be stdout. Cute, huh? + */ + if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) || + (!opts.noExecute && !opts.touchFlag)) { + /* + * tfile is the name of a file into which all shell commands are + * put. It is removed before the child shell is executed, unless + * DEBUG(SCRIPT) is set. + */ + char *tfile; + sigset_t mask; + /* + * We're serious here, but if the commands were bogus, we're + * also dead... + */ + if (!cmdsOK) { + PrintOnError(gn, NULL); /* provide some clue */ + DieHorribly(); + } + + JobSigLock(&mask); + tfd = mkTempFile(TMPPAT, &tfile); + if (!DEBUG(SCRIPT)) + (void)eunlink(tfile); + JobSigUnlock(&mask); + + job->cmdFILE = fdopen(tfd, "w+"); + if (job->cmdFILE == NULL) { + Punt("Could not fdopen %s", tfile); + } + (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC); + /* + * Send the commands to the command file, flush all its buffers then + * rewind and remove the thing. + */ + noExec = FALSE; + +#ifdef USE_META + if (useMeta) { + meta_job_start(job, gn); + if (Targ_Silent(gn)) { /* might have changed */ + job->flags |= JOB_SILENT; + } + } +#endif + /* + * We can do all the commands at once. hooray for sanity + */ + numCommands = 0; + JobPrintCommands(job); + + /* + * If we didn't print out any commands to the shell script, + * there's not much point in executing the shell, is there? + */ + if (numCommands == 0) { + noExec = TRUE; + } + + free(tfile); + } else if (!GNode_ShouldExecute(gn)) { + /* + * Not executing anything -- just print all the commands to stdout + * in one fell swoop. This will still set up job->tailCmds correctly. + */ + if (lastNode != gn) { + MESSAGE(stdout, gn); + lastNode = gn; + } + job->cmdFILE = stdout; + /* + * Only print the commands if they're ok, but don't die if they're + * not -- just let the user know they're bad and keep going. It + * doesn't do any harm in this case and may do some good. + */ + if (cmdsOK) + JobPrintCommands(job); + /* + * Don't execute the shell, thank you. + */ + noExec = TRUE; + } else { + /* + * Just touch the target and note that no shell should be executed. + * Set cmdFILE to stdout to make life easier. Check the commands, too, + * but don't die if they're no good -- it does no harm to keep working + * up the graph. + */ + job->cmdFILE = stdout; + Job_Touch(gn, job->flags&JOB_SILENT); + noExec = TRUE; + } + /* Just in case it isn't already... */ + (void)fflush(job->cmdFILE); + + /* + * If we're not supposed to execute a shell, don't. + */ + if (noExec) { + if (!(job->flags & JOB_SPECIAL)) + Job_TokenReturn(); + /* + * Unlink and close the command file if we opened one + */ + if (job->cmdFILE != stdout) { + if (job->cmdFILE != NULL) { + (void)fclose(job->cmdFILE); + job->cmdFILE = NULL; + } + } + + /* + * We only want to work our way up the graph if we aren't here because + * the commands for the job were no good. + */ + if (cmdsOK && aborting == ABORT_NONE) { + JobSaveCommands(job); + job->node->made = MADE; + Make_Update(job->node); + } + job->job_state = JOB_ST_FREE; + return cmdsOK ? JOB_FINISHED : JOB_ERROR; + } + + /* + * Set up the control arguments to the shell. This is based on the flags + * set earlier for this job. + */ + JobMakeArgv(job, argv); + + /* Create the pipe by which we'll get the shell's output. */ + JobCreatePipe(job, 3); + + JobExec(job, argv); + return JOB_RUNNING; +} + +static char * +JobOutput(Job *job, char *cp, char *endp) +{ + char *ecp; + + if (commandShell->noPrint && commandShell->noPrint[0] != '\0') { + while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) { + if (cp != ecp) { + *ecp = '\0'; + /* + * The only way there wouldn't be a newline after + * this line is if it were the last in the buffer. + * however, since the non-printable comes after it, + * there must be a newline, so we don't print one. + */ + (void)fprintf(stdout, "%s", cp); + (void)fflush(stdout); + } + cp = ecp + commandShell->noPrintLen; + if (cp != endp) { + /* + * Still more to print, look again after skipping + * the whitespace following the non-printable + * command.... + */ + cp++; + while (*cp == ' ' || *cp == '\t' || *cp == '\n') { + cp++; + } + } else { + return cp; + } + } + } + return cp; +} + +/*- + *----------------------------------------------------------------------- + * JobDoOutput -- + * This function is called at different times depending on + * whether the user has specified that output is to be collected + * via pipes or temporary files. In the former case, we are called + * whenever there is something to read on the pipe. We collect more + * output from the given job and store it in the job's outBuf. If + * this makes up a line, we print it tagged by the job's identifier, + * as necessary. + * If output has been collected in a temporary file, we open the + * file and read it line by line, transferring it to our own + * output channel until the file is empty. At which point we + * remove the temporary file. + * In both cases, however, we keep our figurative eye out for the + * 'noPrint' line for the shell from which the output came. If + * we recognize a line, we don't print it. If the command is not + * alone on the line (the character after it is not \0 or \n), we + * do print whatever follows it. + * + * Input: + * job the job whose output needs printing + * finish TRUE if this is the last time we'll be called + * for this job + * + * Side Effects: + * curPos may be shifted as may the contents of outBuf. + *----------------------------------------------------------------------- + */ +static void +JobDoOutput(Job *job, Boolean finish) +{ + Boolean gotNL = FALSE; /* true if got a newline */ + Boolean fbuf; /* true if our buffer filled up */ + size_t nr; /* number of bytes read */ + size_t i; /* auxiliary index into outBuf */ + size_t max; /* limit for i (end of current data) */ + ssize_t nRead; /* (Temporary) number of bytes read */ + + /* + * Read as many bytes as will fit in the buffer. + */ +end_loop: + gotNL = FALSE; + fbuf = FALSE; + + nRead = read(job->inPipe, &job->outBuf[job->curPos], + JOB_BUFSIZE - job->curPos); + if (nRead < 0) { + if (errno == EAGAIN) + return; + if (DEBUG(JOB)) { + perror("JobDoOutput(piperead)"); + } + nr = 0; + } else { + nr = (size_t)nRead; + } + + /* + * If we hit the end-of-file (the job is dead), we must flush its + * remaining output, so pretend we read a newline if there's any + * output remaining in the buffer. + * Also clear the 'finish' flag so we stop looping. + */ + if ((nr == 0) && (job->curPos != 0)) { + job->outBuf[job->curPos] = '\n'; + nr = 1; + finish = FALSE; + } else if (nr == 0) { + finish = FALSE; + } + + /* + * Look for the last newline in the bytes we just got. If there is + * one, break out of the loop with 'i' as its index and gotNL set + * TRUE. + */ + max = job->curPos + nr; + for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) { + if (job->outBuf[i] == '\n') { + gotNL = TRUE; + break; + } else if (job->outBuf[i] == '\0') { + /* + * Why? + */ + job->outBuf[i] = ' '; + } + } + + if (!gotNL) { + job->curPos += nr; + if (job->curPos == JOB_BUFSIZE) { + /* + * If we've run out of buffer space, we have no choice + * but to print the stuff. sigh. + */ + fbuf = TRUE; + i = job->curPos; + } + } + if (gotNL || fbuf) { + /* + * Need to send the output to the screen. Null terminate it + * first, overwriting the newline character if there was one. + * So long as the line isn't one we should filter (according + * to the shell description), we print the line, preceded + * by a target banner if this target isn't the same as the + * one for which we last printed something. + * The rest of the data in the buffer are then shifted down + * to the start of the buffer and curPos is set accordingly. + */ + job->outBuf[i] = '\0'; + if (i >= job->curPos) { + char *cp; + + cp = JobOutput(job, job->outBuf, &job->outBuf[i]); + + /* + * There's still more in that thar buffer. This time, though, + * we know there's no newline at the end, so we add one of + * our own free will. + */ + if (*cp != '\0') { + if (!opts.beSilent && job->node != lastNode) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } +#ifdef USE_META + if (useMeta) { + meta_job_output(job, cp, gotNL ? "\n" : ""); + } +#endif + (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); + (void)fflush(stdout); + } + } + /* + * max is the last offset still in the buffer. Move any remaining + * characters to the start of the buffer and update the end marker + * curPos. + */ + if (i < max) { + (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); + job->curPos = max - (i + 1); + } else { + assert(i == max); + job->curPos = 0; + } + } + if (finish) { + /* + * If the finish flag is true, we must loop until we hit + * end-of-file on the pipe. This is guaranteed to happen + * eventually since the other end of the pipe is now closed + * (we closed it explicitly and the child has exited). When + * we do get an EOF, finish will be set FALSE and we'll fall + * through and out. + */ + goto end_loop; + } +} + +static void +JobRun(GNode *targ) +{ +#if 0 + /* + * Unfortunately it is too complicated to run .BEGIN, .END, and + * .INTERRUPT job in the parallel job module. As of 2020-09-25, + * unit-tests/deptgt-end-jobs.mk hangs in an endless loop. + * + * Running these jobs in compat mode also guarantees that these + * jobs do not overlap with other unrelated jobs. + */ + List *lst = Lst_New(); + Lst_Append(lst, targ); + (void)Make_Run(lst); + Lst_Destroy(lst, NULL); + JobStart(targ, JOB_SPECIAL); + while (jobTokensRunning) { + Job_CatchOutput(); + } +#else + Compat_Make(targ, targ); + if (targ->made == ERROR) { + PrintOnError(targ, "\n\nStop."); + exit(1); + } +#endif +} + +/* Handle the exit of a child. Called from Make_Make. + * + * The job descriptor is removed from the list of children. + * + * Notes: + * We do waits, blocking or not, according to the wisdom of our + * caller, until there are no more children to report. For each + * job, call JobFinish to finish things off. + */ +void +Job_CatchChildren(void) +{ + int pid; /* pid of dead child */ + WAIT_T status; /* Exit/termination status */ + + /* + * Don't even bother if we know there's no one around. + */ + if (jobTokensRunning == 0) + return; + + while ((pid = waitpid((pid_t) -1, &status, WNOHANG | WUNTRACED)) > 0) { + DEBUG2(JOB, "Process %d exited/stopped status %x.\n", pid, + WAIT_STATUS(status)); + JobReapChild(pid, status, TRUE); + } +} + +/* + * It is possible that wait[pid]() was called from elsewhere, + * this lets us reap jobs regardless. + */ +void +JobReapChild(pid_t pid, WAIT_T status, Boolean isJobs) +{ + Job *job; /* job descriptor for dead child */ + + /* + * Don't even bother if we know there's no one around. + */ + if (jobTokensRunning == 0) + return; + + job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); + if (job == NULL) { + if (isJobs) { + if (!lurking_children) + Error("Child (%d) status %x not in table?", pid, status); + } + return; /* not ours */ + } + if (WIFSTOPPED(status)) { + DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name); + if (!make_suspended) { + switch (WSTOPSIG(status)) { + case SIGTSTP: + (void)printf("*** [%s] Suspended\n", job->node->name); + break; + case SIGSTOP: + (void)printf("*** [%s] Stopped\n", job->node->name); + break; + default: + (void)printf("*** [%s] Stopped -- signal %d\n", + job->node->name, WSTOPSIG(status)); + } + job->job_suspended = 1; + } + (void)fflush(stdout); + return; + } + + job->job_state = JOB_ST_FINISHED; + job->exit_status = WAIT_STATUS(status); + + JobFinish(job, status); +} + +/* Catch the output from our children, if we're using pipes do so. Otherwise + * just block time until we get a signal(most likely a SIGCHLD) since there's + * no point in just spinning when there's nothing to do and the reaping of a + * child can wait for a while. */ +void +Job_CatchOutput(void) +{ + int nready; + Job *job; + unsigned int i; + + (void)fflush(stdout); + + /* The first fd in the list is the job token pipe */ + do { + nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC); + } while (nready < 0 && errno == EINTR); + + if (nready < 0) + Punt("poll: %s", strerror(errno)); + + if (nready > 0 && readyfd(&childExitJob)) { + char token = 0; + ssize_t count; + count = read(childExitJob.inPipe, &token, 1); + switch (count) { + case 0: + Punt("unexpected eof on token pipe"); + case -1: + Punt("token pipe read: %s", strerror(errno)); + case 1: + if (token == DO_JOB_RESUME[0]) + /* Complete relay requested from our SIGCONT handler */ + JobRestartJobs(); + break; + default: + abort(); + } + --nready; + } + + Job_CatchChildren(); + if (nready == 0) + return; + + for (i = npseudojobs * nfds_per_job(); i < nfds; i++) { + if (!fds[i].revents) + continue; + job = jobfds[i]; + if (job->job_state == JOB_ST_RUNNING) + JobDoOutput(job, FALSE); +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + /* + * With meta mode, we may have activity on the job's filemon + * descriptor too, which at the moment is any pollfd other than + * job->inPollfd. + */ + if (useMeta && job->inPollfd != &fds[i]) { + if (meta_job_event(job) <= 0) { + fds[i].events = 0; /* never mind */ + } + } +#endif + if (--nready == 0) + return; + } +} + +/* Start the creation of a target. Basically a front-end for JobStart used by + * the Make module. */ +void +Job_Make(GNode *gn) +{ + (void)JobStart(gn, 0); +} + +void +Shell_Init(void) +{ + if (shellPath == NULL) { + /* + * We are using the default shell, which may be an absolute + * path if DEFSHELL_CUSTOM is defined. + */ + shellName = commandShell->name; +#ifdef DEFSHELL_CUSTOM + if (*shellName == '/') { + shellPath = shellName; + shellName = strrchr(shellPath, '/'); + shellName++; + } else +#endif + shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName); + } + Var_Set_with_flags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY); + if (commandShell->exit == NULL) { + commandShell->exit = ""; + } + if (commandShell->echo == NULL) { + commandShell->echo = ""; + } + if (commandShell->hasErrCtl && commandShell->exit[0] != '\0') { + if (shellErrFlag && + strcmp(commandShell->exit, &shellErrFlag[1]) != 0) { + free(shellErrFlag); + shellErrFlag = NULL; + } + if (!shellErrFlag) { + size_t n = strlen(commandShell->exit) + 2; + + shellErrFlag = bmake_malloc(n); + if (shellErrFlag) { + snprintf(shellErrFlag, n, "-%s", commandShell->exit); + } + } + } else if (shellErrFlag) { + free(shellErrFlag); + shellErrFlag = NULL; + } +} + +/* Return the string literal that is used in the current command shell + * to produce a newline character. */ +const char * +Shell_GetNewline(void) +{ + return commandShell->newline; +} + +void +Job_SetPrefix(void) +{ + if (targPrefix) { + free(targPrefix); + } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) { + Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL); + } + + (void)Var_Subst("${" MAKE_JOB_PREFIX "}", + VAR_GLOBAL, VARE_WANTRES, &targPrefix); + /* TODO: handle errors */ +} + +/* Initialize the process module. */ +void +Job_Init(void) +{ + Job_SetPrefix(); + /* Allocate space for all the job info */ + job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); + memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); + job_table_end = job_table + opts.maxJobs; + wantToken = 0; + + aborting = ABORT_NONE; + errors = 0; + + lastNode = NULL; + + /* + * There is a non-zero chance that we already have children. + * eg after 'make -f- < 0) + continue; + if (rval == 0) + lurking_children = 1; + break; + } + + Shell_Init(); + + JobCreatePipe(&childExitJob, 3); + + /* Preallocate enough for the maximum number of jobs. */ + fds = bmake_malloc(sizeof(*fds) * + (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); + jobfds = bmake_malloc(sizeof(*jobfds) * + (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); + + /* These are permanent entries and take slots 0 and 1 */ + watchfd(&tokenWaitJob); + watchfd(&childExitJob); + + sigemptyset(&caught_signals); + /* + * Install a SIGCHLD handler. + */ + (void)bmake_signal(SIGCHLD, JobChildSig); + sigaddset(&caught_signals, SIGCHLD); + +#define ADDSIG(s,h) \ + if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \ + sigaddset(&caught_signals, s); \ + (void)bmake_signal(s, h); \ + } + + /* + * Catch the four signals that POSIX specifies if they aren't ignored. + * JobPassSig will take care of calling JobInterrupt if appropriate. + */ + ADDSIG(SIGINT, JobPassSig_int) + ADDSIG(SIGHUP, JobPassSig_term) + ADDSIG(SIGTERM, JobPassSig_term) + ADDSIG(SIGQUIT, JobPassSig_term) + + /* + * There are additional signals that need to be caught and passed if + * either the export system wants to be told directly of signals or if + * we're giving each job its own process group (since then it won't get + * signals from the terminal driver as we own the terminal) + */ + ADDSIG(SIGTSTP, JobPassSig_suspend) + ADDSIG(SIGTTOU, JobPassSig_suspend) + ADDSIG(SIGTTIN, JobPassSig_suspend) + ADDSIG(SIGWINCH, JobCondPassSig) + ADDSIG(SIGCONT, JobContinueSig) +#undef ADDSIG + + (void)Job_RunTarget(".BEGIN", NULL); + /* Create the .END node now, even though no code in the unit tests + * depends on it. See also Targ_GetEndNode in Compat_Run. */ + (void)Targ_GetEndNode(); +} + +static void JobSigReset(void) +{ +#define DELSIG(s) \ + if (sigismember(&caught_signals, s)) { \ + (void)bmake_signal(s, SIG_DFL); \ + } + + DELSIG(SIGINT) + DELSIG(SIGHUP) + DELSIG(SIGQUIT) + DELSIG(SIGTERM) + DELSIG(SIGTSTP) + DELSIG(SIGTTOU) + DELSIG(SIGTTIN) + DELSIG(SIGWINCH) + DELSIG(SIGCONT) +#undef DELSIG + (void)bmake_signal(SIGCHLD, SIG_DFL); +} + +/* Find a shell in 'shells' given its name, or return NULL. */ +static Shell * +FindShellByName(const char *name) +{ + Shell *sh = shells; + const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0]; + + for (sh = shells; sh < shellsEnd; sh++) { + if (strcmp(name, sh->name) == 0) + return sh; + } + return NULL; +} + +/*- + *----------------------------------------------------------------------- + * Job_ParseShell -- + * Parse a shell specification and set up commandShell, shellPath + * and shellName appropriately. + * + * Input: + * line The shell spec + * + * Results: + * FALSE if the specification was incorrect. + * + * Side Effects: + * commandShell points to a Shell structure (either predefined or + * created from the shell spec), shellPath is the full path of the + * shell described by commandShell, while shellName is just the + * final component of shellPath. + * + * Notes: + * A shell specification consists of a .SHELL target, with dependency + * operator, followed by a series of blank-separated words. Double + * quotes can be used to use blanks in words. A backslash escapes + * anything (most notably a double-quote and a space) and + * provides the functionality it does in C. Each word consists of + * keyword and value separated by an equal sign. There should be no + * unnecessary spaces in the word. The keywords are as follows: + * name Name of shell. + * path Location of shell. + * quiet Command to turn off echoing. + * echo Command to turn echoing on + * filter Result of turning off echoing that shouldn't be + * printed. + * echoFlag Flag to turn echoing on at the start + * errFlag Flag to turn error checking on at the start + * hasErrCtl True if shell has error checking control + * newline String literal to represent a newline char + * check Command to turn on error checking if hasErrCtl + * is TRUE or template of command to echo a command + * for which error checking is off if hasErrCtl is + * FALSE. + * ignore Command to turn off error checking if hasErrCtl + * is TRUE or template of command to execute a + * command so as to ignore any errors it returns if + * hasErrCtl is FALSE. + * + *----------------------------------------------------------------------- + */ +Boolean +Job_ParseShell(char *line) +{ + Words wordsList; + char **words; + char **argv; + size_t argc; + char *path; + Shell newShell; + Boolean fullSpec = FALSE; + Shell *sh; + + pp_skip_whitespace(&line); + + free(shellArgv); + + memset(&newShell, 0, sizeof(newShell)); + + /* + * Parse the specification by keyword + */ + wordsList = Str_Words(line, TRUE); + words = wordsList.words; + argc = wordsList.len; + path = wordsList.freeIt; + if (words == NULL) { + Error("Unterminated quoted string [%s]", line); + return FALSE; + } + shellArgv = path; + + for (path = NULL, argv = words; argc != 0; argc--, argv++) { + char *arg = *argv; + if (strncmp(arg, "path=", 5) == 0) { + path = arg + 5; + } else if (strncmp(arg, "name=", 5) == 0) { + newShell.name = arg + 5; + } else { + if (strncmp(arg, "quiet=", 6) == 0) { + newShell.echoOff = arg + 6; + } else if (strncmp(arg, "echo=", 5) == 0) { + newShell.echoOn = arg + 5; + } else if (strncmp(arg, "filter=", 7) == 0) { + newShell.noPrint = arg + 7; + newShell.noPrintLen = strlen(newShell.noPrint); + } else if (strncmp(arg, "echoFlag=", 9) == 0) { + newShell.echo = arg + 9; + } else if (strncmp(arg, "errFlag=", 8) == 0) { + newShell.exit = arg + 8; + } else if (strncmp(arg, "hasErrCtl=", 10) == 0) { + char c = arg[10]; + newShell.hasErrCtl = c == 'Y' || c == 'y' || + c == 'T' || c == 't'; + } else if (strncmp(arg, "newline=", 8) == 0) { + newShell.newline = arg + 8; + } else if (strncmp(arg, "check=", 6) == 0) { + newShell.errOnOrEcho = arg + 6; + } else if (strncmp(arg, "ignore=", 7) == 0) { + newShell.errOffOrExecIgnore = arg + 7; + } else if (strncmp(arg, "errout=", 7) == 0) { + newShell.errExit = arg + 7; + } else if (strncmp(arg, "comment=", 8) == 0) { + newShell.commentChar = arg[8]; + } else { + Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", arg); + free(words); + return FALSE; + } + fullSpec = TRUE; + } + } + + if (path == NULL) { + /* + * If no path was given, the user wants one of the pre-defined shells, + * yes? So we find the one s/he wants with the help of FindShellByName + * and set things up the right way. shellPath will be set up by + * Shell_Init. + */ + if (newShell.name == NULL) { + Parse_Error(PARSE_FATAL, "Neither path nor name specified"); + free(words); + return FALSE; + } else { + if ((sh = FindShellByName(newShell.name)) == NULL) { + Parse_Error(PARSE_WARNING, "%s: No matching shell", + newShell.name); + free(words); + return FALSE; + } + commandShell = sh; + shellName = newShell.name; + if (shellPath) { + /* Shell_Init has already been called! Do it again. */ + free(UNCONST(shellPath)); + shellPath = NULL; + Shell_Init(); + } + } + } else { + /* + * The user provided a path. If s/he gave nothing else (fullSpec is + * FALSE), try and find a matching shell in the ones we know of. + * Else we just take the specification at its word and copy it + * to a new location. In either case, we need to record the + * path the user gave for the shell. + */ + shellPath = path; + path = strrchr(path, '/'); + if (path == NULL) { + path = UNCONST(shellPath); + } else { + path++; + } + if (newShell.name != NULL) { + shellName = newShell.name; + } else { + shellName = path; + } + if (!fullSpec) { + if ((sh = FindShellByName(shellName)) == NULL) { + Parse_Error(PARSE_WARNING, "%s: No matching shell", + shellName); + free(words); + return FALSE; + } + commandShell = sh; + } else { + commandShell = bmake_malloc(sizeof(Shell)); + *commandShell = newShell; + } + /* this will take care of shellErrFlag */ + Shell_Init(); + } + + if (commandShell->echoOn && commandShell->echoOff) { + commandShell->hasEchoCtl = TRUE; + } + + if (!commandShell->hasErrCtl) { + if (commandShell->errOnOrEcho == NULL) { + commandShell->errOnOrEcho = ""; + } + if (commandShell->errOffOrExecIgnore == NULL) { + commandShell->errOffOrExecIgnore = "%s\n"; + } + } + + /* + * Do not free up the words themselves, since they might be in use by the + * shell specification. + */ + free(words); + return TRUE; +} + +/* Handle the receipt of an interrupt. + * + * All children are killed. Another job will be started if the .INTERRUPT + * target is defined. + * + * Input: + * runINTERRUPT Non-zero if commands for the .INTERRUPT target + * should be executed + * signo signal received + */ +static void +JobInterrupt(int runINTERRUPT, int signo) +{ + Job *job; /* job descriptor in that element */ + GNode *interrupt; /* the node describing the .INTERRUPT target */ + sigset_t mask; + GNode *gn; + + aborting = ABORT_INTERRUPT; + + JobSigLock(&mask); + + for (job = job_table; job < job_table_end; job++) { + if (job->job_state != JOB_ST_RUNNING) + continue; + + gn = job->node; + + JobDeleteTarget(gn); + if (job->pid) { + DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n", + signo, job->pid); + KILLPG(job->pid, signo); + } + } + + JobSigUnlock(&mask); + + if (runINTERRUPT && !opts.touchFlag) { + interrupt = Targ_FindNode(".INTERRUPT"); + if (interrupt != NULL) { + opts.ignoreErrors = FALSE; + JobRun(interrupt); + } + } + Trace_Log(MAKEINTR, 0); + exit(signo); +} + +/* Do the final processing, i.e. run the commands attached to the .END target. + * + * Return the number of errors reported. */ +int +Job_Finish(void) +{ + GNode *endNode = Targ_GetEndNode(); + if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) { + if (errors) { + Error("Errors reported so .END ignored"); + } else { + JobRun(endNode); + } + } + return errors; +} + +/* Clean up any memory used by the jobs module. */ +void +Job_End(void) +{ +#ifdef CLEANUP + free(shellArgv); +#endif +} + +/* Waits for all running jobs to finish and returns. + * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. */ +void +Job_Wait(void) +{ + aborting = ABORT_WAIT; + while (jobTokensRunning != 0) { + Job_CatchOutput(); + } + aborting = ABORT_NONE; +} + +/* Abort all currently running jobs without handling output or anything. + * This function is to be called only in the event of a major error. + * Most definitely NOT to be called from JobInterrupt. + * + * All children are killed, not just the firstborn. */ +void +Job_AbortAll(void) +{ + Job *job; /* the job descriptor in that element */ + WAIT_T foo; + + aborting = ABORT_ERROR; + + if (jobTokensRunning) { + for (job = job_table; job < job_table_end; job++) { + if (job->job_state != JOB_ST_RUNNING) + continue; + /* + * kill the child process with increasingly drastic signals to make + * darn sure it's dead. + */ + KILLPG(job->pid, SIGINT); + KILLPG(job->pid, SIGKILL); + } + } + + /* + * Catch as many children as want to report in at first, then give up + */ + while (waitpid((pid_t) -1, &foo, WNOHANG) > 0) + continue; +} + +/* Tries to restart stopped jobs if there are slots available. + * Called in process context in response to a SIGCONT. */ +static void +JobRestartJobs(void) +{ + Job *job; + + for (job = job_table; job < job_table_end; job++) { + if (job->job_state == JOB_ST_RUNNING && + (make_suspended || job->job_suspended)) { + DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid); + if (job->job_suspended) { + (void)printf("*** [%s] Continued\n", job->node->name); + (void)fflush(stdout); + } + job->job_suspended = 0; + if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) { + debug_printf("Failed to send SIGCONT to %d\n", job->pid); + } + } + if (job->job_state == JOB_ST_FINISHED) + /* Job exit deferred after calling waitpid() in a signal handler */ + JobFinish(job, job->exit_status); + } + make_suspended = 0; +} + +static void +watchfd(Job *job) +{ + if (job->inPollfd != NULL) + Punt("Watching watched job"); + + fds[nfds].fd = job->inPipe; + fds[nfds].events = POLLIN; + jobfds[nfds] = job; + job->inPollfd = &fds[nfds]; + nfds++; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + fds[nfds].fd = meta_job_fd(job); + fds[nfds].events = fds[nfds].fd == -1 ? 0 : POLLIN; + jobfds[nfds] = job; + nfds++; + } +#endif +} + +static void +clearfd(Job *job) +{ + size_t i; + if (job->inPollfd == NULL) + Punt("Unwatching unwatched job"); + i = (size_t)(job->inPollfd - fds); + nfds--; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + /* + * Sanity check: there should be two fds per job, so the job's + * pollfd number should be even. + */ + assert(nfds_per_job() == 2); + if (i % 2) + Punt("odd-numbered fd with meta"); + nfds--; + } +#endif + /* + * Move last job in table into hole made by dead job. + */ + if (nfds != i) { + fds[i] = fds[nfds]; + jobfds[i] = jobfds[nfds]; + jobfds[i]->inPollfd = &fds[i]; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + fds[i + 1] = fds[nfds + 1]; + jobfds[i + 1] = jobfds[nfds + 1]; + } +#endif + } + job->inPollfd = NULL; +} + +static int +readyfd(Job *job) +{ + if (job->inPollfd == NULL) + Punt("Polling unwatched job"); + return (job->inPollfd->revents & POLLIN) != 0; +} + +/* Put a token (back) into the job pipe. + * This allows a make process to start a build job. */ +static void +JobTokenAdd(void) +{ + char tok = JOB_TOKENS[aborting], tok1; + + /* If we are depositing an error token flush everything else */ + while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1) + continue; + + DEBUG3(JOB, "(%d) aborting %d, deposit token %c\n", + getpid(), aborting, tok); + while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) + continue; +} + +/* Prep the job token pipe in the root make process. */ +void +Job_ServerStart(int max_tokens, int jp_0, int jp_1) +{ + int i; + char jobarg[64]; + + if (jp_0 >= 0 && jp_1 >= 0) { + /* Pipe passed in from parent */ + tokenWaitJob.inPipe = jp_0; + tokenWaitJob.outPipe = jp_1; + (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC); + (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC); + return; + } + + JobCreatePipe(&tokenWaitJob, 15); + + snprintf(jobarg, sizeof(jobarg), "%d,%d", + tokenWaitJob.inPipe, tokenWaitJob.outPipe); + + Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); + Var_Append(MAKEFLAGS, jobarg, VAR_GLOBAL); + + /* + * Preload the job pipe with one token per job, save the one + * "extra" token for the primary job. + * + * XXX should clip maxJobs against PIPE_BUF -- if max_tokens is + * larger than the write buffer size of the pipe, we will + * deadlock here. + */ + for (i = 1; i < max_tokens; i++) + JobTokenAdd(); +} + +/* Return a withdrawn token to the pool. */ +void +Job_TokenReturn(void) +{ + jobTokensRunning--; + if (jobTokensRunning < 0) + Punt("token botch"); + if (jobTokensRunning || JOB_TOKENS[aborting] != '+') + JobTokenAdd(); +} + +/* Attempt to withdraw a token from the pool. + * + * If pool is empty, set wantToken so that we wake up when a token is + * released. + * + * Returns TRUE if a token was withdrawn, and FALSE if the pool is currently + * empty. */ +Boolean +Job_TokenWithdraw(void) +{ + char tok, tok1; + ssize_t count; + + wantToken = 0; + DEBUG3(JOB, "Job_TokenWithdraw(%d): aborting %d, running %d\n", + getpid(), aborting, jobTokensRunning); + + if (aborting != ABORT_NONE || (jobTokensRunning >= opts.maxJobs)) + return FALSE; + + count = read(tokenWaitJob.inPipe, &tok, 1); + if (count == 0) + Fatal("eof on job pipe!"); + if (count < 0 && jobTokensRunning != 0) { + if (errno != EAGAIN) { + Fatal("job pipe read: %s", strerror(errno)); + } + DEBUG1(JOB, "(%d) blocked for token\n", getpid()); + return FALSE; + } + + if (count == 1 && tok != '+') { + /* make being abvorted - remove any other job tokens */ + DEBUG2(JOB, "(%d) aborted by token %c\n", getpid(), tok); + while (read(tokenWaitJob.inPipe, &tok1, 1) == 1) + continue; + /* And put the stopper back */ + while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) + continue; + if (dieQuietly(NULL, 1)) + exit(2); + Fatal("A failure has been detected in another branch of the parallel make"); + } + + if (count == 1 && jobTokensRunning == 0) + /* We didn't want the token really */ + while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) + continue; + + jobTokensRunning++; + DEBUG1(JOB, "(%d) withdrew token\n", getpid()); + return TRUE; +} + +/* Run the named target if found. If a filename is specified, then set that + * to the sources. + * + * Exits if the target fails. */ +Boolean +Job_RunTarget(const char *target, const char *fname) { + GNode *gn = Targ_FindNode(target); + if (gn == NULL) + return FALSE; + + if (fname) + Var_Set(ALLSRC, fname, gn); + + JobRun(gn); + if (gn->made == ERROR) { + PrintOnError(gn, "\n\nStop."); + exit(1); + } + return TRUE; +} + +#ifdef USE_SELECT +int +emul_poll(struct pollfd *fd, int nfd, int timeout) +{ + fd_set rfds, wfds; + int i, maxfd, nselect, npoll; + struct timeval tv, *tvp; + long usecs; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + maxfd = -1; + for (i = 0; i < nfd; i++) { + fd[i].revents = 0; + + if (fd[i].events & POLLIN) + FD_SET(fd[i].fd, &rfds); + + if (fd[i].events & POLLOUT) + FD_SET(fd[i].fd, &wfds); + + if (fd[i].fd > maxfd) + maxfd = fd[i].fd; + } + + if (maxfd >= FD_SETSIZE) { + Punt("Ran out of fd_set slots; " + "recompile with a larger FD_SETSIZE."); + } + + if (timeout < 0) { + tvp = NULL; + } else { + usecs = timeout * 1000; + tv.tv_sec = usecs / 1000000; + tv.tv_usec = usecs % 1000000; + tvp = &tv; + } + + nselect = select(maxfd + 1, &rfds, &wfds, 0, tvp); + + if (nselect <= 0) + return nselect; + + npoll = 0; + for (i = 0; i < nfd; i++) { + if (FD_ISSET(fd[i].fd, &rfds)) + fd[i].revents |= POLLIN; + + if (FD_ISSET(fd[i].fd, &wfds)) + fd[i].revents |= POLLOUT; + + if (fd[i].revents) + npoll++; + } + + return npoll; +} +#endif /* USE_SELECT */ Property changes on: vendor/NetBSD/bmake/20201101/job.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/job.h =================================================================== --- vendor/NetBSD/bmake/20201101/job.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/job.h (revision 367461) @@ -0,0 +1,215 @@ +/* $NetBSD: job.h,v 1.58 2020/10/26 21:34:10 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)job.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)job.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Running of jobs in parallel mode. + */ + +#ifndef MAKE_JOB_H +#define MAKE_JOB_H + +#define TMPPAT "makeXXXXXX" /* relative to tmpdir */ + +#ifdef USE_SELECT +/* + * Emulate poll() in terms of select(). This is not a complete + * emulation but it is sufficient for make's purposes. + */ + +#define poll emul_poll +#define pollfd emul_pollfd + +struct emul_pollfd { + int fd; + short events; + short revents; +}; + +#define POLLIN 0x0001 +#define POLLOUT 0x0004 + +int +emul_poll(struct pollfd *fd, int nfd, int timeout); +#endif + +/* + * The POLL_MSEC constant determines the maximum number of milliseconds spent + * in poll before coming out to see if a child has finished. + */ +#define POLL_MSEC 5000 + +struct pollfd; + + +#ifdef USE_META +# include "meta.h" +#endif + +typedef enum JobState { + JOB_ST_FREE = 0, /* Job is available */ + JOB_ST_SETUP = 1, /* Job is allocated but otherwise invalid */ + JOB_ST_RUNNING = 3, /* Job is running, pid valid */ + JOB_ST_FINISHED = 4 /* Job is done (ie after SIGCHILD) */ +} JobState; + +typedef enum JobFlags { + /* Ignore non-zero exits */ + JOB_IGNERR = 0x001, + /* no output */ + JOB_SILENT = 0x002, + /* Target is a special one. i.e. run it locally + * if we can't export it and maxLocal is 0 */ + JOB_SPECIAL = 0x004, + /* Ignore "..." lines when processing commands */ + JOB_IGNDOTS = 0x008, + /* we've sent 'set -x' */ + JOB_TRACED = 0x400 +} JobFlags; + +/* A Job manages the shell commands that are run to create a single target. + * Each job is run in a separate subprocess by a shell. Several jobs can run + * in parallel. + * + * The shell commands for the target are written to a temporary file, + * then the shell is run with the temporary file as stdin, and the output + * of that shell is captured via a pipe. + * + * When a job is finished, Make_Update updates all parents of the node + * that was just remade, marking them as ready to be made next if all + * other dependencies are finished as well. */ +typedef struct Job { + /* The process ID of the shell running the commands */ + int pid; + + /* The target the child is making */ + GNode *node; + + /* If one of the shell commands is "...", all following commands are + * delayed until the .END node is made. This list node points to the + * first of these commands, if any. */ + StringListNode *tailCmds; + + /* When creating the shell script, this is where the commands go. + * This is only used before the job is actually started. */ + FILE *cmdFILE; + + int exit_status; /* from wait4() in signal handler */ + + JobState job_state; /* status of the job entry */ + + char job_suspended; + + JobFlags flags; /* Flags to control treatment of job */ + + int inPipe; /* Pipe for reading output from job */ + int outPipe; /* Pipe for writing control commands */ + struct pollfd *inPollfd; /* pollfd associated with inPipe */ + +#define JOB_BUFSIZE 1024 + /* Buffer for storing the output of the job, line by line. */ + char outBuf[JOB_BUFSIZE + 1]; + size_t curPos; /* Current position in outBuf. */ + +#ifdef USE_META + struct BuildMon bm; +#endif +} Job; + +extern const char *shellPath; +extern const char *shellName; +extern char *shellErrFlag; + +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_CatchChildren(void); +void Job_CatchOutput(void); +void Job_Make(GNode *); +void Job_Init(void); +Boolean 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); +void Job_ServerStart(int, int, int); +void Job_SetPrefix(void); +Boolean Job_RunTarget(const char *, const char *); + +#endif /* MAKE_JOB_H */ Property changes on: vendor/NetBSD/bmake/20201101/job.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/lst.c =================================================================== --- vendor/NetBSD/bmake/20201101/lst.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/lst.c (revision 367461) @@ -0,0 +1,319 @@ +/* $NetBSD: lst.c,v 1.91 2020/10/28 02:43:16 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include "make.h" + +MAKE_RCSID("$NetBSD: lst.c,v 1.91 2020/10/28 02:43:16 rillig Exp $"); + +#ifdef HAVE_INTTYPES_H +#include +#elif defined(HAVE_STDINT_H) +#include +#endif + +static ListNode * +LstNodeNew(ListNode *prev, ListNode *next, void *datum) +{ + ListNode *node = bmake_malloc(sizeof *node); + node->prev = prev; + node->next = next; + node->datum = datum; + return node; +} + +/* Create and initialize a new, empty list. */ +List * +Lst_New(void) +{ + List *list = bmake_malloc(sizeof *list); + + list->first = NULL; + list->last = NULL; + + return list; +} + +/* Free a list and all its nodes. The node data are not freed though. */ +void +Lst_Free(List *list) +{ + ListNode *node; + ListNode *next; + + for (node = list->first; node != NULL; node = next) { + next = node->next; + free(node); + } + + free(list); +} + +/* Destroy a list and free all its resources. The freeProc is called with the + * datum from each node in turn before the node is freed. */ +void +Lst_Destroy(List *list, LstFreeProc freeProc) +{ + ListNode *node; + ListNode *next; + + for (node = list->first; node != NULL; node = next) { + next = node->next; + freeProc(node->datum); + free(node); + } + + free(list); +} + +/* + * Functions to modify a list + */ + +/* Insert a new node with the datum before the given node. */ +void +Lst_InsertBefore(List *list, ListNode *node, void *datum) +{ + ListNode *newNode; + + assert(datum != NULL); + + newNode = LstNodeNew(node->prev, node, datum); + + if (node->prev != NULL) + node->prev->next = newNode; + node->prev = newNode; + + if (node == list->first) + list->first = newNode; +} + +/* Add a piece of data at the start of the given list. */ +void +Lst_Prepend(List *list, void *datum) +{ + ListNode *node; + + assert(datum != NULL); + + node = LstNodeNew(NULL, list->first, datum); + + if (list->first == NULL) { + list->first = node; + list->last = node; + } else { + list->first->prev = node; + list->first = node; + } +} + +/* Add a piece of data at the end of the given list. */ +void +Lst_Append(List *list, void *datum) +{ + ListNode *node; + + assert(datum != NULL); + + node = LstNodeNew(list->last, NULL, datum); + + if (list->last == NULL) { + list->first = node; + list->last = node; + } else { + list->last->next = node; + list->last = node; + } +} + +/* Remove the given node from the given list. + * The datum stored in the node must be freed by the caller, if necessary. */ +void +Lst_Remove(List *list, ListNode *node) +{ + /* unlink it from its neighbors */ + if (node->next != NULL) + node->next->prev = node->prev; + if (node->prev != NULL) + node->prev->next = node->next; + + /* unlink it from the list */ + if (list->first == node) + list->first = node->next; + if (list->last == node) + list->last = node->prev; +} + +/* Replace the datum in the given node with the new datum. */ +void +LstNode_Set(ListNode *node, void *datum) +{ + assert(datum != NULL); + + node->datum = datum; +} + +/* Replace the datum in the given node to NULL. + * Having NULL values in a list is unusual though. */ +void +LstNode_SetNull(ListNode *node) +{ + node->datum = NULL; +} + +/* + * Functions for entire lists + */ + +/* Return the first node that contains the given datum, or NULL. */ +ListNode * +Lst_FindDatum(List *list, const void *datum) +{ + ListNode *node; + + assert(datum != NULL); + + for (node = list->first; node != NULL; node = node->next) + if (node->datum == datum) + return node; + + return NULL; +} + +int +Lst_ForEachUntil(List *list, LstActionUntilProc proc, void *procData) +{ + ListNode *node; + int result = 0; + + for (node = list->first; node != NULL; node = node->next) { + result = proc(node->datum, procData); + if (result != 0) + break; + } + return result; +} + +/* Move all nodes from list2 to the end of list1. + * List2 is destroyed and freed. */ +void +Lst_MoveAll(List *list1, List *list2) +{ + if (list2->first != NULL) { + list2->first->prev = list1->last; + if (list1->last != NULL) + list1->last->next = list2->first; + else + list1->first = list2->first; + + list1->last = list2->last; + } + free(list2); +} + +/* Copy the element data from src to the start of dst. */ +void +Lst_PrependAll(List *dst, List *src) +{ + ListNode *node; + for (node = src->last; node != NULL; node = node->prev) + Lst_Prepend(dst, node->datum); +} + +/* Copy the element data from src to the end of dst. */ +void +Lst_AppendAll(List *dst, List *src) +{ + ListNode *node; + for (node = src->first; node != NULL; node = node->next) + Lst_Append(dst, node->datum); +} + +/* + * for using the list as a queue + */ + +/* Add the datum to the tail of the given list. */ +void +Lst_Enqueue(List *list, void *datum) +{ + Lst_Append(list, datum); +} + +/* Remove and return the datum at the head of the given list. */ +void * +Lst_Dequeue(List *list) +{ + void *datum = list->first->datum; + Lst_Remove(list, list->first); + assert(datum != NULL); /* since NULL would mean end of the list */ + return datum; +} + +void +Vector_Init(Vector *v, size_t itemSize) +{ + v->len = 0; + v->priv_cap = 10; + v->itemSize = itemSize; + v->items = bmake_malloc(v->priv_cap * v->itemSize); +} + +/* Add space for a new item to the vector and return a pointer to that space. + * The returned data is valid until the next modifying operation. */ +void * +Vector_Push(Vector *v) +{ + if (v->len >= v->priv_cap) { + v->priv_cap *= 2; + v->items = bmake_realloc(v->items, v->priv_cap * v->itemSize); + } + v->len++; + return Vector_Get(v, v->len - 1); +} + +/* Return the pointer to the last item in the vector. + * The returned data is valid until the next modifying operation. */ +void * +Vector_Pop(Vector *v) +{ + assert(v->len > 0); + v->len--; + return Vector_Get(v, v->len); +} + +void +Vector_Done(Vector *v) +{ + free(v->items); +} Property changes on: vendor/NetBSD/bmake/20201101/lst.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/lst.h =================================================================== --- vendor/NetBSD/bmake/20201101/lst.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/lst.h (revision 367461) @@ -0,0 +1,187 @@ +/* $NetBSD: lst.h,v 1.84 2020/10/28 02:43:16 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)lst.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)lst.h 8.1 (Berkeley) 6/6/93 + */ + +/* Doubly-linked lists of arbitrary pointers. */ + +#ifndef MAKE_LST_H +#define MAKE_LST_H + +#include +#include +#include + +/* A doubly-linked list of pointers. */ +typedef struct List List; +/* A single node in the doubly-linked list. */ +typedef struct ListNode ListNode; + +struct ListNode { + ListNode *prev; /* previous node in list, or NULL */ + ListNode *next; /* next node in list, or NULL */ + union { + void *datum; /* datum associated with this element */ + const struct GNode *priv_gnode; /* alias, just for debugging */ + const char *priv_str; /* alias, just for debugging */ + }; +}; + +struct List { + ListNode *first; /* first node in list */ + ListNode *last; /* last node in list */ +}; + +/* Free the datum of a node, called before freeing the node itself. */ +typedef void LstFreeProc(void *); +/* An action for Lst_ForEachUntil and Lst_ForEachUntilConcurrent. */ +typedef int LstActionUntilProc(void *datum, void *args); + +/* Create or destroy a list */ + +/* Create a new list. */ +List *Lst_New(void); +/* Free the list, leaving the node data unmodified. */ +void Lst_Free(List *); +/* Free the list, freeing the node data using the given function. */ +void Lst_Destroy(List *, LstFreeProc); + +/* Get information about a list */ + +static inline MAKE_ATTR_UNUSED Boolean +Lst_IsEmpty(List *list) { return list->first == NULL; } + +/* Find the first node that contains the given datum, or NULL. */ +ListNode *Lst_FindDatum(List *, const void *); + +/* Modify a list */ + +/* Insert a datum before the given node. */ +void Lst_InsertBefore(List *, ListNode *, void *); +/* Place a datum at the front of the list. */ +void Lst_Prepend(List *, void *); +/* Place a datum at the end of the list. */ +void Lst_Append(List *, void *); +/* Remove the node from the list. */ +void Lst_Remove(List *, ListNode *); +void Lst_PrependAll(List *, List *); +void Lst_AppendAll(List *, List *); +void Lst_MoveAll(List *, List *); + +/* Node-specific functions */ + +/* Replace the value of the node. */ +void LstNode_Set(ListNode *, void *); +/* Set the value of the node to NULL. Having NULL in a list is unusual. */ +void LstNode_SetNull(ListNode *); + +/* Iterating over a list, using a callback function */ + +/* Run the action for each datum of the list, until the action returns + * non-zero. + * + * During this iteration, the list must not be modified structurally. */ +int Lst_ForEachUntil(List *, LstActionUntilProc, void *); + +/* Using the list as a queue */ + +/* Add a datum at the tail of the queue. */ +void Lst_Enqueue(List *, void *); +/* Remove the head node of the queue and return its datum. */ +void *Lst_Dequeue(List *); + +/* A vector is an ordered collection of items, allowing for fast indexed + * access. */ +typedef struct Vector { + void *items; /* memory holding the items */ + size_t itemSize; /* size of a single item in bytes */ + size_t len; /* number of actually usable elements */ + size_t priv_cap; /* capacity */ +} Vector; + +void Vector_Init(Vector *, size_t); + +/* Return the pointer to the given item in the vector. + * The returned data is valid until the next modifying operation. */ +static inline MAKE_ATTR_UNUSED void * +Vector_Get(Vector *v, size_t i) +{ + unsigned char *items = v->items; + return items + i * v->itemSize; +} + +void *Vector_Push(Vector *); +void *Vector_Pop(Vector *); +void Vector_Done(Vector *); + +#endif /* MAKE_LST_H */ Property changes on: vendor/NetBSD/bmake/20201101/lst.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/main.c =================================================================== --- vendor/NetBSD/bmake/20201101/main.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/main.c (revision 367461) @@ -0,0 +1,2283 @@ +/* $NetBSD: main.c,v 1.421 2020/11/01 00:24:57 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * main.c -- + * The main file for this entire program. Exit routines etc + * reside here. + * + * Utility functions defined in this file: + * Main_ParseArgLine Takes a line of arguments, breaks them and + * treats them as if they were given when first + * invoked. Used by the parse module to implement + * the .MFLAGS target. + * + * Error Print a tagged error message. The global + * MAKE variable must have been defined. This + * takes a format string and optional arguments + * for it. + * + * Fatal Print an error message and exit. Also takes + * a format string and arguments for it. + * + * Punt Aborts all jobs and exits with a message. Also + * takes a format string and arguments for it. + * + * Finish Finish things up by printing the number of + * errors which occurred, as passed to it, and + * exiting. + */ + +#include +#include +#include +#include +#include +#if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL) +#include +#endif +#include +#include "wait.h" + +#include +#include +#include +#include + +#include "make.h" +#include "dir.h" +#include "job.h" +#include "pathnames.h" +#include "trace.h" + +/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: main.c,v 1.421 2020/11/01 00:24:57 rillig Exp $"); +#if defined(MAKE_NATIVE) && !defined(lint) +__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " + "The Regents of the University of California. " + "All rights reserved."); +#endif + +#ifndef DEFMAXLOCAL +#define DEFMAXLOCAL DEFMAXJOBS +#endif + +#ifndef __arraycount +# define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) +#endif + +CmdOpts opts; +time_t now; /* Time at start of make */ +GNode *DEFAULT; /* .DEFAULT node */ +Boolean allPrecious; /* .PRECIOUS given on line by itself */ +Boolean deleteOnError; /* .DELETE_ON_ERROR: set */ + +static int maxJobTokens; /* -j argument */ +Boolean enterFlagObj; /* -w and objdir != srcdir */ + +Boolean oldVars; /* variable substitution style */ +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 */ +static const char * tracefile; +static int ReadMakefile(const char *); +static void usage(void) MAKE_ATTR_DEAD; +static void purge_cached_realpaths(void); + +static Boolean ignorePWD; /* if we use -C, PWD is meaningless */ +static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */ +char curdir[MAXPATHLEN + 1]; /* Startup directory */ +char *progname; /* the program name */ +char *makeDependfile; +pid_t myPid; +int makelevel; + +Boolean forceJobs = FALSE; +static int errors = 0; + +/* + * On some systems MACHINE is defined as something other than + * what we want. + */ +#ifdef FORCE_MACHINE +# undef MACHINE +# define MACHINE FORCE_MACHINE +#endif + +extern SearchPath *parseIncPath; + +/* + * For compatibility with the POSIX version of MAKEFLAGS that includes + * all the options with out -, convert flags to -f -l -a -g -s. + */ +static char * +explode(const char *flags) +{ + size_t len; + char *nf, *st; + const char *f; + + if (flags == NULL) + return NULL; + + for (f = flags; *f; f++) + if (!ch_isalpha(*f)) + break; + + if (*f) + return bmake_strdup(flags); + + len = strlen(flags); + st = nf = bmake_malloc(len * 3 + 1); + while (*flags) { + *nf++ = '-'; + *nf++ = *flags++; + *nf++ = ' '; + } + *nf = '\0'; + return st; +} + +static void +parse_debug_option_F(const char *modules) +{ + const char *mode; + size_t len; + char *fname; + + if (opts.debug_file != stdout && opts.debug_file != stderr) + fclose(opts.debug_file); + + if (*modules == '+') { + modules++; + mode = "a"; + } else + mode = "w"; + + if (strcmp(modules, "stdout") == 0) { + opts.debug_file = stdout; + return; + } + if (strcmp(modules, "stderr") == 0) { + opts.debug_file = stderr; + return; + } + + len = strlen(modules); + fname = bmake_malloc(len + 20); + memcpy(fname, modules, len + 1); + + /* Let the filename be modified by the pid */ + if (strcmp(fname + len - 3, ".%d") == 0) + snprintf(fname + len - 2, 20, "%d", getpid()); + + opts.debug_file = fopen(fname, mode); + if (!opts.debug_file) { + fprintf(stderr, "Cannot open debug file %s\n", + fname); + usage(); + } + free(fname); +} + +static void +parse_debug_options(const char *argvalue) +{ + const char *modules; + + for (modules = argvalue; *modules; ++modules) { + switch (*modules) { + case '0': /* undocumented, only intended for tests */ + opts.debug &= DEBUG_LINT; + break; + case 'A': + opts.debug = ~(0|DEBUG_LINT); + break; + case 'a': + opts.debug |= DEBUG_ARCH; + break; + case 'C': + opts.debug |= DEBUG_CWD; + break; + case 'c': + opts.debug |= DEBUG_COND; + break; + case 'd': + opts.debug |= DEBUG_DIR; + break; + case 'e': + opts.debug |= DEBUG_ERROR; + break; + case 'f': + opts.debug |= DEBUG_FOR; + break; + case 'g': + if (modules[1] == '1') { + opts.debug |= DEBUG_GRAPH1; + ++modules; + } + else if (modules[1] == '2') { + opts.debug |= DEBUG_GRAPH2; + ++modules; + } + else if (modules[1] == '3') { + opts.debug |= DEBUG_GRAPH3; + ++modules; + } + break; + case 'h': + opts.debug |= DEBUG_HASH; + break; + case 'j': + opts.debug |= DEBUG_JOB; + break; + case 'L': + opts.debug |= DEBUG_LINT; + break; + case 'l': + opts.debug |= DEBUG_LOUD; + break; + case 'M': + opts.debug |= DEBUG_META; + break; + case 'm': + opts.debug |= DEBUG_MAKE; + break; + case 'n': + opts.debug |= DEBUG_SCRIPT; + break; + case 'p': + opts.debug |= DEBUG_PARSE; + break; + case 's': + opts.debug |= DEBUG_SUFF; + break; + case 't': + opts.debug |= DEBUG_TARG; + break; + case 'V': + opts.debugVflag = TRUE; + break; + case 'v': + opts.debug |= DEBUG_VAR; + break; + case 'x': + opts.debug |= DEBUG_SHELL; + break; + case 'F': + parse_debug_option_F(modules + 1); + goto debug_setbuf; + default: + (void)fprintf(stderr, + "%s: illegal argument to d option -- %c\n", + progname, *modules); + usage(); + } + } +debug_setbuf: + /* + * Make the debug_file unbuffered, and make + * stdout line buffered (unless debugfile == stdout). + */ + setvbuf(opts.debug_file, NULL, _IONBF, 0); + if (opts.debug_file != stdout) { + setvbuf(stdout, NULL, _IOLBF, 0); + } +} + +/* + * does path contain any relative components + */ +static Boolean +is_relpath(const char *path) +{ + const char *cp; + + if (path[0] != '/') + return TRUE; + cp = path; + while ((cp = strstr(cp, "/.")) != NULL) { + cp += 2; + if (cp[0] == '/' || cp[0] == '\0') + return TRUE; + else if (cp[0] == '.') { + if (cp[1] == '/' || cp[1] == '\0') + return TRUE; + } + } + return FALSE; +} + +static void +MainParseArgChdir(const char *argvalue) +{ + struct stat sa, sb; + + if (chdir(argvalue) == -1) { + (void)fprintf(stderr, "%s: chdir %s: %s\n", + progname, argvalue, strerror(errno)); + exit(1); + } + if (getcwd(curdir, MAXPATHLEN) == NULL) { + (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno)); + exit(2); + } + if (!is_relpath(argvalue) && + stat(argvalue, &sa) != -1 && + stat(curdir, &sb) != -1 && + sa.st_ino == sb.st_ino && + sa.st_dev == sb.st_dev) + strncpy(curdir, argvalue, MAXPATHLEN); + ignorePWD = TRUE; +} + +static void +MainParseArgJobsInternal(const char *argvalue) +{ + if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) { + (void)fprintf(stderr, + "%s: internal error -- J option malformed (%s)\n", + progname, argvalue); + usage(); + } + if ((fcntl(jp_0, F_GETFD, 0) < 0) || + (fcntl(jp_1, F_GETFD, 0) < 0)) { +#if 0 + (void)fprintf(stderr, + "%s: ###### warning -- J descriptors were closed!\n", + progname); + exit(2); +#endif + jp_0 = -1; + jp_1 = -1; + opts.compatMake = TRUE; + } else { + Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + } +} + +static void +MainParseArgJobs(const char *argvalue) +{ + char *p; + + forceJobs = TRUE; + opts.maxJobs = (int)strtol(argvalue, &p, 0); + if (*p != '\0' || opts.maxJobs < 1) { + (void)fprintf(stderr, + "%s: illegal argument to -j -- must be positive integer!\n", + progname); + exit(1); /* XXX: why not 2? */ + } + Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL); + maxJobTokens = opts.maxJobs; +} + +static void +MainParseArgSysInc(const char *argvalue) +{ + /* look for magic parent directory search string */ + if (strncmp(".../", argvalue, 4) == 0) { + char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4); + if (found_path == NULL) + return; + (void)Dir_AddDir(sysIncPath, found_path); + free(found_path); + } else { + (void)Dir_AddDir(sysIncPath, argvalue); + } + Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); +} + +static Boolean +MainParseArg(char c, const char *argvalue) +{ + switch (c) { + case '\0': + break; + case 'B': + opts.compatMake = TRUE; + Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); + Var_Set(MAKE_MODE, "compat", VAR_GLOBAL); + break; + case 'C': + MainParseArgChdir(argvalue); + break; + case 'D': + if (argvalue[0] == '\0') return FALSE; + Var_Set(argvalue, "1", VAR_GLOBAL); + Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'I': + Parse_AddIncludeDir(argvalue); + Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'J': + MainParseArgJobsInternal(argvalue); + break; + case 'N': + opts.noExecute = TRUE; + opts.noRecursiveExecute = TRUE; + Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); + break; + case 'S': + opts.keepgoing = FALSE; + Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); + break; + case 'T': + tracefile = bmake_strdup(argvalue); + Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'V': + case 'v': + opts.printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS; + Lst_Append(opts.variables, bmake_strdup(argvalue)); + /* XXX: Why always -V? */ + Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'W': + opts.parseWarnFatal = TRUE; + break; + case 'X': + opts.varNoExportEnv = TRUE; + Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); + break; + case 'd': + /* If '-d-opts' don't pass to children */ + if (argvalue[0] == '-') + argvalue++; + else { + Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + } + parse_debug_options(argvalue); + break; + case 'e': + opts.checkEnvFirst = TRUE; + Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); + break; + case 'f': + Lst_Append(opts.makefiles, bmake_strdup(argvalue)); + break; + case 'i': + opts.ignoreErrors = TRUE; + Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); + break; + case 'j': + MainParseArgJobs(argvalue); + break; + case 'k': + opts.keepgoing = TRUE; + Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); + break; + case 'm': + MainParseArgSysInc(argvalue); + break; + case 'n': + opts.noExecute = TRUE; + Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); + break; + case 'q': + opts.queryFlag = TRUE; + /* Kind of nonsensical, wot? */ + Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); + break; + case 'r': + opts.noBuiltins = TRUE; + Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); + break; + case 's': + opts.beSilent = TRUE; + Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); + break; + case 't': + opts.touchFlag = TRUE; + Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); + break; + case 'w': + opts.enterFlag = TRUE; + Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL); + break; + default: + case '?': + usage(); + } + return TRUE; +} + +/* Parse the given arguments. Called from main() and from + * Main_ParseArgLine() when the .MAKEFLAGS target is used. + * + * The arguments must be treated as read-only and will be freed after the + * call. + * + * XXX: Deal with command line overriding .MAKEFLAGS in makefile */ +static void +MainParseArgs(int argc, char **argv) +{ + char c; + int arginc; + char *argvalue; + char *optscan; + Boolean 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; + optscan = NULL; + while (argc > 1) { + const char *optspec; + if (!inOption) + optscan = argv[1]; + c = *optscan++; + arginc = 0; + if (inOption) { + if (c == '\0') { + ++argv; + --argc; + inOption = FALSE; + continue; + } + } else { + if (c != '-' || dashDash) + break; + inOption = TRUE; + c = *optscan++; + } + /* '-' found at some earlier point */ + optspec = strchr(optspecs, c); + if (c != '\0' && optspec != NULL && optspec[1] == ':') { + /* - found, and should have an arg */ + inOption = FALSE; + arginc = 1; + argvalue = optscan; + if (*argvalue == '\0') { + if (argc < 3) + goto noarg; + argvalue = argv[2]; + arginc = 2; + } + } else { + argvalue = NULL; + } + switch (c) { + case '\0': + arginc = 1; + inOption = FALSE; + break; + case '-': + dashDash = TRUE; + break; + default: + if (!MainParseArg(c, argvalue)) + goto noarg; + } + argv += arginc; + argc -= arginc; + } + + oldVars = TRUE; + + /* + * See if the rest of the arguments are variable assignments and + * perform them if so. Else take them to be targets and stuff them + * on the end of the "create" list. + */ + for (; argc > 1; ++argv, --argc) { + VarAssign var; + if (Parse_IsVar(argv[1], &var)) { + Parse_DoVar(&var, VAR_CMDLINE); + } else { + if (!*argv[1]) + Punt("illegal (null) argument."); + if (*argv[1] == '-' && !dashDash) + goto rearg; + Lst_Append(opts.create, bmake_strdup(argv[1])); + } + } + + return; +noarg: + (void)fprintf(stderr, "%s: option requires an argument -- %c\n", + progname, c); + usage(); +} + +/* Break a line of arguments into words and parse them. + * + * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and + * by main() when reading the MAKEFLAGS environment variable. */ +void +Main_ParseArgLine(const char *line) +{ + Words words; + void *p1; + const char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1); + char *buf; + + if (line == NULL) + return; + for (; *line == ' '; ++line) + continue; + if (!*line) + return; + +#ifndef POSIX + { + /* + * $MAKE may simply be naming the make(1) binary + */ + char *cp; + + if (!(cp = strrchr(line, '/'))) + cp = line; + if ((cp = strstr(cp, "make")) && + strcmp(cp, "make") == 0) + return; + } +#endif + buf = str_concat3(argv0, " ", line); + free(p1); + + words = Str_Words(buf, TRUE); + if (words.words == NULL) { + Error("Unterminated quoted string [%s]", buf); + free(buf); + return; + } + free(buf); + MainParseArgs((int)words.len, words.words); + + Words_Free(words); +} + +Boolean +Main_SetObjdir(const char *fmt, ...) +{ + struct stat sb; + char *path; + char buf[MAXPATHLEN + 1]; + char buf2[MAXPATHLEN + 1]; + Boolean rc = FALSE; + va_list ap; + + va_start(ap, fmt); + vsnprintf(path = buf, MAXPATHLEN, fmt, ap); + va_end(ap); + + if (path[0] != '/') { + snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path); + path = buf2; + } + + /* look for the directory and try to chdir there */ + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + /* if not .CURDIR it must be writable */ + if ((strcmp(path, curdir) != 0 && access(path, W_OK) != 0) || + chdir(path)) { + (void)fprintf(stderr, "make warning: %s: %s.\n", + path, strerror(errno)); + } else { + snprintf(objdir, sizeof objdir, "%s", path); + Var_Set(".OBJDIR", objdir, VAR_GLOBAL); + setenv("PWD", objdir, 1); + Dir_InitDot(); + purge_cached_realpaths(); + rc = TRUE; + if (opts.enterFlag && strcmp(objdir, curdir) != 0) + enterFlagObj = TRUE; + } + } + + return rc; +} + +static Boolean +Main_SetVarObjdir(const char *var, const char *suffix) +{ + void *path_freeIt; + const char *path = Var_Value(var, VAR_CMDLINE, &path_freeIt); + const char *xpath; + char *xpath_freeIt; + + if (path == NULL || path[0] == '\0') { + bmake_free(path_freeIt); + return FALSE; + } + + /* expand variable substitutions */ + xpath = path; + xpath_freeIt = NULL; + if (strchr(path, '$') != 0) { + (void)Var_Subst(path, VAR_GLOBAL, VARE_WANTRES, &xpath_freeIt); + /* TODO: handle errors */ + xpath = xpath_freeIt; + } + + (void)Main_SetObjdir("%s%s", xpath, suffix); + + bmake_free(xpath_freeIt); + bmake_free(path_freeIt); + return TRUE; +} + +/* Read and parse the makefile. + * Return TRUE if reading the makefile succeeded. */ +static int +ReadMakefileSucceeded(void *fname, void *unused) +{ + return ReadMakefile(fname) == 0; +} + +int +str2Lst_Append(StringList *lp, char *str, const char *sep) +{ + char *cp; + int n; + + if (!sep) + sep = " \t"; + + for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) { + Lst_Append(lp, cp); + n++; + } + return n; +} + +#ifdef SIGINFO +/*ARGSUSED*/ +static void +siginfo(int signo MAKE_ATTR_UNUSED) +{ + char dir[MAXPATHLEN]; + char str[2 * MAXPATHLEN]; + int len; + if (getcwd(dir, sizeof(dir)) == NULL) + return; + len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir); + if (len > 0) + (void)write(STDERR_FILENO, str, (size_t)len); +} +#endif + +/* + * Allow makefiles some control over the mode we run in. + */ +void +MakeMode(const char *mode) +{ + char *mode_freeIt = NULL; + + if (mode == NULL) { + (void)Var_Subst("${" MAKE_MODE ":tl}", + VAR_GLOBAL, VARE_WANTRES, &mode_freeIt); + /* TODO: handle errors */ + mode = mode_freeIt; + } + + if (mode[0] != '\0') { + if (strstr(mode, "compat")) { + opts.compatMake = TRUE; + forceJobs = FALSE; + } +#if USE_META + if (strstr(mode, "meta")) + meta_mode_init(mode); +#endif + } + + free(mode_freeIt); +} + +static void +PrintVar(const char *varname, Boolean expandVars) +{ + if (strchr(varname, '$')) { + char *evalue; + (void)Var_Subst(varname, VAR_GLOBAL, VARE_WANTRES, &evalue); + /* TODO: handle errors */ + printf("%s\n", evalue); + bmake_free(evalue); + + } else if (expandVars) { + char *expr = str_concat3("${", varname, "}"); + char *evalue; + (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &evalue); + /* TODO: handle errors */ + free(expr); + printf("%s\n", evalue); + bmake_free(evalue); + + } else { + void *freeIt; + const char *value = Var_Value(varname, VAR_GLOBAL, &freeIt); + printf("%s\n", value ? value : ""); + bmake_free(freeIt); + } +} + +static void +doPrintVars(void) +{ + StringListNode *ln; + Boolean expandVars; + + if (opts.printVars == EXPAND_VARS) + expandVars = TRUE; + else if (opts.debugVflag) + expandVars = FALSE; + else + expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE); + + for (ln = opts.variables->first; ln != NULL; ln = ln->next) { + const char *varname = ln->datum; + PrintVar(varname, expandVars); + } +} + +static Boolean +runTargets(void) +{ + GNodeList *targs; /* target nodes to create -- passed to Make_Init */ + Boolean outOfDate; /* FALSE if all targets up to date */ + + /* + * Have now read the entire graph and need to make a list of + * targets to create. If none was given on the command line, + * we consult the parsing module to find the main target(s) + * to create. + */ + if (Lst_IsEmpty(opts.create)) + targs = Parse_MainName(); + else + targs = Targ_FindList(opts.create); + + if (!opts.compatMake) { + /* + * Initialize job module before traversing the graph + * now that any .BEGIN and .END targets have been read. + * This is done only if the -q flag wasn't given + * (to prevent the .BEGIN from being executed should + * it exist). + */ + if (!opts.queryFlag) { + Job_Init(); + jobsRunning = TRUE; + } + + /* Traverse the graph, checking on all the targets */ + outOfDate = Make_Run(targs); + } else { + /* + * Compat_Init will take care of creating all the + * targets as well as initializing the module. + */ + Compat_Run(targs); + outOfDate = FALSE; + } + Lst_Free(targs); + return outOfDate; +} + +/* + * Set up the .TARGETS variable to contain the list of targets to be + * created. If none specified, make the variable empty -- the parser + * will fill the thing in with the default or .MAIN target. + */ +static void +InitVarTargets(void) +{ + StringListNode *ln; + + if (Lst_IsEmpty(opts.create)) { + Var_Set(".TARGETS", "", VAR_GLOBAL); + return; + } + + for (ln = opts.create->first; ln != NULL; ln = ln->next) { + char *name = ln->datum; + Var_Append(".TARGETS", name, VAR_GLOBAL); + } +} + +static void +InitRandom(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + srandom((unsigned int)(tv.tv_sec + tv.tv_usec)); +} + +static const char * +init_machine(const struct utsname *utsname) +{ +#ifdef FORCE_MACHINE + const char *machine = FORCE_MACHINE; +#else + const char *machine = getenv("MACHINE"); +#endif + if (machine != NULL) + return machine; + +#ifdef MAKE_NATIVE + return utsname->machine; +#else +#ifdef MAKE_MACHINE + return MAKE_MACHINE; +#else + return "unknown"; +#endif +#endif +} + +static const char * +init_machine_arch(void) +{ + const char *env = getenv("MACHINE_ARCH"); + if (env != NULL) + return env; + +#if defined(MAKE_NATIVE) && defined(CTL_HW) + { + struct utsname utsname; + static char machine_arch_buf[sizeof(utsname.machine)]; + const int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; + size_t len = sizeof(machine_arch_buf); + + if (sysctl(mib, __arraycount(mib), machine_arch_buf, + &len, NULL, 0) < 0) { + (void)fprintf(stderr, "%s: sysctl failed (%s).\n", progname, + strerror(errno)); + exit(2); + } + + return machine_arch_buf; + } +#else +#ifndef MACHINE_ARCH +#ifdef MAKE_MACHINE_ARCH + return MAKE_MACHINE_ARCH; +#else + return "unknown"; +#endif +#else + return MACHINE_ARCH; +#endif +#endif +} + +#ifndef NO_PWD_OVERRIDE +/* + * All this code is so that we know where we are when we start up + * on a different machine with pmake. + * + * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX + * since the value of curdir can vary depending on how we got + * here. Ie sitting at a shell prompt (shell that provides $PWD) + * or via subdir.mk in which case its likely a shell which does + * not provide it. + * + * So, to stop it breaking this case only, we ignore PWD if + * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a variable expression. + */ +static void +HandlePWD(const struct stat *curdir_st) +{ + char *pwd; + void *prefix_freeIt, *makeobjdir_freeIt; + const char *makeobjdir; + struct stat pwd_st; + + if (ignorePWD || (pwd = getenv("PWD")) == NULL) + return; + + if (Var_Value("MAKEOBJDIRPREFIX", VAR_CMDLINE, &prefix_freeIt) != NULL) { + bmake_free(prefix_freeIt); + return; + } + + makeobjdir = Var_Value("MAKEOBJDIR", VAR_CMDLINE, &makeobjdir_freeIt); + if (makeobjdir != NULL && strchr(makeobjdir, '$') != NULL) + goto ignore_pwd; + + if (stat(pwd, &pwd_st) == 0 && + curdir_st->st_ino == pwd_st.st_ino && + curdir_st->st_dev == pwd_st.st_dev) + (void)strncpy(curdir, pwd, MAXPATHLEN); + +ignore_pwd: + bmake_free(makeobjdir_freeIt); +} +#endif + +/* + * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, + * MAKEOBJDIR is set in the environment, try only that value + * and fall back to .CURDIR if it does not exist. + * + * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE, + * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none + * of these paths exist, just use .CURDIR. + */ +static void +InitObjdir(const char *machine, const char *machine_arch) +{ + Dir_InitDir(curdir); + (void)Main_SetObjdir("%s", curdir); + + if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) && + !Main_SetVarObjdir("MAKEOBJDIR", "") && + !Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) && + !Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) && + !Main_SetObjdir("%s", _PATH_OBJDIR)) + (void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir); +} + +/* get rid of resource limit on file descriptors */ +static void +UnlimitFiles(void) +{ +#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && + rl.rlim_cur != rl.rlim_max) { + rl.rlim_cur = rl.rlim_max; + (void)setrlimit(RLIMIT_NOFILE, &rl); + } +#endif +} + +static void +CmdOpts_Init(void) +{ + opts.compatMake = FALSE; /* No compat mode */ + opts.debug = 0; /* No debug verbosity, please. */ + /* opts.debug_file has been initialized earlier */ + opts.debugVflag = FALSE; + opts.checkEnvFirst = FALSE; + opts.makefiles = Lst_New(); + opts.ignoreErrors = FALSE; /* Pay attention to non-zero returns */ + opts.maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */ + opts.keepgoing = FALSE; /* Stop on error */ + opts.noRecursiveExecute = FALSE; /* Execute all .MAKE targets */ + opts.noExecute = FALSE; /* Execute all commands */ + opts.queryFlag = FALSE; /* This is not just a check-run */ + opts.noBuiltins = FALSE; /* Read the built-in rules */ + opts.beSilent = FALSE; /* Print commands as executed */ + opts.touchFlag = FALSE; /* Actually update targets */ + opts.printVars = 0; + opts.variables = Lst_New(); + opts.parseWarnFatal = FALSE; + opts.enterFlag = FALSE; + opts.varNoExportEnv = FALSE; + opts.create = Lst_New(); +} + +/* Initialize MAKE and .MAKE to the path of the executable, so that it can be + * found by execvp(3) and the shells, even after a chdir. + * + * If it's a relative path and contains a '/', resolve it to an absolute path. + * Otherwise keep it as is, assuming it will be found in the PATH. */ +static void +InitVarMake(const char *argv0) +{ + const char *make = argv0; + + if (argv0[0] != '/' && strchr(argv0, '/') != NULL) { + char pathbuf[MAXPATHLEN]; + const char *abs = cached_realpath(argv0, pathbuf); + struct stat st; + if (abs != NULL && abs[0] == '/' && stat(make, &st) == 0) + make = abs; + } + + Var_Set("MAKE", make, VAR_GLOBAL); + Var_Set(".MAKE", make, VAR_GLOBAL); +} + +static void +InitDefSysIncPath(char *syspath) +{ + static char defsyspath[] = _PATH_DEFSYSPATH; + char *start, *cp; + + /* + * If no user-supplied system path was given (through the -m option) + * add the directories from the DEFSYSPATH (more than one may be given + * as dir1:...:dirn) to the system include path. + */ + /* XXX: mismatch: the -m option sets sysIncPath, not syspath */ + if (syspath == NULL || syspath[0] == '\0') + syspath = defsyspath; + else + syspath = bmake_strdup(syspath); + + for (start = syspath; *start != '\0'; start = cp) { + for (cp = start; *cp != '\0' && *cp != ':'; cp++) + continue; + if (*cp == ':') { + *cp++ = '\0'; + } + /* look for magic parent directory search string */ + if (strncmp(".../", start, 4) != 0) { + (void)Dir_AddDir(defSysIncPath, start); + } else { + char *dir = Dir_FindHereOrAbove(curdir, start + 4); + if (dir != NULL) { + (void)Dir_AddDir(defSysIncPath, dir); + free(dir); + } + } + } + + if (syspath != defsyspath) + free(syspath); +} + +static void +ReadBuiltinRules(void) +{ + StringList *sysMkPath = Lst_New(); + Dir_Expand(_PATH_DEFSYSMK, + Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath, + sysMkPath); + if (Lst_IsEmpty(sysMkPath)) + Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK); + if (!Lst_ForEachUntil(sysMkPath, ReadMakefileSucceeded, NULL)) + Fatal("%s: cannot open %s.", progname, + (char *)sysMkPath->first->datum); + /* XXX: sysMkPath is not freed */ +} + +static void +InitMaxJobs(void) +{ + char *value; + int n; + + if (forceJobs || opts.compatMake || + !Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) + return; + + (void)Var_Subst("${.MAKE.JOBS}", VAR_GLOBAL, VARE_WANTRES, &value); + /* TODO: handle errors */ + n = (int)strtol(value, NULL, 0); + if (n < 1) { + (void)fprintf(stderr, + "%s: illegal value for .MAKE.JOBS " + "-- must be positive integer!\n", + progname); + exit(1); + } + + if (n != opts.maxJobs) { + Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); + Var_Append(MAKEFLAGS, value, VAR_GLOBAL); + } + + opts.maxJobs = n; + maxJobTokens = opts.maxJobs; + forceJobs = TRUE; + free(value); +} + +/* + * For compatibility, look at the directories in the VPATH variable + * and add them to the search path, if the variable is defined. The + * variable's value is in the same format as the PATH environment + * variable, i.e. ::... + */ +static void +InitVpath(void) +{ + char *vpath, savec, *path; + if (!Var_Exists("VPATH", VAR_CMDLINE)) + return; + + (void)Var_Subst("${VPATH}", VAR_CMDLINE, VARE_WANTRES, &vpath); + /* TODO: handle errors */ + path = vpath; + do { + char *cp; + /* skip to end of directory */ + for (cp = path; *cp != ':' && *cp != '\0'; cp++) + continue; + /* Save terminator character so know when to stop */ + savec = *cp; + *cp = '\0'; + /* Add directory to search path */ + (void)Dir_AddDir(dirSearchPath, path); + *cp = savec; + path = cp + 1; + } while (savec == ':'); + free(vpath); +} + +static void +ReadMakefiles(void) +{ + if (opts.makefiles->first != NULL) { + StringListNode *ln; + + for (ln = opts.makefiles->first; ln != NULL; ln = ln->next) { + if (ReadMakefile(ln->datum) != 0) + Fatal("%s: cannot open %s.", + progname, (char *)ln->datum); + } + } else { + char *p1; + (void)Var_Subst("${" MAKEFILE_PREFERENCE "}", + VAR_CMDLINE, VARE_WANTRES, &p1); + /* TODO: handle errors */ + (void)str2Lst_Append(opts.makefiles, p1, NULL); + (void)Lst_ForEachUntil(opts.makefiles, + ReadMakefileSucceeded, NULL); + free(p1); + } +} + +static void +CleanUp(void) +{ +#ifdef CLEANUP + Lst_Destroy(opts.variables, free); + Lst_Free(opts.makefiles); /* don't free, may be used in GNodes */ + Lst_Destroy(opts.create, free); +#endif + + /* print the graph now it's been processed if the user requested it */ + if (DEBUG(GRAPH2)) + Targ_PrintGraph(2); + + Trace_Log(MAKEEND, 0); + + if (enterFlagObj) + printf("%s: Leaving directory `%s'\n", progname, objdir); + if (opts.enterFlag) + printf("%s: Leaving directory `%s'\n", progname, curdir); + +#ifdef USE_META + meta_finish(); +#endif + Suff_End(); + Targ_End(); + Arch_End(); + Var_End(); + Parse_End(); + Dir_End(); + Job_End(); + Trace_End(); +} + +/*- + * main -- + * The main function, for obvious reasons. Initializes variables + * and a few modules, then parses the arguments give it in the + * environment and on the command line. Reads the system makefile + * followed by either Makefile, makefile or the file given by the + * -f argument. Sets the .MAKEFLAGS PMake variable based on all the + * flags it has received by then uses either the Make or the Compat + * module to create the initial list of targets. + * + * Results: + * If -q was given, exits -1 if anything was out-of-date. Else it exits + * 0. + * + * Side Effects: + * The program exits when done. Targets are created. etc. etc. etc. + */ +int +main(int argc, char **argv) +{ + Boolean outOfDate; /* FALSE if all targets up to date */ + struct stat sa; + const char *machine; + const char *machine_arch; + char *syspath = getenv("MAKESYSPATH"); + struct utsname utsname; + + /* default to writing debug to stderr */ + opts.debug_file = stderr; + +#ifdef SIGINFO + (void)bmake_signal(SIGINFO, siginfo); +#endif + + InitRandom(); + + if ((progname = strrchr(argv[0], '/')) != NULL) + progname++; + else + progname = argv[0]; + + UnlimitFiles(); + + if (uname(&utsname) == -1) { + (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, + strerror(errno)); + exit(2); + } + + /* + * Get the name of this type of MACHINE from utsname + * so we can share an executable for similar machines. + * (i.e. m68k: amiga hp300, mac68k, sun3, ...) + * + * Note that both MACHINE and MACHINE_ARCH are decided at + * run-time. + */ + machine = init_machine(&utsname); + machine_arch = init_machine_arch(); + + myPid = getpid(); /* remember this for vFork() */ + + /* + * Just in case MAKEOBJDIR wants us to do something tricky. + */ + Var_Init(); /* Initialize the lists of variables for + * parsing arguments */ + Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL); + Var_Set("MACHINE", machine, VAR_GLOBAL); + Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); +#ifdef MAKE_VERSION + Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL); +#endif + Var_Set(".newline", "\n", VAR_GLOBAL); /* handy for :@ loops */ + /* + * This is the traditional preference for makefiles. + */ +#ifndef MAKEFILE_PREFERENCE_LIST +# define MAKEFILE_PREFERENCE_LIST "makefile Makefile" +#endif + Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST, + VAR_GLOBAL); + Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL); + + CmdOpts_Init(); + allPrecious = FALSE; /* Remove targets when interrupted */ + deleteOnError = FALSE; /* Historical default behavior */ + jobsRunning = FALSE; + + maxJobTokens = opts.maxJobs; + ignorePWD = FALSE; + + /* + * Initialize the parsing, directory and variable modules to prepare + * for the reading of inclusion paths and variable settings on the + * command line + */ + + /* + * Initialize various variables. + * MAKE also gets this name, for compatibility + * .MAKEFLAGS gets set to the empty string just in case. + * MFLAGS also gets initialized empty, for compatibility. + */ + Parse_Init(); + InitVarMake(argv[0]); + Var_Set(MAKEFLAGS, "", VAR_GLOBAL); + Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL); + Var_Set("MFLAGS", "", VAR_GLOBAL); + Var_Set(".ALLTARGETS", "", VAR_GLOBAL); + /* some makefiles need to know this */ + Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMDLINE); + + /* + * Set some other useful macros + */ + { + char tmp[64], *ep; + + makelevel = ((ep = getenv(MAKE_LEVEL_ENV)) && *ep) ? atoi(ep) : 0; + if (makelevel < 0) + makelevel = 0; + snprintf(tmp, sizeof(tmp), "%d", makelevel); + Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL); + snprintf(tmp, sizeof(tmp), "%u", myPid); + Var_Set(".MAKE.PID", tmp, VAR_GLOBAL); + snprintf(tmp, sizeof(tmp), "%u", getppid()); + Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL); + } + if (makelevel > 0) { + char pn[1024]; + snprintf(pn, sizeof(pn), "%s[%d]", progname, makelevel); + progname = bmake_strdup(pn); + } + +#ifdef USE_META + meta_init(); +#endif + Dir_Init(); + + /* + * First snag any flags out of the MAKE environment variable. + * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's + * in a different format). + */ +#ifdef POSIX + { + char *p1 = explode(getenv("MAKEFLAGS")); + Main_ParseArgLine(p1); + free(p1); + } +#else + Main_ParseArgLine(getenv("MAKE")); +#endif + + /* + * Find where we are (now). + * We take care of PWD for the automounter below... + */ + if (getcwd(curdir, MAXPATHLEN) == NULL) { + (void)fprintf(stderr, "%s: getcwd: %s.\n", + progname, strerror(errno)); + exit(2); + } + + MainParseArgs(argc, argv); + + if (opts.enterFlag) + printf("%s: Entering directory `%s'\n", progname, curdir); + + /* + * Verify that cwd is sane. + */ + if (stat(curdir, &sa) == -1) { + (void)fprintf(stderr, "%s: %s: %s.\n", + progname, curdir, strerror(errno)); + exit(2); + } + +#ifndef NO_PWD_OVERRIDE + HandlePWD(&sa); +#endif + Var_Set(".CURDIR", curdir, VAR_GLOBAL); + + InitObjdir(machine, machine_arch); + + /* + * Initialize archive, target and suffix modules in preparation for + * parsing the makefile(s) + */ + Arch_Init(); + Targ_Init(); + Suff_Init(); + Trace_Init(tracefile); + + DEFAULT = NULL; + (void)time(&now); + + Trace_Log(MAKESTART, NULL); + + InitVarTargets(); + + InitDefSysIncPath(syspath); + + /* + * Read in the built-in rules first, followed by the specified + * makefiles, or the default makefile and Makefile, in that order, + * if no makefiles were given on the command line. + */ + if (!opts.noBuiltins) + ReadBuiltinRules(); + ReadMakefiles(); + + /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ + if (!opts.noBuiltins || !opts.printVars) { + /* ignore /dev/null and anything starting with "no" */ + (void)Var_Subst("${.MAKE.DEPENDFILE:N/dev/null:Nno*:T}", + VAR_CMDLINE, VARE_WANTRES, &makeDependfile); + if (makeDependfile[0] != '\0') { + /* TODO: handle errors */ + doing_depend = TRUE; + (void)ReadMakefile(makeDependfile); + doing_depend = FALSE; + } + } + + if (enterFlagObj) + printf("%s: Entering directory `%s'\n", progname, objdir); + + MakeMode(NULL); + + { + void *freeIt; + Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &freeIt), + VAR_GLOBAL); + bmake_free(freeIt); + + } + + InitMaxJobs(); + + /* + * Be compatible if user did not specify -j and did not explicitly + * turned compatibility on + */ + if (!opts.compatMake && !forceJobs) { + opts.compatMake = TRUE; + } + + if (!opts.compatMake) + Job_ServerStart(maxJobTokens, jp_0, jp_1); + DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", + jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0); + + if (!opts.printVars) + Main_ExportMAKEFLAGS(TRUE); /* initial export */ + + InitVpath(); + + /* + * 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(); + + /* + * Propagate attributes through :: dependency lists. + */ + Targ_Propagate(); + + /* print the initial graph, if the user requested it */ + if (DEBUG(GRAPH1)) + Targ_PrintGraph(1); + + /* print the values of any variables requested by the user */ + if (opts.printVars) { + doPrintVars(); + outOfDate = FALSE; + } else { + outOfDate = runTargets(); + } + + CleanUp(); + + if (DEBUG(LINT) && (errors > 0 || Parse_GetFatals() > 0)) + return 2; /* Not 1 so -q can distinguish error */ + return outOfDate ? 1 : 0; +} + +/* Open and parse the given makefile, with all its side effects. + * + * Results: + * 0 if ok. -1 if couldn't open file. + */ +static int +ReadMakefile(const char *fname) +{ + int fd; + char *name, *path = NULL; + + if (!strcmp(fname, "-")) { + Parse_File(NULL /*stdin*/, -1); + Var_Set("MAKEFILE", "", VAR_INTERNAL); + } else { + /* if we've chdir'd, rebuild the path name */ + if (strcmp(curdir, objdir) && *fname != '/') { + path = str_concat3(curdir, "/", fname); + fd = open(path, O_RDONLY); + if (fd != -1) { + fname = path; + goto found; + } + free(path); + + /* If curdir failed, try objdir (ala .depend) */ + path = str_concat3(objdir, "/", fname); + fd = open(path, O_RDONLY); + if (fd != -1) { + fname = path; + goto found; + } + } else { + fd = open(fname, O_RDONLY); + if (fd != -1) + goto found; + } + /* look in -I and system include directories. */ + name = Dir_FindFile(fname, parseIncPath); + if (!name) { + SearchPath *sysInc = Lst_IsEmpty(sysIncPath) + ? defSysIncPath : sysIncPath; + name = Dir_FindFile(fname, sysInc); + } + if (!name || (fd = open(name, O_RDONLY)) == -1) { + free(name); + free(path); + return -1; + } + fname = name; + /* + * set the MAKEFILE variable desired by System V fans -- the + * placement of the setting here means it gets set to the last + * makefile specified, as it is set by SysV make. + */ +found: + if (!doing_depend) + Var_Set("MAKEFILE", fname, VAR_INTERNAL); + Parse_File(fname, fd); + } + free(path); + return 0; +} + + + +/*- + * Cmd_Exec -- + * Execute the command in cmd, and return the output of that command + * in a string. In the output, newlines are replaced with spaces. + * + * Results: + * A string containing the output of the command, or the empty string. + * *errfmt returns a format string describing the command failure, + * if any, using a single %s conversion specification. + * + * Side Effects: + * The string must be freed by the caller. + */ +char * +Cmd_Exec(const char *cmd, const char **errfmt) +{ + const char *args[4]; /* Args for invoking the shell */ + int fds[2]; /* Pipe streams */ + int cpid; /* Child PID */ + int pid; /* PID from wait() */ + WAIT_T status; /* command exit status */ + Buffer buf; /* buffer to store the result */ + ssize_t bytes_read; + char *res; /* result */ + size_t res_len; + char *cp; + int savederr; /* saved errno */ + + *errfmt = NULL; + + if (!shellName) + Shell_Init(); + /* + * Set up arguments for shell + */ + args[0] = shellName; + args[1] = "-c"; + args[2] = cmd; + args[3] = NULL; + + /* + * Open a pipe for fetching its output + */ + if (pipe(fds) == -1) { + *errfmt = "Couldn't create pipe for \"%s\""; + goto bad; + } + + /* + * Fork + */ + switch (cpid = vFork()) { + case 0: + /* + * Close input side of pipe + */ + (void)close(fds[0]); + + /* + * Duplicate the output stream to the shell's output, then + * shut the extra thing down. Note we don't fetch the error + * stream...why not? Why? + */ + (void)dup2(fds[1], 1); + (void)close(fds[1]); + + Var_ExportVars(); + + (void)execv(shellPath, UNCONST(args)); + _exit(1); + /*NOTREACHED*/ + + case -1: + *errfmt = "Couldn't exec \"%s\""; + goto bad; + + default: + /* + * No need for the writing half + */ + (void)close(fds[1]); + + savederr = 0; + Buf_Init(&buf, 0); + + do { + char result[BUFSIZ]; + bytes_read = read(fds[0], result, sizeof(result)); + if (bytes_read > 0) + Buf_AddBytes(&buf, result, (size_t)bytes_read); + } + while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR)); + if (bytes_read == -1) + savederr = errno; + + /* + * Close the input side of the pipe. + */ + (void)close(fds[0]); + + /* + * Wait for the process to exit. + */ + while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) { + JobReapChild(pid, status, FALSE); + continue; + } + res_len = Buf_Len(&buf); + res = Buf_Destroy(&buf, FALSE); + + if (savederr != 0) + *errfmt = "Couldn't read shell's output for \"%s\""; + + if (WIFSIGNALED(status)) + *errfmt = "\"%s\" exited on a signal"; + else if (WEXITSTATUS(status) != 0) + *errfmt = "\"%s\" returned non-zero status"; + + /* Convert newlines to spaces. A final newline is just stripped */ + if (res_len > 0 && res[res_len - 1] == '\n') + res[res_len - 1] = '\0'; + for (cp = res; *cp != '\0'; cp++) + if (*cp == '\n') + *cp = ' '; + break; + } + return res; +bad: + return bmake_strdup(""); +} + +/* Print a printf-style error message. + * + * This error message has no consequences, in particular it does not affect + * the exit status. */ +void +Error(const char *fmt, ...) +{ + va_list ap; + FILE *err_file; + + err_file = opts.debug_file; + if (err_file == stdout) + err_file = stderr; + (void)fflush(stdout); + for (;;) { + va_start(ap, fmt); + fprintf(err_file, "%s: ", progname); + (void)vfprintf(err_file, fmt, ap); + va_end(ap); + (void)fprintf(err_file, "\n"); + (void)fflush(err_file); + if (err_file == stderr) + break; + err_file = stderr; + } + errors++; +} + +/* Produce a Fatal error message, then exit immediately. + * + * If jobs are running, wait for them to finish. */ +void +Fatal(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (jobsRunning) + Job_Wait(); + + (void)fflush(stdout); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + (void)fflush(stderr); + + PrintOnError(NULL, NULL); + + if (DEBUG(GRAPH2) || DEBUG(GRAPH3)) + Targ_PrintGraph(2); + Trace_Log(MAKEERROR, 0); + exit(2); /* Not 1 so -q can distinguish error */ +} + +/* Major exception once jobs are being created. + * Kills all jobs, prints a message and exits. */ +void +Punt(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + (void)fflush(stdout); + (void)fprintf(stderr, "%s: ", progname); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + (void)fflush(stderr); + + PrintOnError(NULL, NULL); + + DieHorribly(); +} + +/* Exit without giving a message. */ +void +DieHorribly(void) +{ + if (jobsRunning) + Job_AbortAll(); + if (DEBUG(GRAPH2)) + Targ_PrintGraph(2); + Trace_Log(MAKEERROR, 0); + exit(2); /* Not 1, so -q can distinguish error */ +} + +/* Called when aborting due to errors in child shell to signal abnormal exit. + * The program exits. + * Errors is the number of errors encountered in Make_Make. */ +void +Finish(int errs) +{ + if (dieQuietly(NULL, -1)) + exit(2); + Fatal("%d error%s", errs, errs == 1 ? "" : "s"); +} + +/* + * eunlink -- + * Remove a file carefully, avoiding directories. + */ +int +eunlink(const char *file) +{ + struct stat st; + + if (lstat(file, &st) == -1) + return -1; + + if (S_ISDIR(st.st_mode)) { + errno = EISDIR; + return -1; + } + return unlink(file); +} + +static void +write_all(int fd, const void *data, size_t n) +{ + const char *mem = data; + + while (n > 0) { + ssize_t written = write(fd, mem, n); + if (written == -1 && errno == EAGAIN) + continue; + if (written == -1) + break; + mem += written; + n -= (size_t)written; + } +} + +/* + * execDie -- + * Print why exec failed, avoiding stdio. + */ +void MAKE_ATTR_DEAD +execDie(const char *af, const char *av) +{ + Buffer buf; + + Buf_Init(&buf, 0); + Buf_AddStr(&buf, progname); + Buf_AddStr(&buf, ": "); + Buf_AddStr(&buf, af); + Buf_AddStr(&buf, "("); + Buf_AddStr(&buf, av); + Buf_AddStr(&buf, ") failed ("); + Buf_AddStr(&buf, strerror(errno)); + Buf_AddStr(&buf, ")\n"); + + write_all(STDERR_FILENO, Buf_GetAll(&buf, NULL), Buf_Len(&buf)); + + Buf_Destroy(&buf, TRUE); + _exit(1); +} + +/* + * usage -- + * exit with usage message + */ +static void +usage(void) +{ + char *p; + if ((p = strchr(progname, '[')) != NULL) + *p = '\0'; + + (void)fprintf(stderr, +"usage: %s [-BeikNnqrstWwX] \n" +" [-C directory] [-D variable] [-d flags] [-f makefile]\n" +" [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n" +" [-V variable] [-v variable] [variable=value] [target ...]\n", + progname); + exit(2); +} + +/* + * realpath(3) can get expensive, cache results... + */ +static GNode *cached_realpaths = NULL; + +static GNode * +get_cached_realpaths(void) +{ + + if (!cached_realpaths) { + cached_realpaths = Targ_NewGN("Realpath"); +#ifndef DEBUG_REALPATH_CACHE + cached_realpaths->flags = INTERNAL; +#endif + } + + return cached_realpaths; +} + +/* purge any relative paths */ +static void +purge_cached_realpaths(void) +{ + GNode *cache = get_cached_realpaths(); + HashEntry *he, *nhe; + HashIter hi; + + HashIter_Init(&hi, &cache->context); + he = HashIter_Next(&hi); + while (he != NULL) { + nhe = HashIter_Next(&hi); + if (he->key[0] != '/') { + if (DEBUG(DIR)) + fprintf(stderr, "cached_realpath: purging %s\n", he->key); + HashTable_DeleteEntry(&cache->context, he); + } + he = nhe; + } +} + +char * +cached_realpath(const char *pathname, char *resolved) +{ + GNode *cache; + const char *rp; + void *freeIt; + + if (!pathname || !pathname[0]) + return NULL; + + cache = get_cached_realpaths(); + + if ((rp = Var_Value(pathname, cache, &freeIt)) != NULL) { + /* a hit */ + strlcpy(resolved, rp, MAXPATHLEN); + } else if ((rp = realpath(pathname, resolved)) != NULL) { + Var_Set(pathname, rp, cache); + } /* else should we negative-cache? */ + + bmake_free(freeIt); + return rp ? resolved : NULL; +} + +/* + * Return true if we should die without noise. + * For example our failing child was a sub-make + * or failure happend elsewhere. + */ +int +dieQuietly(GNode *gn, int bf) +{ + static int quietly = -1; + + if (quietly < 0) { + if (DEBUG(JOB) || !getBoolean(".MAKE.DIE_QUIETLY", TRUE)) + quietly = 0; + else if (bf >= 0) + quietly = bf; + else + quietly = gn != NULL ? ((gn->type & (OP_MAKE)) != 0) : 0; + } + return quietly; +} + +static void +SetErrorVars(GNode *gn) +{ + StringListNode *ln; + + /* + * We can print this even if there is no .ERROR target. + */ + Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL); + Var_Delete(".ERROR_CMD", VAR_GLOBAL); + + for (ln = gn->commands->first; ln != NULL; ln = ln->next) { + const char *cmd = ln->datum; + + if (cmd == NULL) + break; + Var_Append(".ERROR_CMD", cmd, VAR_GLOBAL); + } +} + +void +PrintOnError(GNode *gn, const char *s) +{ + static GNode *en = NULL; + const char *expr; + char *cp; + + if (DEBUG(HASH)) { + Targ_Stats(); + Var_Stats(); + } + + /* we generally want to keep quiet if a sub-make died */ + if (dieQuietly(gn, -1)) + return; + + if (s) + printf("%s", s); + + printf("\n%s: stopped in %s\n", progname, curdir); + + if (en) + return; /* we've been here! */ + if (gn) + SetErrorVars(gn); + expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}"; + (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp); + /* TODO: handle errors */ + printf("%s", cp); + free(cp); + fflush(stdout); + + /* + * Finally, see if there is a .ERROR target, and run it if so. + */ + en = Targ_FindNode(".ERROR"); + if (en) { + en->type |= OP_SPECIAL; + Compat_Make(en, en); + } +} + +void +Main_ExportMAKEFLAGS(Boolean first) +{ + static Boolean once = TRUE; + const char *expr; + char *s; + + if (once != first) + return; + once = FALSE; + + expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}"; + (void)Var_Subst(expr, VAR_CMDLINE, VARE_WANTRES, &s); + /* TODO: handle errors */ + if (s[0] != '\0') { +#ifdef POSIX + setenv("MAKEFLAGS", s, 1); +#else + setenv("MAKE", s, 1); +#endif + } +} + +char * +getTmpdir(void) +{ + static char *tmpdir = NULL; + + if (!tmpdir) { + struct stat st; + + /* + * Honor $TMPDIR but only if it is valid. + * Ensure it ends with /. + */ + (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, + VARE_WANTRES, &tmpdir); + /* TODO: handle errors */ + if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) { + free(tmpdir); + tmpdir = bmake_strdup(_PATH_TMP); + } + } + return tmpdir; +} + +/* + * Create and open a temp file using "pattern". + * If out_fname is provided, set it to a copy of the filename created. + * Otherwise unlink the file once open. + */ +int +mkTempFile(const char *pattern, char **out_fname) +{ + static char *tmpdir = NULL; + char tfile[MAXPATHLEN]; + int fd; + + if (pattern != NULL) + pattern = TMPPAT; + if (tmpdir == NULL) + tmpdir = getTmpdir(); + if (pattern[0] == '/') { + snprintf(tfile, sizeof(tfile), "%s", pattern); + } else { + snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern); + } + if ((fd = mkstemp(tfile)) < 0) + Punt("Could not create temporary file %s: %s", tfile, strerror(errno)); + if (out_fname) { + *out_fname = bmake_strdup(tfile); + } else { + unlink(tfile); /* we just want the descriptor */ + } + return fd; +} + +/* + * Convert a string representation of a boolean. + * Anything that looks like "No", "False", "Off", "0" etc, + * is FALSE, otherwise TRUE. + */ +Boolean +s2Boolean(const char *s, Boolean bf) +{ + switch(s[0]) { + case '\0': /* not set - the default wins */ + break; + case '0': + case 'F': + case 'f': + case 'N': + case 'n': + return FALSE; + case 'O': + case 'o': + return s[1] != 'F' && s[1] != 'f'; + default: + return TRUE; + } + return bf; +} + +/* + * Return a Boolean 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. + */ +Boolean +getBoolean(const char *varname, Boolean fallback) +{ + char *expr = str_concat3("${", varname, ":U}"); + char *value; + Boolean res; + + (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &value); + /* TODO: handle errors */ + res = s2Boolean(value, fallback); + free(value); + free(expr); + return res; +} Property changes on: vendor/NetBSD/bmake/20201101/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make-bootstrap.sh.in =================================================================== --- vendor/NetBSD/bmake/20201101/make-bootstrap.sh.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/make-bootstrap.sh.in (revision 367461) @@ -0,0 +1,94 @@ +#!/bin/sh + +set -e + +srcdir=@srcdir@ + +DEFAULT_SYS_PATH="@default_sys_path@" + +case "@use_meta@" in +yes) XDEFS="-DUSE_META ${XDEFS}";; +esac + +CC="@CC@" +CFLAGS="@CFLAGS@ -I. -I${srcdir} @DEFS@ @CPPFLAGS@ -DMAKE_NATIVE ${XDEFS} -DBMAKE_PATH_MAX=@bmake_path_max@" + +MAKE_VERSION=@_MAKE_VERSION@ + +MDEFS="-DMAKE_VERSION=\"$MAKE_VERSION\" \ +-D@force_machine@MACHINE=\"@machine@\" -DMACHINE_ARCH=\"@machine_arch@\" \ +-D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"" + + +LDFLAGS="@LDFLAGS@" +LIBS="@LIBS@" + +toUpper() { + ${TR:-tr} abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ +} + +do_compile2() { + obj="$1"; shift + src="$1"; shift + echo ${CC} -c ${CFLAGS} "$@" -o "$obj" "$src" + ${CC} -c ${CFLAGS} "$@" -o "$obj" "$src" +} + +do_compile() { + obj="$1"; shift + case "$1" in + *.c) src=$1; shift;; + *) src=`basename "$obj" .o`.c;; + esac + + for d in "$srcdir" "$srcdir/lst.lib" + do + test -s "$d/$src" || continue + + do_compile2 "$obj" "$d/$src" "$@" || exit 1 + return + done + echo "Unknown object file '$obj'" >&2 + exit 1 +} + +do_link() { + output="$1"; shift + echo ${CC} ${LDSTATIC} ${LDFLAGS} -o "$output" "$@" ${LIBS} + ${CC} ${LDSTATIC} ${LDFLAGS} -o "$output" "$@" ${LIBS} +} + +BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o enum.o for.o getopt hash.o \ +lst.o make.o make_malloc.o metachar.o parse.o sigcompat.o str.o strlist.o \ +suff.o targ.o trace.o var.o util.o" + +LIB_OBJECTS="@LIBOBJS@" + +do_compile main.o ${MDEFS} + +for o in ${BASE_OBJECTS} ${LIB_OBJECTS} +do + do_compile "$o" +done + +case "@use_meta@" in +yes) + case "@use_filemon@" in + no) MDEFS=;; + *) + MDEFS="-DUSE_FILEMON -DUSE_FILEMON_`echo @use_filemon@ | toUpper`" + case "@use_filemon@,@filemon_h@" in + dev,*/filemon.h) FDEFS="-DHAVE_FILEMON_H -I`dirname @filemon_h@`";; + *) FDEFS=;; + esac + do_compile filemon_@use_filemon@.o filemon/filemon_@use_filemon@.c ${FDEFS} + BASE_OBJECTS="filemon_@use_filemon@.o $BASE_OBJECTS" + ;; + esac + do_compile meta.o ${MDEFS} + BASE_OBJECTS="meta.o ${BASE_OBJECTS}" + ;; +esac +do_compile job.o ${MDEFS} + +do_link bmake main.o job.o ${BASE_OBJECTS} ${LST_OBJECTS} ${LIB_OBJECTS} Property changes on: vendor/NetBSD/bmake/20201101/make-bootstrap.sh.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make-conf.h =================================================================== --- vendor/NetBSD/bmake/20201101/make-conf.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/make-conf.h (revision 367461) @@ -0,0 +1,163 @@ +/* $NetBSD: config.h,v 1.25 2020/10/19 23:43:55 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)config.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Copyright (c) 1988, 1989 by Adam de Boor + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)config.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * DEFMAXJOBS + * DEFMAXLOCAL + * These control the default concurrency. On no occasion will more + * than DEFMAXJOBS targets be created at once (locally or remotely). + * + * DEFMAXLOCAL is the highest number of targets which will be + * created on the local machine at once. Note that if you set this + * to 0, nothing will ever happen. + */ +#define DEFMAXJOBS 4 +#define DEFMAXLOCAL 1 + +/* + * INCLUDES + * LIBRARIES + * These control the handling of the .INCLUDES and .LIBS variables. + * + * If INCLUDES is defined, the .INCLUDES variable will be filled + * from the search paths of those suffixes which are marked by + * .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS. + * + * See varname-dot-include.mk and varname-dot-libs.mk for more details. + */ +#define INCLUDES +#define LIBRARIES + +/* + * LIBSUFF + * Is the suffix used to denote libraries and is used by the Suff module + * to find the search path on which to seek any -l targets. + */ +#define LIBSUFF ".a" + +/* + * RECHECK + * If defined, Make_Update will check a target for its current + * modification time after it has been re-made, setting it to the + * starting time of the make only if the target still doesn't exist. + * + * Unfortunately, under NFS the modification time often doesn't + * get updated in time, so a target will appear to not have been + * re-made, causing later targets to appear up-to-date. + * + * On systems that don't have this problem, you should define this. + * Under NFS you probably should not, unless you aren't exporting jobs. + */ +#define RECHECK + +/* + * POSIX + * Adhere to the POSIX 1003.2 draft for the make(1) program. + * - Use MAKEFLAGS instead of MAKE to pick arguments from the + * environment. + * - Allow empty command lines if starting with tab. + */ +#define POSIX + +/* + * SYSVINCLUDE + * Recognize system V like include directives [include "filename"] + * (required by POSIX 2018) + * SYSVVARSUB + * Recognize system V like ${VAR:x=y} variable substitutions + * (required by POSIX 2018) + */ +#define SYSVINCLUDE +#define SYSVVARSUB + +/* + * GMAKEEXPORT + * Recognize gmake like variable export directives [export =] + */ +#define GMAKEEXPORT + +/* + * SUNSHCMD + * Recognize SunOS and Solaris: + * VAR :sh= CMD # Assign VAR to the command substitution of CMD + * ${VAR:sh} # Return the command substitution of the value + * # of ${VAR} + */ +#define SUNSHCMD + +#if defined(MAKE_NATIVE) && !defined(__ELF__) +# ifndef RANLIBMAG +# define RANLIBMAG "__.SYMDEF" +# endif +#endif Property changes on: vendor/NetBSD/bmake/20201101/make-conf.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make.1 =================================================================== --- vendor/NetBSD/bmake/20201101/make.1 (nonexistent) +++ vendor/NetBSD/bmake/20201101/make.1 (revision 367461) @@ -0,0 +1,2450 @@ +.\" $NetBSD: make.1,v 1.290 2020/11/01 20:24:45 rillig Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. 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. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 +.\" +.Dd November 1, 2020 +.Dt MAKE 1 +.Os +.Sh NAME +.Nm make +.Nd maintain program dependencies +.Sh SYNOPSIS +.Nm +.Op Fl BeikNnqrstWwX +.Op Fl C Ar directory +.Op Fl D Ar variable +.Op Fl d Ar flags +.Op Fl f Ar makefile +.Op Fl I Ar directory +.Op Fl J Ar private +.Op Fl j Ar max_jobs +.Op Fl m Ar directory +.Op Fl T Ar file +.Op Fl V Ar variable +.Op Fl v Ar variable +.Op Ar variable=value +.Op Ar target ... +.Sh DESCRIPTION +.Nm +is a program designed to simplify the maintenance of other programs. +Its input is a list of specifications as to the files upon which programs +and other files depend. +If no +.Fl f Ar makefile +makefile option is given, +.Nm +will try to open +.Ql Pa makefile +then +.Ql Pa Makefile +in order to find the specifications. +If the file +.Ql Pa .depend +exists, it is read (see +.Xr mkdep 1 ) . +.Pp +This manual page is intended as a reference document only. +For a more thorough description of +.Nm +and makefiles, please refer to +.%T "PMake \- A Tutorial" . +.Pp +.Nm +will prepend the contents of the +.Va MAKEFLAGS +environment variable to the command line arguments before parsing them. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl B +Try to be backwards compatible by executing a single shell per command and +by executing the commands to make the sources of a dependency line in sequence. +.It Fl C Ar directory +Change to +.Ar directory +before reading the makefiles or doing anything else. +If multiple +.Fl C +options are specified, each is interpreted relative to the previous one: +.Fl C Pa / Fl C Pa etc +is equivalent to +.Fl C Pa /etc . +.It Fl D Ar variable +Define +.Ar variable +to be 1, in the global context. +.It Fl d Ar [-]flags +Turn on debugging, and specify which portions of +.Nm +are to print debugging information. +Unless the flags are preceded by +.Ql \- +they are added to the +.Va MAKEFLAGS +environment variable and will be processed by any child make processes. +By default, debugging information is printed to standard error, +but this can be changed using the +.Ar F +debugging flag. +The debugging output is always unbuffered; in addition, if debugging +is enabled but debugging output is not directed to standard output, +then the standard output is line buffered. +.Ar Flags +is one or more of the following: +.Bl -tag -width Ds +.It Ar A +Print all possible debugging information; +equivalent to specifying all of the debugging flags. +.It Ar a +Print debugging information about archive searching and caching. +.It Ar C +Print debugging information about current working directory. +.It Ar c +Print debugging information about conditional evaluation. +.It Ar d +Print debugging information about directory searching and caching. +.It Ar e +Print debugging information about failed commands and targets. +.It Ar F Ns Oo Sy \&+ Oc Ns Ar filename +Specify where debugging output is written. +This must be the last flag, because it consumes the remainder of +the argument. +If the character immediately after the +.Ql F +flag is +.Ql \&+ , +then the file will be opened in append mode; +otherwise the file will be overwritten. +If the file name is +.Ql stdout +or +.Ql stderr +then debugging output will be written to the +standard output or standard error output file descriptors respectively +(and the +.Ql \&+ +option has no effect). +Otherwise, the output will be written to the named file. +If the file name ends +.Ql .%d +then the +.Ql %d +is replaced by the pid. +.It Ar f +Print debugging information about loop evaluation. +.It Ar "g1" +Print the input graph before making anything. +.It Ar "g2" +Print the input graph after making everything, or before exiting +on error. +.It Ar "g3" +Print the input graph before exiting on error. +.It Ar h +Print debugging information about hash table operations. +.It Ar j +Print debugging information about running multiple shells. +.It Ar L +Turn on lint checks. +This will throw errors for variable assignments that do not parse +correctly, at the time of assignment so the file and line number +are available. +.It Ar l +Print commands in Makefiles regardless of whether or not they are prefixed by +.Ql @ +or other "quiet" flags. +Also known as "loud" behavior. +.It Ar M +Print debugging information about "meta" mode decisions about targets. +.It Ar m +Print debugging information about making targets, including modification +dates. +.It Ar n +Don't delete the temporary command scripts created when running commands. +These temporary scripts are created in the directory +referred to by the +.Ev TMPDIR +environment variable, or in +.Pa /tmp +if +.Ev TMPDIR +is unset or set to the empty string. +The temporary scripts are created by +.Xr mkstemp 3 , +and have names of the form +.Pa makeXXXXXX . +.Em NOTE : +This can create many files in +.Ev TMPDIR +or +.Pa /tmp , +so use with care. +.It Ar p +Print debugging information about makefile parsing. +.It Ar s +Print debugging information about suffix-transformation rules. +.It Ar t +Print debugging information about target list maintenance. +.It Ar V +Force the +.Fl V +option to print raw values of variables, overriding the default behavior +set via +.Va .MAKE.EXPAND_VARIABLES . +.It Ar v +Print debugging information about variable assignment. +.It Ar x +Run shell commands with +.Fl x +so the actual commands are printed as they are executed. +.El +.It Fl e +Specify that environment variables override macro assignments within +makefiles. +.It Fl f Ar makefile +Specify a makefile to read instead of the default +.Ql Pa makefile . +If +.Ar makefile +is +.Ql Fl , +standard input is read. +Multiple makefiles may be specified, and are read in the order specified. +.It Fl I Ar directory +Specify a directory in which to search for makefiles and included makefiles. +The system makefile directory (or directories, see the +.Fl m +option) is automatically included as part of this list. +.It Fl i +Ignore non-zero exit of shell commands in the makefile. +Equivalent to specifying +.Ql Fl +before each command line in the makefile. +.It Fl J Ar private +This option should +.Em not +be specified by the user. +.Pp +When the +.Ar j +option is in use in a recursive build, this option is passed by a make +to child makes to allow all the make processes in the build to +cooperate to avoid overloading the system. +.It Fl j Ar max_jobs +Specify the maximum number of jobs that +.Nm +may have running at any one time. +The value is saved in +.Va .MAKE.JOBS . +Turns compatibility mode off, unless the +.Ar B +flag is also specified. +When compatibility mode is off, all commands associated with a +target are executed in a single shell invocation as opposed to the +traditional one shell invocation per line. +This can break traditional scripts which change directories on each +command invocation and then expect to start with a fresh environment +on the next line. +It is more efficient to correct the scripts rather than turn backwards +compatibility on. +.It Fl k +Continue processing after errors are encountered, but only on those targets +that do not depend on the target whose creation caused the error. +.It Fl m Ar directory +Specify a directory in which to search for sys.mk and makefiles included +via the +.Li \&< Ns Ar file Ns Li \&> Ns -style +include statement. +The +.Fl m +option can be used multiple times to form a search path. +This path will override the default system include path: /usr/share/mk. +Furthermore the system include path will be appended to the search path used +for +.Li \*q Ns Ar file Ns Li \*q Ns -style +include statements (see the +.Fl I +option). +.Pp +If a file or directory name in the +.Fl m +argument (or the +.Ev MAKESYSPATH +environment variable) starts with the string +.Qq \&.../ +then +.Nm +will search for the specified file or directory named in the remaining part +of the argument string. +The search starts with the current directory of +the Makefile and then works upward towards the root of the file system. +If the search is successful, then the resulting directory replaces the +.Qq \&.../ +specification in the +.Fl m +argument. +If used, this feature allows +.Nm +to easily search in the current source tree for customized sys.mk files +(e.g., by using +.Qq \&.../mk/sys.mk +as an argument). +.It Fl n +Display the commands that would have been executed, but do not +actually execute them unless the target depends on the .MAKE special +source (see below) or the command is prefixed with +.Ql Ic + . +.It Fl N +Display the commands which would have been executed, but do not +actually execute any of them; useful for debugging top-level makefiles +without descending into subdirectories. +.It Fl q +Do not execute any commands, but exit 0 if the specified targets are +up-to-date and 1, otherwise. +.It Fl r +Do not use the built-in rules specified in the system makefile. +.It Fl s +Do not echo any commands as they are executed. +Equivalent to specifying +.Ql Ic @ +before each command line in the makefile. +.It Fl T Ar tracefile +When used with the +.Fl j +flag, +append a trace record to +.Ar tracefile +for each job started and completed. +.It Fl t +Rather than re-building a target as specified in the makefile, create it +or update its modification time to make it appear up-to-date. +.It Fl V Ar variable +Print the value of +.Ar variable . +Do not build any targets. +Multiple instances of this option may be specified; +the variables will be printed one per line, +with a blank line for each null or undefined variable. +The value printed is extracted from the global context after all +makefiles have been read. +By default, the raw variable contents (which may +include additional unexpanded variable references) are shown. +If +.Ar variable +contains a +.Ql \&$ +then the value will be recursively expanded to its complete resultant +text before printing. +The expanded value will also be printed if +.Va .MAKE.EXPAND_VARIABLES +is set to true and +the +.Fl dV +option has not been used to override it. +Note that loop-local and target-local variables, as well as values +taken temporarily by global variables during makefile processing, are +not accessible via this option. +The +.Fl dv +debug mode can be used to see these at the cost of generating +substantial extraneous output. +.It Fl v Ar variable +Like +.Fl V +but the variable is always expanded to its complete value. +.It Fl W +Treat any warnings during makefile parsing as errors. +.It Fl w +Print entering and leaving directory messages, pre and post processing. +.It Fl X +Don't export variables passed on the command line to the environment +individually. +Variables passed on the command line are still exported +via the +.Va MAKEFLAGS +environment variable. +This option may be useful on systems which have a small limit on the +size of command arguments. +.It Ar variable=value +Set the value of the variable +.Ar variable +to +.Ar value . +Normally, all values passed on the command line are also exported to +sub-makes in the environment. +The +.Fl X +flag disables this behavior. +Variable assignments should follow options for POSIX compatibility +but no ordering is enforced. +.El +.Pp +There are seven different types of lines in a makefile: file dependency +specifications, shell commands, variable assignments, include statements, +conditional directives, for loops, and comments. +.Pp +In general, lines may be continued from one line to the next by ending +them with a backslash +.Pq Ql \e . +The trailing newline character and initial whitespace on the following +line are compressed into a single space. +.Sh FILE DEPENDENCY SPECIFICATIONS +Dependency lines consist of one or more targets, an operator, and zero +or more sources. +This creates a relationship where the targets +.Dq depend +on the sources +and are customarily created from them. +A target is considered out-of-date if it does not exist, or if its +modification time is less than that of any of its sources. +An out-of-date target will be re-created, but not until all sources +have been examined and themselves re-created as needed. +Three operators may be used: +.Bl -tag -width flag +.It Ic \&: +Many dependency lines may name this target but only one may have +attached shell commands. +All sources named in all dependency lines are considered together, +and if needed the attached shell commands are run to create or +re-create the target. +If +.Nm +is interrupted, the target is removed. +.It Ic \&! +The same, but the target is always re-created whether or not it is out +of date. +.It Ic \&:: +Any dependency line may have attached shell commands, but each one +is handled independently: its sources are considered and the attached +shell commands are run if the target is out of date with respect to +(only) those sources. +Thus, different groups of the attached shell commands may be run +depending on the circumstances. +Furthermore, unlike +.Ic \&:, +for dependency lines with no sources, the attached shell +commands are always run. +Also unlike +.Ic \&:, +the target will not be removed if +.Nm +is interrupted. +.El +All dependency lines mentioning a particular target must use the same +operator. +.Pp +Targets and sources may contain the shell wildcard values +.Ql \&? , +.Ql * , +.Ql [] , +and +.Ql {} . +The values +.Ql \&? , +.Ql * , +and +.Ql [] +may only be used as part of the final +component of the target or source, and must be used to describe existing +files. +The value +.Ql {} +need not necessarily be used to describe existing files. +Expansion is in directory order, not alphabetically as done in the shell. +.Sh SHELL COMMANDS +Each target may have associated with it one or more lines of shell +commands, normally +used to create the target. +Each of the lines in this script +.Em must +be preceded by a tab. +(For historical reasons, spaces are not accepted.) +While targets can appear in many dependency lines if desired, by +default only one of these rules may be followed by a creation +script. +If the +.Ql Ic \&:: +operator is used, however, all rules may include scripts and the +scripts are executed in the order found. +.Pp +Each line is treated as a separate shell command, unless the end of +line is escaped with a backslash +.Pq Ql \e +in which case that line and the next are combined. +.\" The escaped newline is retained and passed to the shell, which +.\" normally ignores it. +.\" However, the tab at the beginning of the following line is removed. +If the first characters of the command are any combination of +.Ql Ic @ , +.Ql Ic + , +or +.Ql Ic \- , +the command is treated specially. +A +.Ql Ic @ +causes the command not to be echoed before it is executed. +A +.Ql Ic + +causes the command to be executed even when +.Fl n +is given. +This is similar to the effect of the .MAKE special source, +except that the effect can be limited to a single line of a script. +A +.Ql Ic \- +in compatibility mode +causes any non-zero exit status of the command line to be ignored. +.Pp +When +.Nm +is run in jobs mode with +.Fl j Ar max_jobs , +the entire script for the target is fed to a +single instance of the shell. +In compatibility (non-jobs) mode, each command is run in a separate process. +If the command contains any shell meta characters +.Pq Ql #=|^(){};&<>*?[]:$`\e\en +it will be passed to the shell; otherwise +.Nm +will attempt direct execution. +If a line starts with +.Ql Ic \- +and the shell has ErrCtl enabled then failure of the command line +will be ignored as in compatibility mode. +Otherwise +.Ql Ic \- +affects the entire job; +the script will stop at the first command line that fails, +but the target will not be deemed to have failed. +.Pp +Makefiles should be written so that the mode of +.Nm +operation does not change their behavior. +For example, any command which needs to use +.Dq cd +or +.Dq chdir +without potentially changing the directory for subsequent commands +should be put in parentheses so it executes in a subshell. +To force the use of one shell, escape the line breaks so as to make +the whole script one command. +For example: +.Bd -literal -offset indent +avoid-chdir-side-effects: + @echo Building $@ in `pwd` + @(cd ${.CURDIR} && ${MAKE} $@) + @echo Back in `pwd` + +ensure-one-shell-regardless-of-mode: + @echo Building $@ in `pwd`; \e + (cd ${.CURDIR} && ${MAKE} $@); \e + echo Back in `pwd` +.Ed +.Pp +Since +.Nm +will +.Xr chdir 2 +to +.Ql Va .OBJDIR +before executing any targets, each child process +starts with that as its current working directory. +.Sh VARIABLE ASSIGNMENTS +Variables in make are much like variables in the shell, and, by tradition, +consist of all upper-case letters. +.Ss Variable assignment modifiers +The five operators that can be used to assign values to variables are as +follows: +.Bl -tag -width Ds +.It Ic \&= +Assign the value to the variable. +Any previous value is overridden. +.It Ic \&+= +Append the value to the current value of the variable. +.It Ic \&?= +Assign the value to the variable if it is not already defined. +.It Ic \&:= +Assign with expansion, i.e. expand the value before assigning it +to the variable. +Normally, expansion is not done until the variable is referenced. +.Em NOTE : +References to undefined variables are +.Em not +expanded. +This can cause problems when variable modifiers are used. +.It Ic \&!= +Expand the value and pass it to the shell for execution and assign +the result to the variable. +Any newlines in the result are replaced with spaces. +.El +.Pp +Any white-space before the assigned +.Ar value +is removed; if the value is being appended, a single space is inserted +between the previous contents of the variable and the appended value. +.Pp +Variables are expanded by surrounding the variable name with either +curly braces +.Pq Ql {} +or parentheses +.Pq Ql () +and preceding it with +a dollar sign +.Pq Ql \&$ . +If the variable name contains only a single letter, the surrounding +braces or parentheses are not required. +This shorter form is not recommended. +.Pp +If the variable name contains a dollar, then the name itself is expanded first. +This allows almost arbitrary variable names, however names containing dollar, +braces, parentheses, or whitespace are really best avoided! +.Pp +If the result of expanding a variable contains a dollar sign +.Pq Ql \&$ +the string is expanded again. +.Pp +Variable substitution occurs at three distinct times, depending on where +the variable is being used. +.Bl -enum +.It +Variables in dependency lines are expanded as the line is read. +.It +Variables in shell commands are expanded when the shell command is +executed. +.It +.Dq .for +loop index variables are expanded on each loop iteration. +Note that other variables are not expanded inside loops so +the following example code: +.Bd -literal -offset indent + +.Dv .for i in 1 2 3 +a+= ${i} +j= ${i} +b+= ${j} +.Dv .endfor + +all: + @echo ${a} + @echo ${b} + +.Ed +will print: +.Bd -literal -offset indent +1 2 3 +3 3 3 + +.Ed +Because while ${a} contains +.Dq 1 2 3 +after the loop is executed, ${b} +contains +.Dq ${j} ${j} ${j} +which expands to +.Dq 3 3 3 +since after the loop completes ${j} contains +.Dq 3 . +.El +.Ss Variable classes +The four different classes of variables (in order of increasing precedence) +are: +.Bl -tag -width Ds +.It Environment variables +Variables defined as part of +.Nm Ns 's +environment. +.It Global variables +Variables defined in the makefile or in included makefiles. +.It Command line variables +Variables defined as part of the command line. +.It Local variables +Variables that are defined specific to a certain target. +.El +.Pp +Local variables are all built in and their values vary magically from +target to target. +It is not currently possible to define new local variables. +The seven local variables are as follows: +.Bl -tag -width ".ARCHIVE" -offset indent +.It Va .ALLSRC +The list of all sources for this target; also known as +.Ql Va \&> . +.It Va .ARCHIVE +The name of the archive file; also known as +.Ql Va \&! . +.It Va .IMPSRC +In suffix-transformation rules, the name/path of the source from which the +target is to be transformed (the +.Dq implied +source); also known as +.Ql Va \&< . +It is not defined in explicit rules. +.It Va .MEMBER +The name of the archive member; also known as +.Ql Va % . +.It Va .OODATE +The list of sources for this target that were deemed out-of-date; also +known as +.Ql Va \&? . +.It Va .PREFIX +The file prefix of the target, containing only the file portion, no suffix +or preceding directory components; also known as +.Ql Va * . +The suffix must be one of the known suffixes declared with +.Ic .SUFFIXES +or it will not be recognized. +.It Va .TARGET +The name of the target; also known as +.Ql Va @ . +For compatibility with other makes this is an alias for +.Ic .ARCHIVE +in archive member rules. +.El +.Pp +The shorter forms +.Ql ( Va > , +.Ql Va \&! , +.Ql Va < , +.Ql Va % , +.Ql Va \&? , +.Ql Va * , +and +.Ql Va @ ) +are permitted for backward +compatibility with historical makefiles and legacy POSIX make and are +not recommended. +.Pp +Variants of these variables with the punctuation followed immediately by +.Ql D +or +.Ql F , +e.g. +.Ql Va $(@D) , +are legacy forms equivalent to using the +.Ql :H +and +.Ql :T +modifiers. +These forms are accepted for compatibility with +.At V +makefiles and POSIX but are not recommended. +.Pp +Four of the local variables may be used in sources on dependency lines +because they expand to the proper value for each target on the line. +These variables are +.Ql Va .TARGET , +.Ql Va .PREFIX , +.Ql Va .ARCHIVE , +and +.Ql Va .MEMBER . +.Ss Additional built-in variables +In addition, +.Nm +sets or knows about the following variables: +.Bl -tag -width .MAKEOVERRIDES +.It Va \&$ +A single dollar sign +.Ql \&$ , +i.e. +.Ql \&$$ +expands to a single dollar +sign. +.It Va .ALLTARGETS +The list of all targets encountered in the Makefile. +If evaluated during +Makefile parsing, lists only those targets encountered thus far. +.It Va .CURDIR +A path to the directory where +.Nm +was executed. +Refer to the description of +.Ql Ev PWD +for more details. +.It Va .INCLUDEDFROMDIR +The directory of the file this Makefile was included from. +.It Va .INCLUDEDFROMFILE +The filename of the file this Makefile was included from. +.It Ev MAKE +The name that +.Nm +was executed with +.Pq Va argv[0] . +For compatibility +.Nm +also sets +.Va .MAKE +with the same value. +The preferred variable to use is the environment variable +.Ev MAKE +because it is more compatible with other versions of +.Nm +and cannot be confused with the special target with the same name. +.It Va .MAKE.DEPENDFILE +Names the makefile (default +.Ql Pa .depend ) +from which generated dependencies are read. +.It Va .MAKE.EXPAND_VARIABLES +A boolean that controls the default behavior of the +.Fl V +option. +If true, variable values printed with +.Fl V +are fully expanded; if false, the raw variable contents (which may +include additional unexpanded variable references) are shown. +.It Va .MAKE.EXPORTED +The list of variables exported by +.Nm . +.It Va .MAKE.JOBS +The argument to the +.Fl j +option. +.It Va .MAKE.JOB.PREFIX +If +.Nm +is run with +.Ar j +then output for each target is prefixed with a token +.Ql --- target --- +the first part of which can be controlled via +.Va .MAKE.JOB.PREFIX . +If +.Va .MAKE.JOB.PREFIX +is empty, no token is printed. +.br +For example: +.Li .MAKE.JOB.PREFIX=${.newline}---${.MAKE:T}[${.MAKE.PID}] +would produce tokens like +.Ql ---make[1234] target --- +making it easier to track the degree of parallelism being achieved. +.It Ev MAKEFLAGS +The environment variable +.Ql Ev MAKEFLAGS +may contain anything that +may be specified on +.Nm Ns 's +command line. +Anything specified on +.Nm Ns 's +command line is appended to the +.Ql Ev MAKEFLAGS +variable which is then +entered into the environment for all programs which +.Nm +executes. +.It Va .MAKE.LEVEL +The recursion depth of +.Nm . +The initial instance of +.Nm +will be 0, and an incremented value is put into the environment +to be seen by the next generation. +This allows tests like: +.Li .if ${.MAKE.LEVEL} == 0 +to protect things which should only be evaluated in the initial instance of +.Nm . +.It Va .MAKE.MAKEFILE_PREFERENCE +The ordered list of makefile names +(default +.Ql Pa makefile , +.Ql Pa Makefile ) +that +.Nm +will look for. +.It Va .MAKE.MAKEFILES +The list of makefiles read by +.Nm , +which is useful for tracking dependencies. +Each makefile is recorded only once, regardless of the number of times read. +.It Va .MAKE.MODE +Processed after reading all makefiles. +Can affect the mode that +.Nm +runs in. +It can contain a number of keywords: +.Bl -hang -width missing-filemon=bf. +.It Pa compat +Like +.Fl B , +puts +.Nm +into "compat" mode. +.It Pa meta +Puts +.Nm +into "meta" mode, where meta files are created for each target +to capture the command run, the output generated and if +.Xr filemon 4 +is available, the system calls which are of interest to +.Nm . +The captured output can be very useful when diagnosing errors. +.It Pa curdirOk= Ar bf +Normally +.Nm +will not create .meta files in +.Ql Va .CURDIR . +This can be overridden by setting +.Va bf +to a value which represents True. +.It Pa missing-meta= Ar bf +If +.Va bf +is True, then a missing .meta file makes the target out-of-date. +.It Pa missing-filemon= Ar bf +If +.Va bf +is True, then missing filemon data makes the target out-of-date. +.It Pa nofilemon +Do not use +.Xr filemon 4 . +.It Pa env +For debugging, it can be useful to include the environment +in the .meta file. +.It Pa verbose +If in "meta" mode, print a clue about the target being built. +This is useful if the build is otherwise running silently. +The message printed the value of: +.Va .MAKE.META.PREFIX . +.It Pa ignore-cmd +Some makefiles have commands which are simply not stable. +This keyword causes them to be ignored for +determining whether a target is out of date in "meta" mode. +See also +.Ic .NOMETA_CMP . +.It Pa silent= Ar bf +If +.Va bf +is True, when a .meta file is created, mark the target +.Ic .SILENT . +.El +.It Va .MAKE.META.BAILIWICK +In "meta" mode, provides a list of prefixes which +match the directories controlled by +.Nm . +If a file that was generated outside of +.Va .OBJDIR +but within said bailiwick is missing, +the current target is considered out-of-date. +.It Va .MAKE.META.CREATED +In "meta" mode, this variable contains a list of all the meta files +updated. +If not empty, it can be used to trigger processing of +.Va .MAKE.META.FILES . +.It Va .MAKE.META.FILES +In "meta" mode, this variable contains a list of all the meta files +used (updated or not). +This list can be used to process the meta files to extract dependency +information. +.It Va .MAKE.META.IGNORE_PATHS +Provides a list of path prefixes that should be ignored; +because the contents are expected to change over time. +The default list includes: +.Ql Pa /dev /etc /proc /tmp /var/run /var/tmp +.It Va .MAKE.META.IGNORE_PATTERNS +Provides a list of patterns to match against pathnames. +Ignore any that match. +.It Va .MAKE.META.IGNORE_FILTER +Provides a list of variable modifiers to apply to each pathname. +Ignore if the expansion is an empty string. +.It Va .MAKE.META.PREFIX +Defines the message printed for each meta file updated in "meta verbose" mode. +The default value is: +.Dl Building ${.TARGET:H:tA}/${.TARGET:T} +.It Va .MAKEOVERRIDES +This variable is used to record the names of variables assigned to +on the command line, so that they may be exported as part of +.Ql Ev MAKEFLAGS . +This behavior can be disabled by assigning an empty value to +.Ql Va .MAKEOVERRIDES +within a makefile. +Extra variables can be exported from a makefile +by appending their names to +.Ql Va .MAKEOVERRIDES . +.Ql Ev MAKEFLAGS +is re-exported whenever +.Ql Va .MAKEOVERRIDES +is modified. +.It Va .MAKE.PATH_FILEMON +If +.Nm +was built with +.Xr filemon 4 +support, this is set to the path of the device node. +This allows makefiles to test for this support. +.It Va .MAKE.PID +The process-id of +.Nm . +.It Va .MAKE.PPID +The parent process-id of +.Nm . +.It Va .MAKE.SAVE_DOLLARS +value should be a boolean that controls whether +.Ql $$ +are preserved when doing +.Ql := +assignments. +The default is false, for backwards compatibility. +Set to true for compatability with other makes. +If set to false, +.Ql $$ +becomes +.Ql $ +per normal evaluation rules. +.It Va MAKE_PRINT_VAR_ON_ERROR +When +.Nm +stops due to an error, it sets +.Ql Va .ERROR_TARGET +to the name of the target that failed, +.Ql Va .ERROR_CMD +to the commands of the failed target, +and in "meta" mode, it also sets +.Ql Va .ERROR_CWD +to the +.Xr getcwd 3 , +and +.Ql Va .ERROR_META_FILE +to the path of the meta file (if any) describing the failed target. +It then prints its name and the value of +.Ql Va .CURDIR +as well as the value of any variables named in +.Ql Va MAKE_PRINT_VAR_ON_ERROR . +.It Va .newline +This variable is simply assigned a newline character as its value. +This allows expansions using the +.Cm \&:@ +modifier to put a newline between +iterations of the loop rather than a space. +For example, the printing of +.Ql Va MAKE_PRINT_VAR_ON_ERROR +could be done as ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}. +.It Va .OBJDIR +A path to the directory where the targets are built. +Its value is determined by trying to +.Xr chdir 2 +to the following directories in order and using the first match: +.Bl -enum +.It +.Ev ${MAKEOBJDIRPREFIX}${.CURDIR} +.Pp +(Only if +.Ql Ev MAKEOBJDIRPREFIX +is set in the environment or on the command line.) +.It +.Ev ${MAKEOBJDIR} +.Pp +(Only if +.Ql Ev MAKEOBJDIR +is set in the environment or on the command line.) +.It +.Ev ${.CURDIR} Ns Pa /obj. Ns Ev ${MACHINE} +.It +.Ev ${.CURDIR} Ns Pa /obj +.It +.Pa /usr/obj/ Ns Ev ${.CURDIR} +.It +.Ev ${.CURDIR} +.El +.Pp +Variable expansion is performed on the value before it's used, +so expressions such as +.Dl ${.CURDIR:S,^/usr/src,/var/obj,} +may be used. +This is especially useful with +.Ql Ev MAKEOBJDIR . +.Pp +.Ql Va .OBJDIR +may be modified in the makefile via the special target +.Ql Ic .OBJDIR . +In all cases, +.Nm +will +.Xr chdir 2 +to the specified directory if it exists, and set +.Ql Va .OBJDIR +and +.Ql Ev PWD +to that directory before executing any targets. +. +.It Va .PARSEDIR +A path to the directory of the current +.Ql Pa Makefile +being parsed. +.It Va .PARSEFILE +The basename of the current +.Ql Pa Makefile +being parsed. +This variable and +.Ql Va .PARSEDIR +are both set only while the +.Ql Pa Makefiles +are being parsed. +If you want to retain their current values, assign them to a variable +using assignment with expansion: +.Pq Ql Cm \&:= . +.It Va .PATH +A variable that represents the list of directories that +.Nm +will search for files. +The search list should be updated using the target +.Ql Va .PATH +rather than the variable. +.It Ev PWD +Alternate path to the current directory. +.Nm +normally sets +.Ql Va .CURDIR +to the canonical path given by +.Xr getcwd 3 . +However, if the environment variable +.Ql Ev PWD +is set and gives a path to the current directory, then +.Nm +sets +.Ql Va .CURDIR +to the value of +.Ql Ev PWD +instead. +This behavior is disabled if +.Ql Ev MAKEOBJDIRPREFIX +is set or +.Ql Ev MAKEOBJDIR +contains a variable transform. +.Ql Ev PWD +is set to the value of +.Ql Va .OBJDIR +for all programs which +.Nm +executes. +.It Ev .SHELL +The pathname of the shell used to run target scripts. +It is read-only. +.It Ev .TARGETS +The list of targets explicitly specified on the command line, if any. +.It Ev VPATH +Colon-separated +.Pq Dq \&: +lists of directories that +.Nm +will search for files. +The variable is supported for compatibility with old make programs only, +use +.Ql Va .PATH +instead. +.El +.Ss Variable modifiers +Variable expansion may be modified to select or modify each word of the +variable (where a +.Dq word +is white-space delimited sequence of characters). +The general format of a variable expansion is as follows: +.Pp +.Dl ${variable[:modifier[:...]]} +.Pp +Each modifier begins with a colon, +which may be escaped with a backslash +.Pq Ql \e . +.Pp +A set of modifiers can be specified via a variable, as follows: +.Pp +.Dl modifier_variable=modifier[:...] +.Dl ${variable:${modifier_variable}[:...]} +.Pp +In this case the first modifier in the modifier_variable does not +start with a colon, since that must appear in the referencing +variable. +If any of the modifiers in the modifier_variable contain a dollar sign +.Pq Ql $ , +these must be doubled to avoid early expansion. +.Pp +The supported modifiers are: +.Bl -tag -width EEE +.It Cm \&:E +Replaces each word in the variable with its suffix. +.It Cm \&:H +Replaces each word in the variable with everything but the last component. +.It Cm \&:M Ns Ar pattern +Selects only those words that match +.Ar pattern . +The standard shell wildcard characters +.Pf ( Ql * , +.Ql \&? , +and +.Ql Oo Oc ) +may +be used. +The wildcard characters may be escaped with a backslash +.Pq Ql \e . +As a consequence of the way values are split into words, matched, +and then joined, a construct like +.Dl ${VAR:M*} +will normalize the inter-word spacing, removing all leading and +trailing space, and converting multiple consecutive spaces +to single spaces. +. +.It Cm \&:N Ns Ar pattern +This is identical to +.Ql Cm \&:M , +but selects all words which do not match +.Ar pattern . +.It Cm \&:O +Orders every word in variable alphabetically. +.It Cm \&:Or +Orders every word in variable in reverse alphabetical order. +.It Cm \&:Ox +Shuffles the words in variable. +The results will be different each time you are referring to the +modified variable; use the assignment with expansion +.Pq Ql Cm \&:= +to prevent such behavior. +For example, +.Bd -literal -offset indent +LIST= uno due tre quattro +RANDOM_LIST= ${LIST:Ox} +STATIC_RANDOM_LIST:= ${LIST:Ox} + +all: + @echo "${RANDOM_LIST}" + @echo "${RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" + @echo "${STATIC_RANDOM_LIST}" +.Ed +may produce output similar to: +.Bd -literal -offset indent +quattro due tre uno +tre due quattro uno +due uno quattro tre +due uno quattro tre +.Ed +.It Cm \&:Q +Quotes every shell meta-character in the variable, so that it can be passed +safely to the shell. +.It Cm \&:q +Quotes every shell meta-character in the variable, and also doubles +.Sq $ +characters so that it can be passed +safely through recursive invocations of +.Nm . +This is equivalent to: +.Sq \&:S/\e\&$/&&/g:Q . +.It Cm \&:R +Replaces each word in the variable with everything but its suffix. +.It Cm \&:range[=count] +The value is an integer sequence representing the words of the original +value, or the supplied +.Va count . +.It Cm \&:gmtime[=utc] +The value is a format string for +.Xr strftime 3 , +using +.Xr gmtime 3 . +If a +.Va utc +value is not provided or is 0, the current time is used. +.It Cm \&:hash +Computes a 32-bit hash of the value and encode it as hex digits. +.It Cm \&:localtime[=utc] +The value is a format string for +.Xr strftime 3 , +using +.Xr localtime 3 . +If a +.Va utc +value is not provided or is 0, the current time is used. +.It Cm \&:tA +Attempts to convert variable to an absolute path using +.Xr realpath 3 , +if that fails, the value is unchanged. +.It Cm \&:tl +Converts variable to lower-case letters. +.It Cm \&:ts Ns Ar c +Words in the variable are normally separated by a space on expansion. +This modifier sets the separator to the character +.Ar c . +If +.Ar c +is omitted, then no separator is used. +The common escapes (including octal numeric codes) work as expected. +.It Cm \&:tu +Converts variable to upper-case letters. +.It Cm \&:tW +Causes the value to be treated as a single word +(possibly containing embedded white space). +See also +.Ql Cm \&:[*] . +.It Cm \&:tw +Causes the value to be treated as a sequence of +words delimited by white space. +See also +.Ql Cm \&:[@] . +.Sm off +.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW +.Sm on +Modifies the first occurrence of +.Ar old_string +in each word of the variable's value, replacing it with +.Ar new_string . +If a +.Ql g +is appended to the last delimiter of the pattern, all occurrences +in each word are replaced. +If a +.Ql 1 +is appended to the last delimiter of the pattern, only the first occurrence +is affected. +If a +.Ql W +is appended to the last delimiter of the pattern, +then the value is treated as a single word +(possibly containing embedded white space). +If +.Ar old_string +begins with a caret +.Pq Ql ^ , +.Ar old_string +is anchored at the beginning of each word. +If +.Ar old_string +ends with a dollar sign +.Pq Ql \&$ , +it is anchored at the end of each word. +Inside +.Ar new_string , +an ampersand +.Pq Ql & +is replaced by +.Ar old_string +(without any +.Ql ^ +or +.Ql \&$ ) . +Any character may be used as a delimiter for the parts of the modifier +string. +The anchoring, ampersand and delimiter characters may be escaped with a +backslash +.Pq Ql \e . +.Pp +Variable expansion occurs in the normal fashion inside both +.Ar old_string +and +.Ar new_string +with the single exception that a backslash is used to prevent the expansion +of a dollar sign +.Pq Ql \&$ , +not a preceding dollar sign as is usual. +.Sm off +.It Cm \&:C No \&/ Ar pattern No \&/ Ar replacement No \&/ Op Cm 1gW +.Sm on +The +.Cm \&:C +modifier is just like the +.Cm \&:S +modifier except that the old and new strings, instead of being +simple strings, are an extended regular expression (see +.Xr regex 3 ) +string +.Ar pattern +and an +.Xr ed 1 Ns \-style +string +.Ar replacement . +Normally, the first occurrence of the pattern +.Ar pattern +in each word of the value is substituted with +.Ar replacement . +The +.Ql 1 +modifier causes the substitution to apply to at most one word; the +.Ql g +modifier causes the substitution to apply to as many instances of the +search pattern +.Ar pattern +as occur in the word or words it is found in; the +.Ql W +modifier causes the value to be treated as a single word +(possibly containing embedded white space). +.Pp +As for the +.Cm \&:S +modifier, the +.Ar pattern +and +.Ar replacement +are subjected to variable expansion before being parsed as +regular expressions. +.It Cm \&:T +Replaces each word in the variable with its last path component. +.It Cm \&:u +Removes adjacent duplicate words (like +.Xr uniq 1 ) . +.Sm off +.It Cm \&:\&? Ar true_string Cm \&: Ar false_string +.Sm on +If the variable name (not its value), when parsed as a .if conditional +expression, evaluates to true, return as its value the +.Ar true_string , +otherwise return the +.Ar false_string . +Since the variable name is used as the expression, \&:\&? must be the +first modifier after the variable name itself - which will, of course, +usually contain variable expansions. +A common error is trying to use expressions like +.Dl ${NUMBERS:M42:?match:no} +which actually tests defined(NUMBERS), +to determine if any words match "42" you need to use something like: +.Dl ${"${NUMBERS:M42}" != \&"\&":?match:no} . +.It Ar :old_string=new_string +This is the +.At V +style variable substitution. +It must be the last modifier specified. +If +.Ar old_string +or +.Ar new_string +do not contain the pattern matching character +.Ar % +then it is assumed that they are +anchored at the end of each word, so only suffixes or entire +words may be replaced. +Otherwise +.Ar % +is the substring of +.Ar old_string +to be replaced in +.Ar new_string . +If only +.Ar old_string +contains the pattern matching character +.Ar % , +and +.Ar old_string +matches, then the result is the +.Ar new_string . +If only the +.Ar new_string +contains the pattern matching character +.Ar % , +then it is not treated specially and it is printed as a literal +.Ar % +on match. +If there is more than one pattern matching character +.Ar ( % ) +in either the +.Ar new_string +or +.Ar old_string , +only the first instance is treated specially (as the pattern character); +all subsequent instances are treated as regular characters. +.Pp +Variable expansion occurs in the normal fashion inside both +.Ar old_string +and +.Ar new_string +with the single exception that a backslash is used to prevent the +expansion of a dollar sign +.Pq Ql \&$ , +not a preceding dollar sign as is usual. +.Sm off +.It Cm \&:@ Ar temp Cm @ Ar string Cm @ +.Sm on +This is the loop expansion mechanism from the OSF Development +Environment (ODE) make. +Unlike +.Cm \&.for +loops, expansion occurs at the time of reference. +Assigns +.Ar temp +to each word in the variable and evaluates +.Ar string . +The ODE convention is that +.Ar temp +should start and end with a period. +For example. +.Dl ${LINKS:@.LINK.@${LN} ${TARGET} ${.LINK.}@} +.Pp +However a single character variable is often more readable: +.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@} +.It Cm \&:_[=var] +Saves the current variable value in +.Ql $_ +or the named +.Va var +for later reference. +Example usage: +.Bd -literal -offset indent +M_cmpv.units = 1 1000 1000000 +M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \&\\ +\\* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh + +.Dv .if ${VERSION:${M_cmpv}} < ${3.1.12:L:${M_cmpv}} + +.Ed +Here +.Ql $_ +is used to save the result of the +.Ql :S +modifier which is later referenced using the index values from +.Ql :range . +.It Cm \&:U Ns Ar newval +If the variable is undefined, +.Ar newval +is the value. +If the variable is defined, the existing value is returned. +This is another ODE make feature. +It is handy for setting per-target CFLAGS for instance: +.Dl ${_${.TARGET:T}_CFLAGS:U${DEF_CFLAGS}} +If a value is only required if the variable is undefined, use: +.Dl ${VAR:D:Unewval} +.It Cm \&:D Ns Ar newval +If the variable is defined, +.Ar newval +is the value. +.It Cm \&:L +The name of the variable is the value. +.It Cm \&:P +The path of the node which has the same name as the variable +is the value. +If no such node exists or its path is null, then the +name of the variable is used. +In order for this modifier to work, the name (node) must at least have +appeared on the rhs of a dependency. +.Sm off +.It Cm \&:\&! Ar cmd Cm \&! +.Sm on +The output of running +.Ar cmd +is the value. +.It Cm \&:sh +If the variable is non-empty it is run as a command and the output +becomes the new value. +.It Cm \&::= Ns Ar str +The variable is assigned the value +.Ar str +after substitution. +This modifier and its variations are useful in +obscure situations such as wanting to set a variable when shell commands +are being parsed. +These assignment modifiers always expand to +nothing, so if appearing in a rule line by themselves should be +preceded with something to keep +.Nm +happy. +.Pp +The +.Ql Cm \&:: +helps avoid false matches with the +.At V +style +.Cm \&:= +modifier and since substitution always occurs the +.Cm \&::= +form is vaguely appropriate. +.It Cm \&::?= Ns Ar str +As for +.Cm \&::= +but only if the variable does not already have a value. +.It Cm \&::+= Ns Ar str +Append +.Ar str +to the variable. +.It Cm \&::!= Ns Ar cmd +Assign the output of +.Ar cmd +to the variable. +.It Cm \&:\&[ Ns Ar range Ns Cm \&] +Selects one or more words from the value, +or performs other operations related to the way in which the +value is divided into words. +.Pp +Ordinarily, a value is treated as a sequence of words +delimited by white space. +Some modifiers suppress this behavior, +causing a value to be treated as a single word +(possibly containing embedded white space). +An empty value, or a value that consists entirely of white-space, +is treated as a single word. +For the purposes of the +.Ql Cm \&:[] +modifier, the words are indexed both forwards using positive integers +(where index 1 represents the first word), +and backwards using negative integers +(where index \-1 represents the last word). +.Pp +The +.Ar range +is subjected to variable expansion, and the expanded result is +then interpreted as follows: +.Bl -tag -width index +.\" :[n] +.It Ar index +Selects a single word from the value. +.\" :[start..end] +.It Ar start Ns Cm \&.. Ns Ar end +Selects all words from +.Ar start +to +.Ar end , +inclusive. +For example, +.Ql Cm \&:[2..-1] +selects all words from the second word to the last word. +If +.Ar start +is greater than +.Ar end , +then the words are output in reverse order. +For example, +.Ql Cm \&:[-1..1] +selects all the words from last to first. +If the list is already ordered, then this effectively reverses +the list, but it is more efficient to use +.Ql Cm \&:Or +instead of +.Ql Cm \&:O:[-1..1] . +.\" :[*] +.It Cm \&* +Causes subsequent modifiers to treat the value as a single word +(possibly containing embedded white space). +Analogous to the effect of +\&"$*\&" +in Bourne shell. +.\" :[0] +.It 0 +Means the same as +.Ql Cm \&:[*] . +.\" :[*] +.It Cm \&@ +Causes subsequent modifiers to treat the value as a sequence of words +delimited by white space. +Analogous to the effect of +\&"$@\&" +in Bourne shell. +.\" :[#] +.It Cm \&# +Returns the number of words in the value. +.El \" :[range] +.El +.Sh INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS +Makefile inclusion, conditional structures and for loops reminiscent +of the C programming language are provided in +.Nm . +All such structures are identified by a line beginning with a single +dot +.Pq Ql \&. +character. +Files are included with either +.Cm \&.include \&< Ns Ar file Ns Cm \&> +or +.Cm \&.include \&\*q Ns Ar file Ns Cm \&\*q . +Variables between the angle brackets or double quotes are expanded +to form the file name. +If angle brackets are used, the included makefile is expected to be in +the system makefile directory. +If double quotes are used, the including makefile's directory and any +directories specified using the +.Fl I +option are searched before the system +makefile directory. +For compatibility with other versions of +.Nm +.Ql include file ... +is also accepted. +.Pp +If the include statement is written as +.Cm .-include +or as +.Cm .sinclude +then errors locating and/or opening include files are ignored. +.Pp +If the include statement is written as +.Cm .dinclude +not only are errors locating and/or opening include files ignored, +but stale dependencies within the included file will be ignored +just like +.Va .MAKE.DEPENDFILE . +.Pp +Conditional expressions are also preceded by a single dot as the first +character of a line. +The possible conditionals are as follows: +.Bl -tag -width Ds +.It Ic .error Ar message +The message is printed along with the name of the makefile and line number, +then +.Nm +will exit immediately. +.It Ic .export Ar variable ... +Export the specified global variable. +If no variable list is provided, all globals are exported +except for internal variables (those that start with +.Ql \&. ) . +This is not affected by the +.Fl X +flag, so should be used with caution. +For compatibility with other +.Nm +programs +.Ql export variable=value +is also accepted. +.Pp +Appending a variable name to +.Va .MAKE.EXPORTED +is equivalent to exporting a variable. +.It Ic .export-env Ar variable ... +The same as +.Ql .export , +except that the variable is not appended to +.Va .MAKE.EXPORTED . +This allows exporting a value to the environment which is different from that +used by +.Nm +internally. +.It Ic .export-literal Ar variable ... +The same as +.Ql .export-env , +except that variables in the value are not expanded. +.It Ic .info Ar message +The message is printed along with the name of the makefile and line number. +.It Ic .undef Ar variable +Un-define the specified global variable. +Only global variables may be un-defined. +.It Ic .unexport Ar variable ... +The opposite of +.Ql .export . +The specified global +.Va variable +will be removed from +.Va .MAKE.EXPORTED . +If no variable list is provided, all globals are unexported, +and +.Va .MAKE.EXPORTED +deleted. +.It Ic .unexport-env +Unexport all globals previously exported and +clear the environment inherited from the parent. +This operation will cause a memory leak of the original environment, +so should be used sparingly. +Testing for +.Va .MAKE.LEVEL +being 0, would make sense. +Also note that any variables which originated in the parent environment +should be explicitly preserved if desired. +For example: +.Bd -literal -offset indent +.Li .if ${.MAKE.LEVEL} == 0 +PATH := ${PATH} +.Li .unexport-env +.Li .export PATH +.Li .endif +.Pp +.Ed +Would result in an environment containing only +.Ql Ev PATH , +which is the minimal useful environment. +Actually +.Ql Ev .MAKE.LEVEL +will also be pushed into the new environment. +.It Ic .warning Ar message +The message prefixed by +.Ql Pa warning: +is printed along with the name of the makefile and line number. +.It Ic \&.if Oo \&! Oc Ns Ar expression Op Ar operator expression ... +Test the value of an expression. +.It Ic .ifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +Test the value of a variable. +.It Ic .ifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +Test the value of a variable. +.It Ic .ifmake Oo \&! Oc Ns Ar target Op Ar operator target ... +Test the target being built. +.It Ic .ifnmake Oo \&! Ns Oc Ar target Op Ar operator target ... +Test the target being built. +.It Ic .else +Reverse the sense of the last conditional. +.It Ic .elif Oo \&! Ns Oc Ar expression Op Ar operator expression ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .if . +.It Ic .elifdef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifdef . +.It Ic .elifndef Oo \&! Oc Ns Ar variable Op Ar operator variable ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifndef . +.It Ic .elifmake Oo \&! Oc Ns Ar target Op Ar operator target ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifmake . +.It Ic .elifnmake Oo \&! Oc Ns Ar target Op Ar operator target ... +A combination of +.Ql Ic .else +followed by +.Ql Ic .ifnmake . +.It Ic .endif +End the body of the conditional. +.El +.Pp +The +.Ar operator +may be any one of the following: +.Bl -tag -width "Cm XX" +.It Cm \&|\&| +Logical OR. +.It Cm \&&& +Logical +.Tn AND ; +of higher precedence than +.Dq \&|\&| . +.El +.Pp +As in C, +.Nm +will only evaluate a conditional as far as is necessary to determine +its value. +Parentheses may be used to change the order of evaluation. +The boolean operator +.Ql Ic \&! +may be used to logically negate an entire +conditional. +It is of higher precedence than +.Ql Ic \&&& . +.Pp +The value of +.Ar expression +may be any of the following: +.Bl -tag -width defined +.It Ic defined +Takes a variable name as an argument and evaluates to true if the variable +has been defined. +.It Ic make +Takes a target name as an argument and evaluates to true if the target +was specified as part of +.Nm Ns 's +command line or was declared the default target (either implicitly or +explicitly, see +.Va .MAIN ) +before the line containing the conditional. +.It Ic empty +Takes a variable, with possible modifiers, and evaluates to true if +the expansion of the variable would result in an empty string. +.It Ic exists +Takes a file name as an argument and evaluates to true if the file exists. +The file is searched for on the system search path (see +.Va .PATH ) . +.It Ic target +Takes a target name as an argument and evaluates to true if the target +has been defined. +.It Ic commands +Takes a target name as an argument and evaluates to true if the target +has been defined and has commands associated with it. +.El +.Pp +.Ar Expression +may also be an arithmetic or string comparison. +Variable expansion is +performed on both sides of the comparison, after which the numerical +values are compared. +A value is interpreted as hexadecimal if it is +preceded by 0x, otherwise it is decimal; octal numbers are not supported. +The standard C relational operators are all supported. +If after +variable expansion, either the left or right hand side of a +.Ql Ic == +or +.Ql Ic "!=" +operator is not a numerical value, then +string comparison is performed between the expanded +variables. +If no relational operator is given, it is assumed that the expanded +variable is being compared against 0, or an empty string in the case +of a string comparison. +.Pp +When +.Nm +is evaluating one of these conditional expressions, and it encounters +a (white-space separated) word it doesn't recognize, either the +.Dq make +or +.Dq defined +expression is applied to it, depending on the form of the conditional. +If the form is +.Ql Ic .ifdef , +.Ql Ic .ifndef , +or +.Ql Ic .if +the +.Dq defined +expression is applied. +Similarly, if the form is +.Ql Ic .ifmake +or +.Ql Ic .ifnmake , +the +.Dq make +expression is applied. +.Pp +If the conditional evaluates to true the parsing of the makefile continues +as before. +If it evaluates to false, the following lines are skipped. +In both cases this continues until a +.Ql Ic .else +or +.Ql Ic .endif +is found. +.Pp +For loops are typically used to apply a set of rules to a list of files. +The syntax of a for loop is: +.Pp +.Bl -tag -compact -width Ds +.It Ic \&.for Ar variable Oo Ar variable ... Oc Ic in Ar expression +.It Aq make-lines +.It Ic \&.endfor +.El +.Pp +After the for +.Ic expression +is evaluated, it is split into words. +On each iteration of the loop, one word is taken and assigned to each +.Ic variable , +in order, and these +.Ic variables +are substituted into the +.Ic make-lines +inside the body of the for loop. +The number of words must come out even; that is, if there are three +iteration variables, the number of words provided must be a multiple +of three. +.Sh COMMENTS +Comments begin with a hash +.Pq Ql \&# +character, anywhere but in a shell +command line, and continue to the end of an unescaped new line. +.Sh SPECIAL SOURCES (ATTRIBUTES) +.Bl -tag -width .IGNOREx +.It Ic .EXEC +Target is never out of date, but always execute commands anyway. +.It Ic .IGNORE +Ignore any errors from the commands associated with this target, exactly +as if they all were preceded by a dash +.Pq Ql \- . +.\" .It Ic .INVISIBLE +.\" XXX +.\" .It Ic .JOIN +.\" XXX +.It Ic .MADE +Mark all sources of this target as being up-to-date. +.It Ic .MAKE +Execute the commands associated with this target even if the +.Fl n +or +.Fl t +options were specified. +Normally used to mark recursive +.Nm Ns s . +.It Ic .META +Create a meta file for the target, even if it is flagged as +.Ic .PHONY , +.Ic .MAKE , +or +.Ic .SPECIAL . +Usage in conjunction with +.Ic .MAKE +is the most likely case. +In "meta" mode, the target is out-of-date if the meta file is missing. +.It Ic .NOMETA +Do not create a meta file for the target. +Meta files are also not created for +.Ic .PHONY , +.Ic .MAKE , +or +.Ic .SPECIAL +targets. +.It Ic .NOMETA_CMP +Ignore differences in commands when deciding if target is out of date. +This is useful if the command contains a value which always changes. +If the number of commands change, though, the target will still be out of date. +The same effect applies to any command line that uses the variable +.Va .OODATE , +which can be used for that purpose even when not otherwise needed or desired: +.Bd -literal -offset indent + +skip-compare-for-some: + @echo this will be compared + @echo this will not ${.OODATE:M.NOMETA_CMP} + @echo this will also be compared + +.Ed +The +.Cm \&:M +pattern suppresses any expansion of the unwanted variable. +.It Ic .NOPATH +Do not search for the target in the directories specified by +.Ic .PATH . +.It Ic .NOTMAIN +Normally +.Nm +selects the first target it encounters as the default target to be built +if no target was specified. +This source prevents this target from being selected. +.It Ic .OPTIONAL +If a target is marked with this attribute and +.Nm +can't figure out how to create it, it will ignore this fact and assume +the file isn't needed or already exists. +.It Ic .PHONY +The target does not +correspond to an actual file; it is always considered to be out of date, +and will not be created with the +.Fl t +option. +Suffix-transformation rules are not applied to +.Ic .PHONY +targets. +.It Ic .PRECIOUS +When +.Nm +is interrupted, it normally removes any partially made targets. +This source prevents the target from being removed. +.It Ic .RECURSIVE +Synonym for +.Ic .MAKE . +.It Ic .SILENT +Do not echo any of the commands associated with this target, exactly +as if they all were preceded by an at sign +.Pq Ql @ . +.It Ic .USE +Turn the target into +.Nm Ns 's +version of a macro. +When the target is used as a source for another target, the other target +acquires the commands, sources, and attributes (except for +.Ic .USE ) +of the +source. +If the target already has commands, the +.Ic .USE +target's commands are appended +to them. +.It Ic .USEBEFORE +Exactly like +.Ic .USE , +but prepend the +.Ic .USEBEFORE +target commands to the target. +.It Ic .WAIT +If +.Ic .WAIT +appears in a dependency line, the sources that precede it are +made before the sources that succeed it in the line. +Since the dependents of files are not made until the file itself +could be made, this also stops the dependents being built unless they +are needed for another branch of the dependency tree. +So given: +.Bd -literal +x: a .WAIT b + echo x +a: + echo a +b: b1 + echo b +b1: + echo b1 + +.Ed +the output is always +.Ql a , +.Ql b1 , +.Ql b , +.Ql x . +.br +The ordering imposed by +.Ic .WAIT +is only relevant for parallel makes. +.El +.Sh SPECIAL TARGETS +Special targets may not be included with other targets, i.e. they must be +the only target specified. +.Bl -tag -width .BEGINx +.It Ic .BEGIN +Any command lines attached to this target are executed before anything +else is done. +.It Ic .DEFAULT +This is sort of a +.Ic .USE +rule for any target (that was used only as a +source) that +.Nm +can't figure out any other way to create. +Only the shell script is used. +The +.Ic .IMPSRC +variable of a target that inherits +.Ic .DEFAULT Ns 's +commands is set +to the target's own name. +.It Ic .DELETE_ON_ERROR +If this target is present in the makefile, it globally causes make to +delete targets whose commands fail. +(By default, only targets whose commands are interrupted during +execution are deleted. +This is the historical behavior.) +This setting can be used to help prevent half-finished or malformed +targets from being left around and corrupting future rebuilds. +.It Ic .END +Any command lines attached to this target are executed after everything +else is done. +.It Ic .ERROR +Any command lines attached to this target are executed when another target fails. +The +.Ic .ERROR_TARGET +variable is set to the target that failed. +See also +.Ic MAKE_PRINT_VAR_ON_ERROR . +.It Ic .IGNORE +Mark each of the sources with the +.Ic .IGNORE +attribute. +If no sources are specified, this is the equivalent of specifying the +.Fl i +option. +.It Ic .INTERRUPT +If +.Nm +is interrupted, the commands for this target will be executed. +.It Ic .MAIN +If no target is specified when +.Nm +is invoked, this target will be built. +.It Ic .MAKEFLAGS +This target provides a way to specify flags for +.Nm +when the makefile is used. +The flags are as if typed to the shell, though the +.Fl f +option will have +no effect. +.\" XXX: NOT YET!!!! +.\" .It Ic .NOTPARALLEL +.\" The named targets are executed in non parallel mode. +.\" If no targets are +.\" specified, then all targets are executed in non parallel mode. +.It Ic .NOPATH +Apply the +.Ic .NOPATH +attribute to any specified sources. +.It Ic .NOTPARALLEL +Disable parallel mode. +.It Ic .NO_PARALLEL +Synonym for +.Ic .NOTPARALLEL , +for compatibility with other pmake variants. +.It Ic .OBJDIR +The source is a new value for +.Ql Va .OBJDIR . +If it exists, +.Nm +will +.Xr chdir 2 +to it and update the value of +.Ql Va .OBJDIR . +.It Ic .ORDER +The named targets are made in sequence. +This ordering does not add targets to the list of targets to be made. +Since the dependents of a target do not get built until the target itself +could be built, unless +.Ql a +is built by another part of the dependency graph, +the following is a dependency loop: +.Bd -literal +\&.ORDER: b a +b: a +.Ed +.Pp +The ordering imposed by +.Ic .ORDER +is only relevant for parallel makes. +.\" XXX: NOT YET!!!! +.\" .It Ic .PARALLEL +.\" The named targets are executed in parallel mode. +.\" If no targets are +.\" specified, then all targets are executed in parallel mode. +.It Ic .PATH +The sources are directories which are to be searched for files not +found in the current directory. +If no sources are specified, any previously specified directories are +deleted. +If the source is the special +.Ic .DOTLAST +target, then the current working +directory is searched last. +.It Ic .PATH. Ns Va suffix +Like +.Ic .PATH +but applies only to files with a particular suffix. +The suffix must have been previously declared with +.Ic .SUFFIXES . +.It Ic .PHONY +Apply the +.Ic .PHONY +attribute to any specified sources. +.It Ic .PRECIOUS +Apply the +.Ic .PRECIOUS +attribute to any specified sources. +If no sources are specified, the +.Ic .PRECIOUS +attribute is applied to every +target in the file. +.It Ic .SHELL +Sets the shell that +.Nm +will use to execute commands. +The sources are a set of +.Ar field=value +pairs. +.Bl -tag -width hasErrCtls +.It Ar name +This is the minimal specification, used to select one of the built-in +shell specs; +.Ar sh , +.Ar ksh , +and +.Ar csh . +.It Ar path +Specifies the path to the shell. +.It Ar hasErrCtl +Indicates whether the shell supports exit on error. +.It Ar check +The command to turn on error checking. +.It Ar ignore +The command to disable error checking. +.It Ar echo +The command to turn on echoing of commands executed. +.It Ar quiet +The command to turn off echoing of commands executed. +.It Ar filter +The output to filter after issuing the +.Ar quiet +command. +It is typically identical to +.Ar quiet . +.It Ar errFlag +The flag to pass the shell to enable error checking. +.It Ar echoFlag +The flag to pass the shell to enable command echoing. +.It Ar newline +The string literal to pass the shell that results in a single newline +character when used outside of any quoting characters. +.El +Example: +.Bd -literal +\&.SHELL: name=ksh path=/bin/ksh hasErrCtl=true \e + check="set \-e" ignore="set +e" \e + echo="set \-v" quiet="set +v" filter="set +v" \e + echoFlag=v errFlag=e newline="'\en'" +.Ed +.It Ic .SILENT +Apply the +.Ic .SILENT +attribute to any specified sources. +If no sources are specified, the +.Ic .SILENT +attribute is applied to every +command in the file. +.It Ic .STALE +This target gets run when a dependency file contains stale entries, having +.Va .ALLSRC +set to the name of that dependency file. +.It Ic .SUFFIXES +Each source specifies a suffix to +.Nm . +If no sources are specified, any previously specified suffixes are deleted. +It allows the creation of suffix-transformation rules. +.Pp +Example: +.Bd -literal +\&.SUFFIXES: .o +\&.c.o: + cc \-o ${.TARGET} \-c ${.IMPSRC} +.Ed +.El +.Sh ENVIRONMENT +.Nm +uses the following environment variables, if they exist: +.Ev MACHINE , +.Ev MACHINE_ARCH , +.Ev MAKE , +.Ev MAKEFLAGS , +.Ev MAKEOBJDIR , +.Ev MAKEOBJDIRPREFIX , +.Ev MAKESYSPATH , +.Ev PWD , +and +.Ev TMPDIR . +.Pp +.Ev MAKEOBJDIRPREFIX +and +.Ev MAKEOBJDIR +may only be set in the environment or on the command line to +.Nm +and not as makefile variables; +see the description of +.Ql Va .OBJDIR +for more details. +.Sh FILES +.Bl -tag -width /usr/share/mk -compact +.It .depend +list of dependencies +.It Makefile +list of dependencies +.It makefile +list of dependencies +.It sys.mk +system makefile +.It /usr/share/mk +system makefile directory +.El +.Sh COMPATIBILITY +The basic make syntax is compatible between different versions of make; +however the special variables, variable modifiers and conditionals are not. +.Ss Older versions +An incomplete list of changes in older versions of +.Nm : +.Pp +The way that .for loop variables are substituted changed after +.Nx 5.0 +so that they still appear to be variable expansions. +In particular this stops them being treated as syntax, and removes some +obscure problems using them in .if statements. +.Pp +The way that parallel makes are scheduled changed in +.Nx 4.0 +so that .ORDER and .WAIT apply recursively to the dependent nodes. +The algorithms used may change again in the future. +.Ss Other make dialects +Other make dialects (GNU make, SVR4 make, POSIX make, etc.) do not +support most of the features of +.Nm +as described in this manual. +Most notably: +.Bl -bullet -offset indent +.It +The +.Ic .WAIT +and +.Ic .ORDER +declarations and most functionality pertaining to parallelization. +(GNU make supports parallelization but lacks these features needed to +control it effectively.) +.It +Directives, including for loops and conditionals and most of the +forms of include files. +(GNU make has its own incompatible and less powerful syntax for +conditionals.) +.It +All built-in variables that begin with a dot. +.It +Most of the special sources and targets that begin with a dot, +with the notable exception of +.Ic .PHONY , +.Ic .PRECIOUS , +and +.Ic .SUFFIXES . +.It +Variable modifiers, except for the +.Dl :old=new +string substitution, which does not portably support globbing with +.Ql % +and historically only works on declared suffixes. +.It +The +.Ic $> +variable even in its short form; most makes support this functionality +but its name varies. +.El +.Pp +Some features are somewhat more portable, such as assignment with +.Ic += , +.Ic ?= , +and +.Ic != . +The +.Ic .PATH +functionality is based on an older feature +.Ic VPATH +found in GNU make and many versions of SVR4 make; however, +historically its behavior is too ill-defined (and too buggy) to rely +upon. +.Pp +The +.Ic $@ +and +.Ic $< +variables are more or less universally portable, as is the +.Ic $(MAKE) +variable. +Basic use of suffix rules (for files only in the current directory, +not trying to chain transformations together, etc.) is also reasonably +portable. +.Sh SEE ALSO +.Xr mkdep 1 +.Sh HISTORY +A +.Nm +command appeared in +.At v7 . +This +.Nm +implementation is based on Adam De Boor's pmake program which was written +for Sprite at Berkeley. +It was designed to be a parallel distributed make running jobs on different +machines using a daemon called +.Dq customs . +.Pp +Historically the target/dependency +.Dq FRC +has been used to FoRCe rebuilding (since the target/dependency +does not exist... unless someone creates an +.Dq FRC +file). +.Sh BUGS +The +.Nm +syntax is difficult to parse without actually acting on the data. +For instance, finding the end of a variable's use should involve scanning +each of the modifiers, using the correct terminator for each field. +In many places +.Nm +just counts {} and () in order to find the end of a variable expansion. +.Pp +There is no way of escaping a space character in a filename. Property changes on: vendor/NetBSD/bmake/20201101/make.1 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make.c =================================================================== --- vendor/NetBSD/bmake/20201101/make.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/make.c (revision 367461) @@ -0,0 +1,1361 @@ +/* $NetBSD: make.c,v 1.186 2020/11/01 17:47:26 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * make.c -- + * The functions which perform the examination of targets and + * their suitability for creation + * + * Interface: + * Make_Run Initialize things for the module and recreate + * whatever needs recreating. Returns TRUE if + * work was (or would have been) done and FALSE + * otherwise. + * + * Make_Update Update all parents of a given child. Performs + * various bookkeeping chores like the updating + * of the youngestChild field of the parent, filling + * of the IMPSRC context variable, etc. It will + * place the parent on the toBeMade queue if it + * should be. + * + * Make_TimeStamp Function to set the parent's youngestChild field + * based on a child's modification time. + * + * Make_DoAllVar 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. + * + * Make_OODate Determine if a target is out-of-date. + * + * Make_HandleUse See if a child is a .USE node for a parent + * and perform the .USE actions if so. + * + * Make_ExpandUse Expand .USE nodes + */ + +#include "make.h" +#include "dir.h" +#include "job.h" + +/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */ +MAKE_RCSID("$NetBSD: make.c,v 1.186 2020/11/01 17:47:26 rillig Exp $"); + +/* Sequence # to detect recursion. */ +static unsigned int checked = 1; + +/* The current fringe of the graph. + * These are nodes which await examination by MakeOODate. + * It is added to by Make_Update and subtracted from by MakeStartJobs */ +static GNodeList *toBeMade; + +static int MakeCheckOrder(void *, void *); +static int MakeBuildParent(void *, void *); + +void +debug_printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(opts.debug_file, fmt, args); + va_end(args); +} + +MAKE_ATTR_DEAD static void +make_abort(GNode *gn, int line) +{ + debug_printf("make_abort from line %d\n", line); + Targ_PrintNode(gn, 2); + Targ_PrintNodes(toBeMade, 2); + Targ_PrintGraph(3); + abort(); +} + +ENUM_VALUE_RTTI_8(GNodeMade, + UNMADE, DEFERRED, REQUESTED, BEINGMADE, + MADE, UPTODATE, ERROR, ABORTED); + +ENUM_FLAGS_RTTI_31(GNodeType, + OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP, + /* OP_OPMASK is omitted since it combines other flags */ + OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE, + OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN, + OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE, + OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT, + OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE, + OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV, + OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK); + +ENUM_FLAGS_RTTI_10(GNodeFlags, + REMAKE, CHILDMADE, FORCE, DONE_WAIT, + DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE, + DONECYCLE, INTERNAL); + +void +GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn, + const char *suffix) +{ + char type_buf[GNodeType_ToStringSize]; + char flags_buf[GNodeFlags_ToStringSize]; + + fprintf(f, "%smade %s, type %s, flags %s%s", + prefix, + Enum_ValueToString(gn->made, GNodeMade_ToStringSpecs), + Enum_FlagsToString(type_buf, sizeof type_buf, + gn->type, GNodeType_ToStringSpecs), + Enum_FlagsToString(flags_buf, sizeof flags_buf, + gn->flags, GNodeFlags_ToStringSpecs), + suffix); +} + +Boolean +GNode_ShouldExecute(GNode *gn) +{ + return !((gn->type & OP_MAKE) ? opts.noRecursiveExecute : opts.noExecute); +} + +/* Update the youngest child of the node, according to the given child. */ +void +Make_TimeStamp(GNode *pgn, GNode *cgn) +{ + if (pgn->youngestChild == NULL || cgn->mtime > pgn->youngestChild->mtime) { + pgn->youngestChild = cgn; + } +} + +/* See if the node is out of date with respect to its sources. + * + * Used by Make_Run when deciding which nodes to place on the + * toBeMade queue initially and by Make_Update to screen out .USE and + * .EXEC nodes. In the latter case, however, any other sort of node + * must be considered out-of-date since at least one of its children + * will have been recreated. + * + * The mtime field of the node and the youngestChild field of its parents + * may be changed. + */ +Boolean +Make_OODate(GNode *gn) +{ + Boolean 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)) == 0) { + (void)Dir_MTime(gn, 1); + if (DEBUG(MAKE)) { + if (gn->mtime != 0) { + debug_printf("modified %s...", Targ_FmtTime(gn->mtime)); + } else { + debug_printf("non-existent..."); + } + } + } + + /* + * A target is remade in one of the following circumstances: + * its modification time is smaller than that of its youngest child and + * it would actually be run (has commands or is not GNode_IsTarget) + * it's the object of a force operator + * it has no children, was on the lhs of an operator and doesn't exist + * already. + * + * Libraries are only considered out-of-date if the archive module says + * they are. + * + * These weird rules are brought to you by Backward-Compatibility and + * the strange people who wrote 'Make'. + */ + if (gn->type & (OP_USE|OP_USEBEFORE)) { + /* + * If the node is a USE node it is *never* out of date + * no matter *what*. + */ + DEBUG0(MAKE, ".USE node..."); + oodate = FALSE; + } else if ((gn->type & OP_LIB) && + ((gn->mtime==0) || Arch_IsLib(gn))) { + DEBUG0(MAKE, "library..."); + + /* + * always out of date if no children and :: target + * or non-existent. + */ + oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || + (gn->youngestChild == NULL && (gn->type & OP_DOUBLEDEP))); + } else if (gn->type & OP_JOIN) { + /* + * A target with the .JOIN attribute is only considered + * out-of-date if any of its children was out-of-date. + */ + DEBUG0(MAKE, ".JOIN node..."); + DEBUG1(MAKE, "source %smade...", gn->flags & CHILDMADE ? "" : "not "); + oodate = (gn->flags & CHILDMADE) ? TRUE : FALSE; + } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { + /* + * A node which is the object of the force (!) operator or which has + * the .EXEC attribute is always considered out-of-date. + */ + if (DEBUG(MAKE)) { + if (gn->type & OP_FORCE) { + debug_printf("! operator..."); + } else if (gn->type & OP_PHONY) { + debug_printf(".PHONY node..."); + } else { + debug_printf(".EXEC node..."); + } + } + oodate = TRUE; + } else if ((gn->youngestChild != NULL && + gn->mtime < gn->youngestChild->mtime) || + (gn->youngestChild == NULL && + ((gn->mtime == 0 && !(gn->type & OP_OPTIONAL)) + || gn->type & OP_DOUBLEDEP))) + { + /* + * A node whose modification time is less than that of its + * youngest child or that has no children (youngestChild == NULL) and + * either doesn't exist (mtime == 0) and it isn't optional + * or was the object of a * :: operator is out-of-date. + * Why? Because that's the way Make does it. + */ + if (DEBUG(MAKE)) { + if (gn->youngestChild != NULL && + gn->mtime < gn->youngestChild->mtime) { + debug_printf("modified before source %s...", + GNode_Path(gn->youngestChild)); + } else if (gn->mtime == 0) { + debug_printf("non-existent and no sources..."); + } else { + debug_printf(":: operator and no sources..."); + } + } + oodate = TRUE; + } else { + /* + * When a non-existing child with no sources + * (such as a typically used FORCE source) has been made and + * the target of the child (usually a directory) has the same + * timestamp as the timestamp just given to the non-existing child + * after it was considered made. + */ + if (DEBUG(MAKE)) { + if (gn->flags & FORCE) + debug_printf("non existing child..."); + } + oodate = (gn->flags & FORCE) ? TRUE : FALSE; + } + +#ifdef USE_META + if (useMeta) { + oodate = meta_oodate(gn, oodate); + } +#endif + + /* + * If the target isn't out-of-date, the parents need to know its + * modification time. Note that targets that appear to be out-of-date + * but aren't, because they have no commands and are GNode_IsTarget, + * have their mtime stay below their children's mtime to keep parents from + * thinking they're out-of-date. + */ + if (!oodate) { + GNodeListNode *ln; + for (ln = gn->parents->first; ln != NULL; ln = ln->next) + Make_TimeStamp(ln->datum, gn); + } + + return oodate; +} + +/* Add the node to the list if it needs to be examined. */ +static int +MakeAddChild(void *gnp, void *lp) +{ + GNode *gn = gnp; + GNodeList *l = lp; + + if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) { + DEBUG2(MAKE, "MakeAddChild: need to examine %s%s\n", + gn->name, gn->cohort_num); + Lst_Enqueue(l, gn); + } + return 0; +} + +/* Find the pathname of a child that was already made. + * + * The path and mtime of the node and the youngestChild of the parent are + * updated; the unmade children count of the parent is decremented. + * + * Input: + * gnp the node to find + */ +static int +MakeFindChild(void *gnp, void *pgnp) +{ + GNode *gn = gnp; + GNode *pgn = pgnp; + + (void)Dir_MTime(gn, 0); + Make_TimeStamp(pgn, gn); + pgn->unmade--; + + return 0; +} + +/* Called by Make_Run and SuffApplyTransform on the downward pass to handle + * .USE and transformation nodes, by copying the child node's commands, type + * flags and children to the parent node. + * + * A .USE node is much like an explicit transformation rule, except its + * commands are always added to the target node, even if the target already + * has commands. + * + * Input: + * cgn The source node, which is either a .USE/.USEBEFORE + * node or a transformation node (OP_TRANSFORM). + * pgn The target node + */ +void +Make_HandleUse(GNode *cgn, GNode *pgn) +{ + GNodeListNode *ln; /* An element in the children list */ + +#ifdef DEBUG_SRC + if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) { + debug_printf("Make_HandleUse: called for plain node %s\n", cgn->name); + return; + } +#endif + + if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) { + if (cgn->type & OP_USEBEFORE) { + /* .USEBEFORE */ + Lst_PrependAll(pgn->commands, cgn->commands); + } else { + /* .USE, or target has no commands */ + Lst_AppendAll(pgn->commands, cgn->commands); + } + } + + for (ln = cgn->children->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + + /* + * Expand variables in the .USE node's name + * and save the unexpanded form. + * We don't need to do this for commands. + * They get expanded properly when we execute. + */ + if (gn->uname == NULL) { + gn->uname = gn->name; + } else { + free(gn->name); + } + (void)Var_Subst(gn->uname, pgn, VARE_WANTRES, &gn->name); + /* TODO: handle errors */ + if (gn->uname && strcmp(gn->name, gn->uname) != 0) { + /* See if we have a target for this node. */ + GNode *tgn = Targ_FindNode(gn->name); + if (tgn != NULL) + gn = tgn; + } + + Lst_Append(pgn->children, gn); + Lst_Append(gn->parents, pgn); + pgn->unmade++; + } + + pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM); +} + +/* Used by Make_Run on the downward pass to handle .USE nodes. Should be + * called before the children are enqueued to be looked at by MakeAddChild. + * + * For a .USE child, the commands, type flags and children are copied to the + * parent node, and since the relation to the .USE node is then no longer + * needed, that relation is removed. + * + * Input: + * cgn the child, which may be a .USE node + * pgn the current parent + */ +static void +MakeHandleUse(GNode *cgn, GNode *pgn, GNodeListNode *ln) +{ + Boolean unmarked; + + unmarked = ((cgn->type & OP_MARK) == 0); + cgn->type |= OP_MARK; + + if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0) + return; + + if (unmarked) + Make_HandleUse(cgn, pgn); + + /* + * This child node is now "made", so we decrement the count of + * unmade children in the parent... We also remove the child + * from the parent's list to accurately reflect the number of decent + * children the parent has. This is used by Make_Run to decide + * whether to queue the parent or examine its children... + */ + Lst_Remove(pgn->children, ln); + pgn->unmade--; +} + +static void +HandleUseNodes(GNode *gn) +{ + GNodeListNode *ln, *nln; + for (ln = gn->children->first; ln != NULL; ln = nln) { + nln = ln->next; + MakeHandleUse(ln->datum, gn, ln); + } +} + + +/* Check the modification time of a gnode, and update it if necessary. + * Return 0 if the gnode does not exist, or its filesystem time if it does. */ +time_t +Make_Recheck(GNode *gn) +{ + time_t mtime = Dir_MTime(gn, 1); + +#ifndef RECHECK + /* + * We can't re-stat the thing, but we can at least take care of rules + * where a target depends on a source that actually creates the + * target, but only if it has changed, e.g. + * + * parse.h : parse.o + * + * parse.o : parse.y + * yacc -d parse.y + * cc -c y.tab.c + * mv y.tab.o parse.o + * cmp -s y.tab.h parse.h || mv y.tab.h parse.h + * + * In this case, if the definitions produced by yacc haven't changed + * from before, parse.h won't have been updated and gn->mtime will + * reflect the current modification time for parse.h. This is + * something of a kludge, I admit, but it's a useful one.. + * XXX: People like to use a rule like + * + * FRC: + * + * To force things that depend on FRC to be made, so we have to + * check for gn->children being empty as well... + */ + if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) { + gn->mtime = now; + } +#else + /* + * This is what Make does and it's actually a good thing, as it + * allows rules like + * + * cmp -s y.tab.h parse.h || cp y.tab.h parse.h + * + * to function as intended. Unfortunately, thanks to the stateless + * nature of NFS (by which I mean the loose coupling of two clients + * using the same file from a common server), there are times + * when the modification time of a file created on a remote + * machine will not be modified before the local stat() implied by + * the Dir_MTime occurs, thus leading us to believe that the file + * is unchanged, wreaking havoc with files that depend on this one. + * + * I have decided it is better to make too much than to make too + * little, so this stuff is commented out unless you're sure it's ok. + * -- ardeb 1/12/88 + */ + /* + * Christos, 4/9/92: If we are saving commands pretend that + * the target is made now. Otherwise archives with ... rules + * don't work! + */ + if (!GNode_ShouldExecute(gn) || (gn->type & OP_SAVE_CMDS) || + (mtime == 0 && !(gn->type & OP_WAIT))) { + DEBUG2(MAKE, " recheck(%s): update time from %s to now\n", + gn->name, Targ_FmtTime(gn->mtime)); + gn->mtime = now; + } + else { + DEBUG2(MAKE, " recheck(%s): current update time: %s\n", + gn->name, Targ_FmtTime(gn->mtime)); + } +#endif + return mtime; +} + +/* + * Set the .PREFIX and .IMPSRC variables for all the implied parents + * of this node. + */ +static void +UpdateImplicitParentsVars(GNode *cgn, const char *cname) +{ + GNodeListNode *ln; + const char *cpref = GNode_VarPrefix(cgn); + + for (ln = cgn->implicitParents->first; ln != NULL; ln = ln->next) { + GNode *pgn = ln->datum; + if (pgn->flags & REMAKE) { + Var_Set(IMPSRC, cname, pgn); + if (cpref != NULL) + Var_Set(PREFIX, cpref, pgn); + } + } +} + +/* Perform update on the parents of a node. Used by JobFinish once + * a node has been dealt with and by MakeStartJobs if it finds an + * up-to-date node. + * + * The unmade field of pgn is decremented and pgn may be placed on + * the toBeMade queue if this field becomes 0. + * + * If the child was made, the parent's flag CHILDMADE field will be + * set true. + * + * If the child is not up-to-date and still does not exist, + * set the FORCE flag on the parents. + * + * If the child wasn't made, the youngestChild field of the parent will be + * altered if the child's mtime is big enough. + * + * Finally, if the child is the implied source for the parent, the + * parent's IMPSRC variable is set appropriately. + */ +void +Make_Update(GNode *cgn) +{ + const char *cname; /* the child's name */ + time_t mtime = -1; + GNodeList *parents; + GNodeListNode *ln; + GNode *centurion; + + /* It is save to re-examine any nodes again */ + checked++; + + cname = GNode_VarTarget(cgn); + + DEBUG2(MAKE, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num); + + /* + * If the child was actually made, see what its modification time is + * now -- some rules won't actually update the file. If the file still + * doesn't exist, make its mtime now. + */ + if (cgn->made != UPTODATE) { + mtime = Make_Recheck(cgn); + } + + /* + * If this is a `::' node, we must consult its first instance + * which is where all parents are linked. + */ + if ((centurion = cgn->centurion) != NULL) { + if (!Lst_IsEmpty(cgn->parents)) + Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num); + centurion->unmade_cohorts--; + if (centurion->unmade_cohorts < 0) + Error("Graph cycles through centurion %s", centurion->name); + } else { + centurion = cgn; + } + parents = centurion->parents; + + /* If this was a .ORDER node, schedule the RHS */ + Lst_ForEachUntil(centurion->order_succ, MakeBuildParent, toBeMade->first); + + /* Now mark all the parents as having one less unmade child */ + for (ln = parents->first; ln != NULL; ln = ln->next) { + GNode *pgn = ln->datum; + + if (DEBUG(MAKE)) + debug_printf("inspect parent %s%s: flags %x, " + "type %x, made %d, unmade %d ", + pgn->name, pgn->cohort_num, pgn->flags, + pgn->type, pgn->made, pgn->unmade - 1); + + if (!(pgn->flags & REMAKE)) { + /* This parent isn't needed */ + DEBUG0(MAKE, "- not needed\n"); + continue; + } + if (mtime == 0 && !(cgn->type & OP_WAIT)) + pgn->flags |= FORCE; + + /* + * If the parent has the .MADE attribute, its timestamp got + * updated to that of its newest child, and its unmade + * child count got set to zero in Make_ExpandUse(). + * However other things might cause us to build one of its + * children - and so we mustn't do any processing here when + * the child build finishes. + */ + if (pgn->type & OP_MADE) { + DEBUG0(MAKE, "- .MADE\n"); + continue; + } + + if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) { + if (cgn->made == MADE) + pgn->flags |= CHILDMADE; + (void)Make_TimeStamp(pgn, cgn); + } + + /* + * A parent must wait for the completion of all instances + * of a `::' dependency. + */ + if (centurion->unmade_cohorts != 0 || centurion->made < MADE) { + DEBUG2(MAKE, "- centurion made %d, %d unmade cohorts\n", + centurion->made, centurion->unmade_cohorts); + continue; + } + + /* One more child of this parent is now made */ + pgn->unmade--; + if (pgn->unmade < 0) { + if (DEBUG(MAKE)) { + debug_printf("Graph cycles through %s%s\n", + pgn->name, pgn->cohort_num); + Targ_PrintGraph(2); + } + Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num); + } + + /* We must always rescan the parents of .WAIT and .ORDER nodes. */ + if (pgn->unmade != 0 && !(centurion->type & OP_WAIT) + && !(centurion->flags & DONE_ORDER)) { + DEBUG0(MAKE, "- unmade children\n"); + continue; + } + if (pgn->made != DEFERRED) { + /* + * Either this parent is on a different branch of the tree, + * or it on the RHS of a .WAIT directive + * or it is already on the toBeMade list. + */ + DEBUG0(MAKE, "- not deferred\n"); + continue; + } + assert(pgn->order_pred != NULL); + if (Lst_ForEachUntil(pgn->order_pred, MakeCheckOrder, 0)) { + /* A .ORDER rule stops us building this */ + continue; + } + if (DEBUG(MAKE)) { + debug_printf("- %s%s made, schedule %s%s (made %d)\n", + cgn->name, cgn->cohort_num, + pgn->name, pgn->cohort_num, pgn->made); + Targ_PrintNode(pgn, 2); + } + /* Ok, we can schedule the parent again */ + pgn->made = REQUESTED; + Lst_Enqueue(toBeMade, pgn); + } + + UpdateImplicitParentsVars(cgn, cname); +} + +static void +UnmarkChildren(GNode *gn) +{ + GNodeListNode *ln; + + for (ln = gn->children->first; ln != NULL; ln = ln->next) { + GNode *child = ln->datum; + child->type &= ~OP_MARK; + } +} + +/* Add a child's name to the ALLSRC and OODATE variables of the given + * node, but only if it has not been given the .EXEC, .USE or .INVISIBLE + * attributes. .EXEC and .USE children are very rarely going to be files, + * so... + * + * If the child is a .JOIN node, its ALLSRC is propagated to the parent. + * + * A child is added to the OODATE variable if its modification time is + * later than that of its parent, as defined by Make, except if the + * parent is a .JOIN node. In that case, it is only added to the OODATE + * variable if it was actually made (since .JOIN nodes don't have + * modification times, the comparison is rather unfair...).. + * + * Input: + * cgn The child to add + * pgn The parent to whose ALLSRC variable it should + * be added + */ +static void +MakeAddAllSrc(GNode *cgn, GNode *pgn) +{ + if (cgn->type & OP_MARK) + return; + cgn->type |= OP_MARK; + + if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) { + const char *child, *allsrc; + + if (cgn->type & OP_ARCHV) + child = GNode_VarMember(cgn); + else + child = GNode_Path(cgn); + if (cgn->type & OP_JOIN) { + allsrc = GNode_VarAllsrc(cgn); + } else { + allsrc = child; + } + if (allsrc != NULL) + Var_Append(ALLSRC, allsrc, pgn); + if (pgn->type & OP_JOIN) { + if (cgn->made == MADE) { + Var_Append(OODATE, child, pgn); + } + } else if ((pgn->mtime < cgn->mtime) || + (cgn->mtime >= now && cgn->made == MADE)) + { + /* + * It goes in the OODATE variable if the parent is younger than the + * child or if the child has been modified more recently than + * the start of the make. This is to keep pmake from getting + * confused if something else updates the parent after the + * make starts (shouldn't happen, I know, but sometimes it + * does). In such a case, if we've updated the kid, the parent + * is likely to have a modification time later than that of + * the kid and anything that relies on the OODATE variable will + * be hosed. + * + * XXX: This will cause all made children to go in the OODATE + * variable, even if they're not touched, if RECHECK isn't defined, + * since cgn->mtime is set to now in Make_Update. According to + * some people, this is good... + */ + Var_Append(OODATE, child, pgn); + } + } +} + +/* Set up the ALLSRC and OODATE variables. Sad to say, it must be + * done separately, rather than while traversing the graph. This is + * because Make defined OODATE to contain all sources whose modification + * times were later than that of the target, *not* those sources that + * were out-of-date. Since in both compatibility and native modes, + * the modification time of the parent isn't found until the child + * has been dealt with, we have to wait until now to fill in the + * variable. As for ALLSRC, the ordering is important and not + * guaranteed when in native mode, so it must be set here, too. + * + * If the node is a .JOIN node, its TARGET variable will be set to + * match its ALLSRC variable. + */ +void +Make_DoAllVar(GNode *gn) +{ + GNodeListNode *ln; + + if (gn->flags & DONE_ALLSRC) + return; + + UnmarkChildren(gn); + for (ln = gn->children->first; ln != NULL; ln = ln->next) + MakeAddAllSrc(ln->datum, gn); + + if (!Var_Exists(OODATE, gn)) { + Var_Set(OODATE, "", gn); + } + if (!Var_Exists(ALLSRC, gn)) { + Var_Set(ALLSRC, "", gn); + } + + if (gn->type & OP_JOIN) + Var_Set(TARGET, GNode_VarAllsrc(gn), gn); + gn->flags |= DONE_ALLSRC; +} + +static int +MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED) +{ + GNode *bn = v_bn; + + if (bn->made >= MADE || !(bn->flags & REMAKE)) + return 0; + + DEBUG2(MAKE, "MakeCheckOrder: Waiting for .ORDER node %s%s\n", + bn->name, bn->cohort_num); + return 1; +} + +static int +MakeBuildChild(void *v_cn, void *toBeMade_next) +{ + GNode *cn = v_cn; + + DEBUG4(MAKE, "MakeBuildChild: inspect %s%s, made %d, type %x\n", + cn->name, cn->cohort_num, cn->made, cn->type); + if (cn->made > DEFERRED) + return 0; + + /* If this node is on the RHS of a .ORDER, check LHSs. */ + assert(cn->order_pred); + if (Lst_ForEachUntil(cn->order_pred, MakeCheckOrder, 0)) { + /* Can't build this (or anything else in this child list) yet */ + cn->made = DEFERRED; + return 0; /* but keep looking */ + } + + DEBUG2(MAKE, "MakeBuildChild: schedule %s%s\n", cn->name, cn->cohort_num); + + cn->made = REQUESTED; + if (toBeMade_next == NULL) + Lst_Append(toBeMade, cn); + else + Lst_InsertBefore(toBeMade, toBeMade_next, cn); + + if (cn->unmade_cohorts != 0) + Lst_ForEachUntil(cn->cohorts, MakeBuildChild, toBeMade_next); + + /* + * If this node is a .WAIT node with unmade children + * then don't add the next sibling. + */ + return cn->type & OP_WAIT && cn->unmade > 0; +} + +/* When a .ORDER LHS node completes we do this on each RHS */ +static int +MakeBuildParent(void *v_pn, void *toBeMade_next) +{ + GNode *pn = v_pn; + + if (pn->made != DEFERRED) + return 0; + + if (MakeBuildChild(pn, toBeMade_next) == 0) { + /* Mark so that when this node is built we reschedule its parents */ + pn->flags |= DONE_ORDER; + } + + return 0; +} + +/* Start as many jobs as possible, taking them from the toBeMade queue. + * + * If the query flag was given to pmake, no job will be started, + * but as soon as an out-of-date target is found, this function + * returns TRUE. At all other times, this function returns FALSE. + */ +static Boolean +MakeStartJobs(void) +{ + GNode *gn; + int have_token = 0; + + while (!Lst_IsEmpty(toBeMade)) { + /* Get token now to avoid cycling job-list when we only have 1 token */ + if (!have_token && !Job_TokenWithdraw()) + break; + have_token = 1; + + gn = Lst_Dequeue(toBeMade); + DEBUG2(MAKE, "Examining %s%s...\n", gn->name, gn->cohort_num); + + if (gn->made != REQUESTED) { + DEBUG1(MAKE, "state %d\n", gn->made); + + make_abort(gn, __LINE__); + } + + if (gn->checked_seqno == checked) { + /* We've already looked at this node since a job finished... */ + DEBUG2(MAKE, "already checked %s%s\n", gn->name, gn->cohort_num); + gn->made = DEFERRED; + continue; + } + gn->checked_seqno = checked; + + if (gn->unmade != 0) { + /* + * We can't build this yet, add all unmade children to toBeMade, + * just before the current first element. + */ + gn->made = DEFERRED; + Lst_ForEachUntil(gn->children, MakeBuildChild, toBeMade->first); + /* and drop this node on the floor */ + DEBUG2(MAKE, "dropped %s%s\n", gn->name, gn->cohort_num); + continue; + } + + gn->made = BEINGMADE; + if (Make_OODate(gn)) { + DEBUG0(MAKE, "out-of-date\n"); + if (opts.queryFlag) { + return TRUE; + } + Make_DoAllVar(gn); + Job_Make(gn); + have_token = 0; + } else { + DEBUG0(MAKE, "up-to-date\n"); + gn->made = UPTODATE; + if (gn->type & OP_JOIN) { + /* + * Even for an up-to-date .JOIN node, we need it to have its + * context variables so references to it get the correct + * value for .TARGET when building up the context variables + * of its parent(s)... + */ + Make_DoAllVar(gn); + } + Make_Update(gn); + } + } + + if (have_token) + Job_TokenReturn(); + + return FALSE; +} + +static void +MakePrintStatusOrderNode(GNode *ogn, GNode *gn) +{ + if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED) + /* not waiting for this one */ + return; + + printf(" `%s%s' has .ORDER dependency against %s%s ", + gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); + GNode_FprintDetails(stdout, "(", ogn, ")\n"); + + if (DEBUG(MAKE) && opts.debug_file != stdout) { + debug_printf(" `%s%s' has .ORDER dependency against %s%s ", + gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); + GNode_FprintDetails(opts.debug_file, "(", ogn, ")\n"); + } +} + +static void +MakePrintStatusOrder(GNode *gn) +{ + GNodeListNode *ln; + for (ln = gn->order_pred->first; ln != NULL; ln = ln->next) + MakePrintStatusOrderNode(ln->datum, gn); +} + +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. + * Callback function for Make_Run via Lst_ForEachUntil. + */ +static Boolean +MakePrintStatus(GNode *gn, int *errors) +{ + if (gn->flags & DONECYCLE) + /* We've completely processed this node before, don't do it again. */ + return FALSE; + + if (gn->unmade == 0) { + gn->flags |= DONECYCLE; + switch (gn->made) { + case UPTODATE: + printf("`%s%s' is up to date.\n", gn->name, gn->cohort_num); + break; + case MADE: + break; + case UNMADE: + case DEFERRED: + case REQUESTED: + case BEINGMADE: + (*errors)++; + printf("`%s%s' was not built", gn->name, gn->cohort_num); + GNode_FprintDetails(stdout, " (", gn, ")!\n"); + if (DEBUG(MAKE) && opts.debug_file != stdout) { + debug_printf("`%s%s' was not built", gn->name, gn->cohort_num); + GNode_FprintDetails(opts.debug_file, " (", gn, ")!\n"); + } + /* Most likely problem is actually caused by .ORDER */ + MakePrintStatusOrder(gn); + break; + default: + /* Errors - already counted */ + printf("`%s%s' not remade because of errors.\n", + gn->name, gn->cohort_num); + if (DEBUG(MAKE) && opts.debug_file != stdout) + debug_printf("`%s%s' not remade because of errors.\n", + gn->name, gn->cohort_num); + break; + } + return FALSE; + } + + DEBUG3(MAKE, "MakePrintStatus: %s%s has %d unmade children\n", + gn->name, gn->cohort_num, gn->unmade); + /* + * If printing cycles and came to one that has unmade children, + * print out the cycle by recursing on its children. + */ + if (!(gn->flags & CYCLE)) { + /* Fist time we've seen this node, check all children */ + gn->flags |= CYCLE; + MakePrintStatusList(gn->children, errors); + /* Mark that this node needn't be processed again */ + gn->flags |= DONECYCLE; + return FALSE; + } + + /* Only output the error once per node */ + gn->flags |= DONECYCLE; + Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num); + if ((*errors)++ > 100) + /* Abandon the whole error report */ + return TRUE; + + /* Reporting for our children will give the rest of the loop */ + MakePrintStatusList(gn->children, errors); + return FALSE; +} + +static void +MakePrintStatusList(GNodeList *gnodes, int *errors) +{ + GNodeListNode *ln; + for (ln = gnodes->first; ln != NULL; ln = ln->next) + if (MakePrintStatus(ln->datum, errors)) + break; +} + +/* Expand .USE nodes and create a new targets list. + * + * Input: + * targs the initial list of targets + */ +void +Make_ExpandUse(GNodeList *targs) +{ + GNodeList *examine; /* List of targets to examine */ + + { + /* XXX: Why is it necessary to copy the list? There shouldn't be + * any modifications to the list, at least the function name + * ExpandUse doesn't suggest that. */ + GNodeListNode *ln; + examine = Lst_New(); + for (ln = targs->first; ln != NULL; ln = ln->next) + Lst_Append(examine, ln->datum); + } + + /* + * Make an initial downward pass over the graph, marking nodes to be made + * as we go down. We call Suff_FindDeps to find where a node is and + * to get some children for it if it has none and also has no commands. + * If the node is a leaf, we stick it on the toBeMade queue to + * be looked at in a minute, otherwise we add its children to our queue + * and go on about our business. + */ + while (!Lst_IsEmpty(examine)) { + GNode *gn = Lst_Dequeue(examine); + + if (gn->flags & REMAKE) + /* We've looked at this one already */ + continue; + gn->flags |= REMAKE; + DEBUG2(MAKE, "Make_ExpandUse: examine %s%s\n", + gn->name, gn->cohort_num); + + if (gn->type & OP_DOUBLEDEP) + Lst_PrependAll(examine, gn->cohorts); + + /* + * Apply any .USE rules before looking for implicit dependencies + * to make sure everything has commands that should... + * Make sure that the TARGET is set, so that we can make + * expansions. + */ + if (gn->type & OP_ARCHV) { + char *eoa, *eon; + eoa = strchr(gn->name, '('); + eon = strchr(gn->name, ')'); + if (eoa == NULL || eon == NULL) + continue; + *eoa = '\0'; + *eon = '\0'; + Var_Set(MEMBER, eoa + 1, gn); + Var_Set(ARCHIVE, gn->name, gn); + *eoa = '('; + *eon = ')'; + } + + (void)Dir_MTime(gn, 0); + Var_Set(TARGET, GNode_Path(gn), gn); + UnmarkChildren(gn); + HandleUseNodes(gn); + + if ((gn->type & OP_MADE) == 0) + Suff_FindDeps(gn); + else { + /* Pretend we made all this node's children */ + Lst_ForEachUntil(gn->children, MakeFindChild, gn); + if (gn->unmade != 0) + printf("Warning: %s%s still has %d unmade children\n", + gn->name, gn->cohort_num, gn->unmade); + } + + if (gn->unmade != 0) + Lst_ForEachUntil(gn->children, MakeAddChild, examine); + } + + Lst_Free(examine); +} + +/* Make the .WAIT node depend on the previous children */ +static void +add_wait_dependency(GNodeListNode *owln, GNode *wn) +{ + GNodeListNode *cln; + GNode *cn; + + for (cln = owln; (cn = cln->datum) != wn; cln = cln->next) { + DEBUG3(MAKE, ".WAIT: add dependency %s%s -> %s\n", + cn->name, cn->cohort_num, wn->name); + + /* XXX: This pattern should be factored out, it repeats often */ + Lst_Append(wn->children, cn); + wn->unmade++; + Lst_Append(cn->parents, wn); + } +} + +/* Convert .WAIT nodes into dependencies. */ +static void +Make_ProcessWait(GNodeList *targs) +{ + GNode *pgn; /* 'parent' node we are examining */ + GNodeListNode *owln; /* Previous .WAIT node */ + GNodeList *examine; /* List of targets to examine */ + + /* + * We need all the nodes to have a common parent in order for the + * .WAIT and .ORDER scheduling to work. + * Perhaps this should be done earlier... + */ + + pgn = Targ_NewGN(".MAIN"); + pgn->flags = REMAKE; + pgn->type = OP_PHONY | OP_DEPENDS; + /* Get it displayed in the diag dumps */ + Lst_Prepend(Targ_List(), pgn); + + { + GNodeListNode *ln; + for (ln = targs->first; ln != NULL; ln = ln->next) { + GNode *cgn = ln->datum; + + Lst_Append(pgn->children, cgn); + Lst_Append(cgn->parents, pgn); + pgn->unmade++; + } + } + + /* Start building with the 'dummy' .MAIN' node */ + MakeBuildChild(pgn, NULL); + + examine = Lst_New(); + Lst_Append(examine, pgn); + + while (!Lst_IsEmpty(examine)) { + GNodeListNode *ln; + + pgn = Lst_Dequeue(examine); + + /* We only want to process each child-list once */ + if (pgn->flags & DONE_WAIT) + continue; + pgn->flags |= DONE_WAIT; + DEBUG1(MAKE, "Make_ProcessWait: examine %s\n", pgn->name); + + if (pgn->type & OP_DOUBLEDEP) + Lst_PrependAll(examine, pgn->cohorts); + + owln = pgn->children->first; + for (ln = pgn->children->first; ln != NULL; ln = ln->next) { + GNode *cgn = ln->datum; + if (cgn->type & OP_WAIT) { + add_wait_dependency(owln, cgn); + owln = ln; + } else { + Lst_Append(examine, cgn); + } + } + } + + Lst_Free(examine); +} + +/*- + *----------------------------------------------------------------------- + * Make_Run -- + * Initialize the nodes to remake and the list of nodes which are + * ready to be made by doing a breadth-first traversal of the graph + * starting from the nodes in the given list. Once this traversal + * is finished, all the 'leaves' of the graph are in the toBeMade + * queue. + * Using this queue and the Job module, work back up the graph, + * calling on MakeStartJobs to keep the job table as full as + * possible. + * + * Input: + * targs the initial list of targets + * + * Results: + * 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 +Make_Run(GNodeList *targs) +{ + int errors; /* Number of errors the Job module reports */ + + /* Start trying to make the current targets... */ + toBeMade = Lst_New(); + + Make_ExpandUse(targs); + Make_ProcessWait(targs); + + if (DEBUG(MAKE)) { + debug_printf("#***# full graph\n"); + Targ_PrintGraph(1); + } + + if (opts.queryFlag) { + /* + * We wouldn't do any work unless we could start some jobs in the + * next loop... (we won't actually start any, of course, this is just + * to see if any of the targets was out of date) + */ + return MakeStartJobs(); + } + /* + * Initialization. At the moment, no jobs are running and until some + * get started, nothing will happen since the remaining upward + * traversal of the graph is performed by the routines in job.c upon + * the finishing of a job. So we fill the Job table as much as we can + * before going into our loop. + */ + (void)MakeStartJobs(); + + /* + * Main Loop: The idea here is that the ending of jobs will take + * care of the maintenance of data structures and the waiting for output + * will cause us to be idle most of the time while our children run as + * much as possible. Because the job table is kept as full as possible, + * the only time when it will be empty is when all the jobs which need + * running have been run, so that is the end condition of this loop. + * Note that the Job module will exit if there were any errors unless the + * keepgoing flag was given. + */ + while (!Lst_IsEmpty(toBeMade) || jobTokensRunning > 0) { + Job_CatchOutput(); + (void)MakeStartJobs(); + } + + errors = Job_Finish(); + + /* + * Print the final status of each target. E.g. if it wasn't made + * because some inferior reported an error. + */ + DEBUG1(MAKE, "done: errors %d\n", errors); + if (errors == 0) { + MakePrintStatusList(targs, &errors); + if (DEBUG(MAKE)) { + debug_printf("done: errors %d\n", errors); + if (errors) + Targ_PrintGraph(4); + } + } + return errors != 0; +} Property changes on: vendor/NetBSD/bmake/20201101/make.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make.h =================================================================== --- vendor/NetBSD/bmake/20201101/make.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/make.h (revision 367461) @@ -0,0 +1,744 @@ +/* $NetBSD: make.h,v 1.179 2020/11/01 17:47:26 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)make.h 8.3 (Berkeley) 6/13/95 + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)make.h 8.3 (Berkeley) 6/13/95 + */ + +/*- + * make.h -- + * The global definitions for pmake + */ + +#ifndef MAKE_MAKE_H +#define MAKE_MAKE_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRING_H +#include +#else +#include +#endif +#include +#include + +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +#if defined(__GNUC__) +#define MAKE_GNUC_PREREQ(x, y) \ + ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ + (__GNUC__ > (x))) +#else /* defined(__GNUC__) */ +#define MAKE_GNUC_PREREQ(x, y) 0 +#endif /* defined(__GNUC__) */ + +#if MAKE_GNUC_PREREQ(2, 7) +#define MAKE_ATTR_UNUSED __attribute__((__unused__)) +#else +#define MAKE_ATTR_UNUSED /* delete */ +#endif + +#if MAKE_GNUC_PREREQ(2, 5) +#define MAKE_ATTR_DEAD __attribute__((__noreturn__)) +#elif defined(__GNUC__) +#define MAKE_ATTR_DEAD __volatile +#else +#define MAKE_ATTR_DEAD /* delete */ +#endif + +#if MAKE_GNUC_PREREQ(2, 7) +#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */ +#endif + +/* + * 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). + */ + +#ifdef 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 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#endif + +#include "lst.h" +#include "enum.h" +#include "hash.h" +#include "make-conf.h" +#include "buf.h" +#include "make_malloc.h" + +/* + * some vendors don't have this --sjg + */ +#if defined(S_IFDIR) && !defined(S_ISDIR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +#define POSIX_SIGNALS +#endif + +typedef enum { + UNMADE, /* Not examined yet */ + DEFERRED, /* Examined once (building child) */ + REQUESTED, /* on toBeMade list */ + BEINGMADE, /* Target is already being made. + * Indicates a cycle in the graph. */ + MADE, /* Was out-of-date and has been made */ + UPTODATE, /* Was already up-to-date */ + ERROR, /* An error occurred while it was being + * made (used only in compat mode) */ + ABORTED /* The target was aborted due to an error + * making an inferior (compat). */ +} GNodeMade; + +/* The OP_ constants are used when parsing a dependency line as a way of + * communicating to other parts of the program the way in which a target + * should be made. + * + * Some of the OP_ constants can be combined, others cannot. */ +typedef enum GNodeType { + /* The dependency operator ':' is the most common one. The commands of + * this node are executed if any child is out-of-date. */ + OP_DEPENDS = 1 << 0, + /* The dependency operator '!' always executes its commands, even if + * its children are up-to-date. */ + OP_FORCE = 1 << 1, + /* The dependency operator '::' behaves like ':', except that it allows + * multiple dependency groups to be defined. Each of these groups is + * executed on its own, independently from the others. */ + OP_DOUBLEDEP = 1 << 2, + + /* Matches the dependency operators ':', '!' and '::'. */ + OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP, + + /* Don't care if the target doesn't exist and can't be created */ + OP_OPTIONAL = 1 << 3, + /* Use associated commands for parents */ + OP_USE = 1 << 4, + /* Target is never out of date, but always execute commands anyway. + * Its time doesn't matter, so it has none...sort of */ + OP_EXEC = 1 << 5, + /* Ignore non-zero exit status from shell commands when creating the node */ + OP_IGNORE = 1 << 6, + /* Don't remove the target when interrupted */ + OP_PRECIOUS = 1 << 7, + /* Don't echo commands when executed */ + OP_SILENT = 1 << 8, + /* Target is a recursive make so its commands should always be executed + * when it is out of date, regardless of the state of the -n or -t flags */ + OP_MAKE = 1 << 9, + /* Target is out-of-date only if any of its children was out-of-date */ + OP_JOIN = 1 << 10, + /* Assume the children of the node have been already made */ + OP_MADE = 1 << 11, + /* Special .BEGIN, .END, .INTERRUPT */ + OP_SPECIAL = 1 << 12, + /* Like .USE, only prepend commands */ + OP_USEBEFORE = 1 << 13, + /* The node is invisible to its parents. I.e. it doesn't show up in the + * parents' local variables. */ + OP_INVISIBLE = 1 << 14, + /* The node is exempt from normal 'main target' processing in parse.c */ + OP_NOTMAIN = 1 << 15, + /* Not a file target; run always */ + OP_PHONY = 1 << 16, + /* Don't search for file in the path */ + OP_NOPATH = 1 << 17, + /* .WAIT phony node */ + OP_WAIT = 1 << 18, + /* .NOMETA do not create a .meta file */ + OP_NOMETA = 1 << 19, + /* .META we _do_ want a .meta file */ + OP_META = 1 << 20, + /* Do not compare commands in .meta file */ + OP_NOMETA_CMP = 1 << 21, + /* Possibly a submake node */ + OP_SUBMAKE = 1 << 22, + + /* Attributes applied by PMake */ + + /* The node is a transformation rule */ + OP_TRANSFORM = 1 << 31, + /* Target is a member of an archive */ + /* XXX: How does this differ from OP_ARCHV? */ + OP_MEMBER = 1 << 30, + /* The node is a library, + * its name has the form "-l" */ + OP_LIB = 1 << 29, + /* The node is an archive member, + * its name has the form "archive(member)" */ + /* XXX: How does this differ from OP_MEMBER? */ + OP_ARCHV = 1 << 28, + /* Target has all the commands it should. Used when parsing to catch + * multiple command groups for a target. Only applies to the dependency + * operators ':' and '!', but not to '::'. */ + OP_HAS_COMMANDS = 1 << 27, + /* The special command "..." has been seen. All further commands from + * this node will be saved on the .END node instead, to be executed at + * the very end. */ + OP_SAVE_CMDS = 1 << 26, + /* Already processed by Suff_FindDeps */ + OP_DEPS_FOUND = 1 << 25, + /* Node found while expanding .ALLSRC */ + OP_MARK = 1 << 24, + + OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM +} GNodeType; + +typedef enum GNodeFlags { + REMAKE = 0x0001, /* this target needs to be (re)made */ + CHILDMADE = 0x0002, /* children of this target were made */ + FORCE = 0x0004, /* children don't exist, and we pretend made */ + DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */ + DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */ + FROM_DEPEND = 0x0020, /* Node created from .depend */ + DONE_ALLSRC = 0x0040, /* We do it once only */ + CYCLE = 0x1000, /* Used by MakePrintStatus */ + DONECYCLE = 0x2000, /* Used by MakePrintStatus */ + INTERNAL = 0x4000 /* Internal use only */ +} GNodeFlags; + +typedef struct List StringList; +typedef struct ListNode StringListNode; + +typedef struct List GNodeList; +typedef struct ListNode GNodeListNode; + +typedef struct List /* of CachedDir */ SearchPath; + +/* A graph node represents a target that can possibly be made, including its + * relation to other targets and a lot of other details. */ +typedef struct GNode { + /* The target's name, such as "clean" or "make.c" */ + char *name; + /* The unexpanded name of a .USE node */ + char *uname; + /* The full pathname of the file belonging to the target. + * XXX: What about .PHONY targets? These don't have an associated path. */ + char *path; + + /* The type of operator used to define the sources (see the OP flags below). + * XXX: This looks like a wild mixture of type and flags. */ + GNodeType type; + GNodeFlags flags; + + /* The state of processing on this node */ + GNodeMade made; + int unmade; /* The number of unmade children */ + + /* The modification time; 0 means the node does not have a corresponding + * file; see Make_OODate. */ + time_t mtime; + struct GNode *youngestChild; + + /* The GNodes for which this node is an implied source. May be empty. + * For example, when there is an inference rule for .c.o, the node for + * file.c has the node for file.o in this list. */ + GNodeList *implicitParents; + + /* Other nodes of the same name, for the '::' operator. */ + GNodeList *cohorts; + + /* The nodes that depend on this one, or in other words, the nodes for + * which this is a source. */ + GNodeList *parents; + /* The nodes on which this one depends. */ + GNodeList *children; + + /* .ORDER nodes we need made. The nodes that must be made (if they're + * made) before this node can be made, but that do not enter into the + * datedness of this node. */ + GNodeList *order_pred; + /* .ORDER nodes who need us. The nodes that must be made (if they're made + * at all) after this node is made, but that do not depend on this node, + * in the normal sense. */ + GNodeList *order_succ; + + /* The "#n" suffix for this cohort, or "" for other nodes */ + char cohort_num[8]; + /* The number of unmade instances on the cohorts list */ + int unmade_cohorts; + /* Pointer to the first instance of a '::' node; only set when on a + * cohorts list */ + struct GNode *centurion; + + /* Last time (sequence number) we tried to make this node */ + unsigned int checked_seqno; + + /* The "local" variables that are specific to this target and this target + * only, such as $@, $<, $?. + * + * Also used for the global variable scopes VAR_GLOBAL, VAR_CMDLINE, + * VAR_INTERNAL, which contain variables with arbitrary names. */ + HashTable /* of Var pointer */ context; + + /* The commands to be given to a shell to create this target. */ + StringList *commands; + + /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone + * but the Suff module) */ + struct Suff *suffix; + + /* filename where the GNode got defined */ + const char *fname; + /* line number where the GNode got defined */ + int lineno; +} GNode; + +/* + * Error levels for parsing. PARSE_FATAL means the process cannot continue + * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO + * mean it can. + */ +typedef enum ParseErrorLevel { + PARSE_FATAL = 1, + PARSE_WARNING, + PARSE_INFO +} ParseErrorLevel; + +/* + * Values returned by Cond_EvalLine and Cond_EvalCondition. + */ +typedef enum CondEvalResult { + COND_PARSE, /* Parse the next lines */ + COND_SKIP, /* Skip the next lines */ + COND_INVALID /* Not a conditional statement */ +} CondEvalResult; + +/* + * Definitions for the "local" variables. Used only for clarity. + */ +#define TARGET "@" /* Target of dependency */ +#define OODATE "?" /* All out-of-date sources */ +#define ALLSRC ">" /* All sources */ +#define IMPSRC "<" /* Source implied by transformation */ +#define PREFIX "*" /* Common prefix */ +#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ +#define MEMBER "%" /* Member in "archive(member)" syntax */ + +#define FTARGET "@F" /* file part of TARGET */ +#define DTARGET "@D" /* directory part of TARGET */ +#define FIMPSRC "type & OP_OPMASK) != 0; +} + +static MAKE_ATTR_UNUSED const char * +GNode_Path(const GNode *gn) +{ + return gn->path != NULL ? gn->path : gn->name; +} + +static MAKE_ATTR_UNUSED const char * +GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); } +static MAKE_ATTR_UNUSED const char * +GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); } + +#ifdef __GNUC__ +#define UNCONST(ptr) ({ \ + union __unconst { \ + const void *__cp; \ + void *__p; \ + } __d; \ + __d.__cp = ptr, __d.__p; }) +#else +#define UNCONST(ptr) (void *)(ptr) +#endif + +/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */ +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef MAXPATHLEN +#define MAXPATHLEN BMAKE_PATH_MAX +#endif +#ifndef PATH_MAX +#define PATH_MAX MAXPATHLEN +#endif + +#if defined(SYSV) +#define KILLPG(pid, sig) kill(-(pid), (sig)) +#else +#define KILLPG(pid, sig) killpg((pid), (sig)) +#endif + +static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch) +{ return isalnum((unsigned char)ch) != 0; } +static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch) +{ return isalpha((unsigned char)ch) != 0; } +static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch) +{ return isdigit((unsigned char)ch) != 0; } +static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch) +{ return isspace((unsigned char)ch) != 0; } +static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch) +{ return isupper((unsigned char)ch) != 0; } +static inline MAKE_ATTR_UNUSED char ch_tolower(char ch) +{ return (char)tolower((unsigned char)ch); } +static inline MAKE_ATTR_UNUSED char ch_toupper(char ch) +{ return (char)toupper((unsigned char)ch); } + +static inline MAKE_ATTR_UNUSED void +cpp_skip_whitespace(const char **pp) +{ + while (ch_isspace(**pp)) + (*pp)++; +} + +static inline MAKE_ATTR_UNUSED void +pp_skip_whitespace(char **pp) +{ + while (ch_isspace(**pp)) + (*pp)++; +} + +#ifdef MAKE_NATIVE +# include +# ifndef lint +# define MAKE_RCSID(id) __RCSID(id) +# endif +#else +# define MAKE_RCSID(id) static volatile char rcsid[] = id +#endif + +#endif /* MAKE_MAKE_H */ Property changes on: vendor/NetBSD/bmake/20201101/make.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make_malloc.c =================================================================== --- vendor/NetBSD/bmake/20201101/make_malloc.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/make_malloc.c (revision 367461) @@ -0,0 +1,94 @@ +/* $NetBSD: make_malloc.c,v 1.23 2020/10/05 19:27:47 rillig Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include + +#include "make.h" + +MAKE_RCSID("$NetBSD: make_malloc.c,v 1.23 2020/10/05 19:27:47 rillig Exp $"); + +#ifndef USE_EMALLOC + +/* die when out of memory. */ +static MAKE_ATTR_DEAD void +enomem(void) +{ + (void)fprintf(stderr, "%s: %s.\n", progname, strerror(ENOMEM)); + exit(2); +} + +/* malloc, but die on error. */ +void * +bmake_malloc(size_t len) +{ + void *p; + + if ((p = malloc(len)) == NULL) + enomem(); + return p; +} + +/* strdup, but die on error. */ +char * +bmake_strdup(const char *str) +{ + size_t len; + char *p; + + len = strlen(str) + 1; + if ((p = malloc(len)) == NULL) + enomem(); + return memcpy(p, str, len); +} + +/* Allocate a string starting from str with exactly len characters. */ +char * +bmake_strldup(const char *str, size_t len) +{ + char *p = bmake_malloc(len + 1); + memcpy(p, str, len); + p[len] = '\0'; + return p; +} + +/* realloc, but die on error. */ +void * +bmake_realloc(void *ptr, size_t size) +{ + if ((ptr = realloc(ptr, size)) == NULL) + enomem(); + return ptr; +} +#endif + +/* Allocate a string from start up to but excluding end. */ +char * +bmake_strsedup(const char *start, const char *end) +{ + return bmake_strldup(start, (size_t)(end - start)); +} Property changes on: vendor/NetBSD/bmake/20201101/make_malloc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/make_malloc.h =================================================================== --- vendor/NetBSD/bmake/20201101/make_malloc.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/make_malloc.h (revision 367461) @@ -0,0 +1,54 @@ +/* $NetBSD: make_malloc.h,v 1.12 2020/10/19 23:43:55 rillig Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef USE_EMALLOC +void *bmake_malloc(size_t); +void *bmake_realloc(void *, size_t); +char *bmake_strdup(const char *); +char *bmake_strldup(const char *, size_t); +#else +#include +#define bmake_malloc(n) emalloc(n) +#define bmake_realloc(p, n) erealloc(p, n) +#define bmake_strdup(s) estrdup(s) +#define bmake_strldup(s, n) estrndup(s, n) +#endif + +char *bmake_strsedup(const char *, const char *); + +/* Thin wrapper around free(3) to avoid the extra function call in case + * p is NULL, to save a few machine instructions. + * + * The case of a NULL pointer happens especially often after Var_Value, + * since only environment variables need to be freed, but not others. */ +static inline MAKE_ATTR_UNUSED void +bmake_free(void *p) +{ + if (p != NULL) + free(p); +} Property changes on: vendor/NetBSD/bmake/20201101/make_malloc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/meta.c =================================================================== --- vendor/NetBSD/bmake/20201101/meta.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/meta.c (revision 367461) @@ -0,0 +1,1709 @@ +/* $NetBSD: meta.c,v 1.136 2020/10/31 12:04:24 rillig Exp $ */ + +/* + * Implement 'meta' mode. + * Adapted from John Birrell's patches to FreeBSD make. + * --sjg + */ +/* + * Copyright (c) 2009-2016, Juniper Networks, Inc. + * Portions Copyright (c) 2009, John Birrell. + * + * 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 + * OWNER 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. + */ +#if defined(USE_META) + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#ifdef HAVE_LIBGEN_H +#include +#elif !defined(HAVE_DIRNAME) +char * dirname(char *); +#endif +#include +#if !defined(HAVE_CONFIG_H) || defined(HAVE_ERR_H) +#include +#endif + +#include "make.h" +#include "dir.h" +#include "job.h" + +#ifdef USE_FILEMON +#include "filemon/filemon.h" +#endif + +static BuildMon Mybm; /* for compat */ +static StringList *metaBailiwick; /* our scope of control */ +static char *metaBailiwickStr; /* string storage for the list */ +static StringList *metaIgnorePaths; /* paths we deliberately ignore */ +static char *metaIgnorePathsStr; /* string storage for the list */ + +#ifndef MAKE_META_IGNORE_PATHS +#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS" +#endif +#ifndef MAKE_META_IGNORE_PATTERNS +#define MAKE_META_IGNORE_PATTERNS ".MAKE.META.IGNORE_PATTERNS" +#endif +#ifndef MAKE_META_IGNORE_FILTER +#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 */ + +extern Boolean forceJobs; +extern Boolean comatMake; +extern char **environ; + +#define MAKE_META_PREFIX ".MAKE.META.PREFIX" + +#ifndef N2U +# define N2U(n, u) (((n) + ((u) - 1)) / (u)) +#endif +#ifndef ROUNDUP +# define ROUNDUP(n, u) (N2U((n), (u)) * (u)) +#endif + +#if !defined(HAVE_STRSEP) +# define strsep(s, d) stresep((s), (d), 0) +#endif + +/* + * Filemon is a kernel module which snoops certain syscalls. + * + * C chdir + * E exec + * F [v]fork + * L [sym]link + * M rename + * R read + * W write + * S stat + * + * See meta_oodate below - we mainly care about 'E' and 'R'. + * + * We can still use meta mode without filemon, but + * the benefits are more limited. + */ +#ifdef USE_FILEMON + +/* + * Open the filemon device. + */ +static void +meta_open_filemon(BuildMon *pbm) +{ + int dupfd; + + pbm->mon_fd = -1; + pbm->filemon = NULL; + if (!useFilemon || !pbm->mfp) + return; + + pbm->filemon = filemon_open(); + if (pbm->filemon == NULL) { + useFilemon = FALSE; + warn("Could not open filemon %s", filemon_path()); + return; + } + + /* + * We use a file outside of '.' + * to avoid a FreeBSD kernel bug where unlink invalidates + * cwd causing getcwd to do a lot more work. + * We only care about the descriptor. + */ + pbm->mon_fd = mkTempFile("filemon.XXXXXX", NULL); + if ((dupfd = dup(pbm->mon_fd)) == -1) { + err(1, "Could not dup filemon output!"); + } + (void)fcntl(dupfd, F_SETFD, FD_CLOEXEC); + if (filemon_setfd(pbm->filemon, dupfd) == -1) { + err(1, "Could not set filemon file descriptor!"); + } + /* we don't need these once we exec */ + (void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC); +} + +/* + * Read the build monitor output file and write records to the target's + * metadata file. + */ +static int +filemon_read(FILE *mfp, int fd) +{ + char buf[BUFSIZ]; + int error; + + /* Check if we're not writing to a meta data file.*/ + if (mfp == NULL) { + if (fd >= 0) + close(fd); /* not interested */ + return 0; + } + /* rewind */ + if (lseek(fd, (off_t)0, SEEK_SET) < 0) { + error = errno; + warn("Could not rewind filemon"); + fprintf(mfp, "\n"); + } else { + ssize_t n; + + error = 0; + fprintf(mfp, "\n-- filemon acquired metadata --\n"); + + while ((n = read(fd, buf, sizeof(buf))) > 0) { + if ((ssize_t)fwrite(buf, 1, (size_t)n, mfp) < n) + error = EIO; + } + } + fflush(mfp); + if (close(fd) < 0) + error = errno; + return error; +} +#endif + +/* + * when realpath() fails, + * we use this, to clean up ./ and ../ + */ +static void +eat_dots(char *buf, size_t bufsz, int dots) +{ + char *cp; + char *cp2; + const char *eat; + size_t eatlen; + + switch (dots) { + case 1: + eat = "/./"; + eatlen = 2; + break; + case 2: + eat = "/../"; + eatlen = 3; + break; + default: + return; + } + + do { + cp = strstr(buf, eat); + if (cp) { + cp2 = cp + eatlen; + if (dots == 2 && cp > buf) { + do { + cp--; + } while (cp > buf && *cp != '/'); + } + if (*cp == '/') { + strlcpy(cp, cp2, bufsz - (size_t)(cp - buf)); + } else { + return; /* can't happen? */ + } + } + } while (cp); +} + +static char * +meta_name(char *mname, size_t mnamelen, + const char *dname, + const char *tname, + const char *cwd) +{ + char buf[MAXPATHLEN]; + char *rp; + char *cp; + char *tp; + char *dtp; + size_t ldname; + + /* + * Weed out relative paths from the target file name. + * We have to be careful though since if target is a + * symlink, the result will be unstable. + * So we use realpath() just to get the dirname, and leave the + * basename as given to us. + */ + if ((cp = strrchr(tname, '/'))) { + if (cached_realpath(tname, buf)) { + if ((rp = strrchr(buf, '/'))) { + rp++; + cp++; + if (strcmp(cp, rp) != 0) + strlcpy(rp, cp, sizeof buf - (size_t)(rp - buf)); + } + tname = buf; + } else { + /* + * We likely have a directory which is about to be made. + * We pretend realpath() succeeded, to have a chance + * of generating the same meta file name that we will + * next time through. + */ + if (tname[0] == '/') { + strlcpy(buf, tname, sizeof(buf)); + } else { + snprintf(buf, sizeof(buf), "%s/%s", cwd, tname); + } + eat_dots(buf, sizeof(buf), 1); /* ./ */ + eat_dots(buf, sizeof(buf), 2); /* ../ */ + tname = buf; + } + } + /* on some systems dirname may modify its arg */ + tp = bmake_strdup(tname); + dtp = dirname(tp); + if (strcmp(dname, dtp) == 0) + snprintf(mname, mnamelen, "%s.meta", tname); + else { + ldname = strlen(dname); + if (strncmp(dname, dtp, ldname) == 0 && dtp[ldname] == '/') + snprintf(mname, mnamelen, "%s/%s.meta", dname, &tname[ldname+1]); + else + snprintf(mname, mnamelen, "%s/%s.meta", dname, tname); + + /* + * Replace path separators in the file name after the + * current object directory path. + */ + cp = mname + strlen(dname) + 1; + + while (*cp != '\0') { + if (*cp == '/') + *cp = '_'; + cp++; + } + } + free(tp); + return mname; +} + +/* + * Return true if running ${.MAKE} + * Bypassed if target is flagged .MAKE + */ +static int +is_submake(void *cmdp, void *gnp) +{ + static const char *p_make = NULL; + static size_t p_len; + char *cmd = cmdp; + GNode *gn = gnp; + char *mp = NULL; + char *cp; + char *cp2; + int rc = 0; /* keep looking */ + + if (!p_make) { + void *dontFreeIt; + p_make = Var_Value(".MAKE", gn, &dontFreeIt); + p_len = strlen(p_make); + } + cp = strchr(cmd, '$'); + if ((cp)) { + (void)Var_Subst(cmd, gn, VARE_WANTRES, &mp); + /* TODO: handle errors */ + cmd = mp; + } + cp2 = strstr(cmd, p_make); + if ((cp2)) { + switch (cp2[p_len]) { + case '\0': + case ' ': + case '\t': + case '\n': + rc = 1; + break; + } + if (cp2 > cmd && rc > 0) { + switch (cp2[-1]) { + case ' ': + case '\t': + case '\n': + break; + default: + rc = 0; /* no match */ + break; + } + } + } + free(mp); + return rc; +} + +typedef struct meta_file_s { + FILE *fp; + GNode *gn; +} meta_file_t; + +static void +printCMD(const char *cmd, meta_file_t *mfp) +{ + char *cmd_freeIt = NULL; + + if (strchr(cmd, '$')) { + (void)Var_Subst(cmd, mfp->gn, VARE_WANTRES, &cmd_freeIt); + /* TODO: handle errors */ + cmd = cmd_freeIt; + } + fprintf(mfp->fp, "CMD %s\n", cmd); + free(cmd_freeIt); +} + +static void +printCMDs(GNode *gn, meta_file_t *mf) +{ + GNodeListNode *ln; + + for (ln = gn->commands->first; ln != NULL; ln = ln->next) + printCMD(ln->datum, mf); +} + +/* + * Certain node types never get a .meta file + */ +#define SKIP_META_TYPE(_type) do { \ + if ((gn->type & __CONCAT(OP_, _type))) { \ + if (verbose) { \ + debug_printf("Skipping meta for %s: .%s\n", \ + gn->name, __STRING(_type)); \ + } \ + return FALSE; \ + } \ +} while (0) + + +/* + * Do we need/want a .meta file ? + */ +static Boolean +meta_needed(GNode *gn, const char *dname, + char *objdir, int verbose) +{ + struct make_stat mst; + + if (verbose) + verbose = DEBUG(META); + + /* This may be a phony node which we don't want meta data for... */ + /* Skip .meta for .BEGIN, .END, .ERROR etc as well. */ + /* Or it may be explicitly flagged as .NOMETA */ + SKIP_META_TYPE(NOMETA); + /* Unless it is explicitly flagged as .META */ + if (!(gn->type & OP_META)) { + SKIP_META_TYPE(PHONY); + SKIP_META_TYPE(SPECIAL); + SKIP_META_TYPE(MAKE); + } + + /* Check if there are no commands to execute. */ + if (Lst_IsEmpty(gn->commands)) { + if (verbose) + debug_printf("Skipping meta for %s: no commands\n", gn->name); + return FALSE; + } + if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) { + /* OP_SUBMAKE is a bit too aggressive */ + if (Lst_ForEachUntil(gn->commands, is_submake, gn)) { + DEBUG1(META, "Skipping meta for %s: .SUBMAKE\n", gn->name); + return FALSE; + } + } + + /* The object directory may not exist. Check it.. */ + if (cached_stat(dname, &mst) != 0) { + if (verbose) + debug_printf("Skipping meta for %s: no .OBJDIR\n", gn->name); + return FALSE; + } + + /* make sure these are canonical */ + if (cached_realpath(dname, objdir)) + dname = objdir; + + /* If we aren't in the object directory, don't create a meta file. */ + if (!metaCurdirOk && strcmp(curdir, dname) == 0) { + if (verbose) + debug_printf("Skipping meta for %s: .OBJDIR == .CURDIR\n", + gn->name); + return FALSE; + } + return TRUE; +} + + +static FILE * +meta_create(BuildMon *pbm, GNode *gn) +{ + meta_file_t mf; + char buf[MAXPATHLEN]; + char objdir[MAXPATHLEN]; + char **ptr; + const char *dname; + const char *tname; + char *fname; + const char *cp; + void *objdir_freeIt; + + mf.fp = NULL; + + dname = Var_Value(".OBJDIR", gn, &objdir_freeIt); + tname = GNode_VarTarget(gn); + + /* if this succeeds objdir is realpath of dname */ + if (!meta_needed(gn, dname, objdir, TRUE)) + goto out; + dname = objdir; + + if (metaVerbose) { + char *mp; + + /* Describe the target we are building */ + (void)Var_Subst("${" MAKE_META_PREFIX "}", gn, VARE_WANTRES, &mp); + /* TODO: handle errors */ + if (*mp) + fprintf(stdout, "%s\n", mp); + free(mp); + } + /* Get the basename of the target */ + if ((cp = strrchr(tname, '/')) == NULL) { + cp = tname; + } else { + cp++; + } + + fflush(stdout); + + if (!writeMeta) + /* Don't create meta data. */ + goto out; + + fname = meta_name(pbm->meta_fname, sizeof(pbm->meta_fname), + dname, tname, objdir); + +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_create: %s\n", fname); +#endif + + if ((mf.fp = fopen(fname, "w")) == NULL) + err(1, "Could not open meta file '%s'", fname); + + fprintf(mf.fp, "# Meta data file %s\n", fname); + + mf.gn = gn; + + printCMDs(gn, &mf); + + fprintf(mf.fp, "CWD %s\n", getcwd(buf, sizeof(buf))); + fprintf(mf.fp, "TARGET %s\n", tname); + cp = GNode_VarOodate(gn); + if (cp && *cp) { + fprintf(mf.fp, "OODATE %s\n", cp); + } + if (metaEnv) { + for (ptr = environ; *ptr != NULL; ptr++) + fprintf(mf.fp, "ENV %s\n", *ptr); + } + + fprintf(mf.fp, "-- command output --\n"); + fflush(mf.fp); + + Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); + Var_Append(".MAKE.META.CREATED", fname, VAR_GLOBAL); + + gn->type |= OP_META; /* in case anyone wants to know */ + if (metaSilent) { + gn->type |= OP_SILENT; + } + out: + bmake_free(objdir_freeIt); + + return mf.fp; +} + +static Boolean +boolValue(char *s) +{ + switch(*s) { + case '0': + case 'N': + case 'n': + case 'F': + case 'f': + return FALSE; + } + return TRUE; +} + +/* + * Initialization we need before reading makefiles. + */ +void +meta_init(void) +{ +#ifdef USE_FILEMON + /* this allows makefiles to test if we have filemon support */ + Var_Set(".MAKE.PATH_FILEMON", filemon_path(), VAR_GLOBAL); +#endif +} + + +#define get_mode_bf(bf, token) \ + if ((cp = strstr(make_mode, token))) \ + bf = boolValue(&cp[sizeof(token) - 1]) + +/* + * Initialization we need after reading makefiles. + */ +void +meta_mode_init(const char *make_mode) +{ + static int once = 0; + char *cp; + void *freeIt; + + useMeta = TRUE; + useFilemon = TRUE; + writeMeta = TRUE; + + if (make_mode) { + if (strstr(make_mode, "env")) + metaEnv = TRUE; + if (strstr(make_mode, "verb")) + metaVerbose = TRUE; + if (strstr(make_mode, "read")) + writeMeta = FALSE; + if (strstr(make_mode, "nofilemon")) + useFilemon = FALSE; + if (strstr(make_mode, "ignore-cmd")) + metaIgnoreCMDs = TRUE; + if (useFilemon) + get_mode_bf(filemonMissing, "missing-filemon="); + get_mode_bf(metaCurdirOk, "curdirok="); + get_mode_bf(metaMissing, "missing-meta="); + get_mode_bf(metaSilent, "silent="); + } + if (metaVerbose && !Var_Exists(MAKE_META_PREFIX, VAR_GLOBAL)) { + /* + * The default value for MAKE_META_PREFIX + * prints the absolute path of the target. + * This works be cause :H will generate '.' if there is no / + * and :tA will resolve that to cwd. + */ + Var_Set(MAKE_META_PREFIX, "Building ${.TARGET:H:tA}/${.TARGET:T}", VAR_GLOBAL); + } + if (once) + return; + once = 1; + memset(&Mybm, 0, sizeof(Mybm)); + /* + * We consider ourselves master of all within ${.MAKE.META.BAILIWICK} + */ + metaBailiwick = Lst_New(); + (void)Var_Subst("${.MAKE.META.BAILIWICK:O:u:tA}", + VAR_GLOBAL, VARE_WANTRES, &metaBailiwickStr); + /* TODO: handle errors */ + str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL); + /* + * We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS} + */ + metaIgnorePaths = Lst_New(); + Var_Append(MAKE_META_IGNORE_PATHS, + "/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL); + (void)Var_Subst("${" MAKE_META_IGNORE_PATHS ":O:u:tA}", + VAR_GLOBAL, VARE_WANTRES, &metaIgnorePathsStr); + /* TODO: handle errors */ + str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL); + + /* + * We ignore any paths that match ${.MAKE.META.IGNORE_PATTERNS} + */ + freeIt = NULL; + if (Var_Value(MAKE_META_IGNORE_PATTERNS, VAR_GLOBAL, &freeIt)) { + metaIgnorePatterns = TRUE; + bmake_free(freeIt); + } + freeIt = NULL; + if (Var_Value(MAKE_META_IGNORE_FILTER, VAR_GLOBAL, &freeIt)) { + metaIgnoreFilter = TRUE; + bmake_free(freeIt); + } +} + +/* + * In each case below we allow for job==NULL + */ +void +meta_job_start(Job *job, GNode *gn) +{ + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + pbm->mfp = meta_create(pbm, gn); +#ifdef USE_FILEMON_ONCE + /* compat mode we open the filemon dev once per command */ + if (job == NULL) + return; +#endif +#ifdef USE_FILEMON + if (pbm->mfp != NULL && useFilemon) { + meta_open_filemon(pbm); + } else { + pbm->mon_fd = -1; + pbm->filemon = NULL; + } +#endif +} + +/* + * The child calls this before doing anything. + * It does not disturb our state. + */ +void +meta_job_child(Job *job) +{ +#ifdef USE_FILEMON + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (pbm->mfp != NULL) { + close(fileno(pbm->mfp)); + if (useFilemon && pbm->filemon) { + pid_t pid; + + pid = getpid(); + if (filemon_setpid_child(pbm->filemon, pid) == -1) { + err(1, "Could not set filemon pid!"); + } + } + } +#endif +} + +void +meta_job_parent(Job *job, pid_t pid) +{ +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (useFilemon && pbm->filemon) { + filemon_setpid_parent(pbm->filemon, pid); + } +#endif +} + +int +meta_job_fd(Job *job) +{ +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (useFilemon && pbm->filemon) { + return filemon_readfd(pbm->filemon); + } +#endif + return -1; +} + +int +meta_job_event(Job *job) +{ +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (useFilemon && pbm->filemon) { + return filemon_process(pbm->filemon); + } +#endif + return 0; +} + +void +meta_job_error(Job *job, GNode *gn, int flags, int status) +{ + char cwd[MAXPATHLEN]; + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + if (!gn) + gn = job->node; + } else { + pbm = &Mybm; + } + if (pbm->mfp != NULL) { + fprintf(pbm->mfp, "\n*** Error code %d%s\n", + status, + (flags & JOB_IGNERR) ? + "(ignored)" : ""); + } + if (gn) { + Var_Set(".ERROR_TARGET", GNode_Path(gn), VAR_GLOBAL); + } + getcwd(cwd, sizeof(cwd)); + Var_Set(".ERROR_CWD", cwd, VAR_GLOBAL); + if (pbm->meta_fname[0]) { + Var_Set(".ERROR_META_FILE", pbm->meta_fname, VAR_GLOBAL); + } + meta_job_finish(job); +} + +void +meta_job_output(Job *job, char *cp, const char *nl) +{ + BuildMon *pbm; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (pbm->mfp != NULL) { + if (metaVerbose) { + static char *meta_prefix = NULL; + static size_t meta_prefix_len; + + if (!meta_prefix) { + char *cp2; + + (void)Var_Subst("${" MAKE_META_PREFIX "}", + VAR_GLOBAL, VARE_WANTRES, &meta_prefix); + /* TODO: handle errors */ + if ((cp2 = strchr(meta_prefix, '$'))) + meta_prefix_len = (size_t)(cp2 - meta_prefix); + else + meta_prefix_len = strlen(meta_prefix); + } + if (strncmp(cp, meta_prefix, meta_prefix_len) == 0) { + cp = strchr(cp+1, '\n'); + if (!cp++) + return; + } + } + fprintf(pbm->mfp, "%s%s", cp, nl); + } +} + +int +meta_cmd_finish(void *pbmp) +{ + int error = 0; + BuildMon *pbm = pbmp; +#ifdef USE_FILEMON + int x; +#endif + + if (!pbm) + pbm = &Mybm; + +#ifdef USE_FILEMON + if (pbm->filemon) { + while (filemon_process(pbm->filemon) > 0) + continue; + if (filemon_close(pbm->filemon) == -1) + error = errno; + x = filemon_read(pbm->mfp, pbm->mon_fd); + if (error == 0 && x != 0) + error = x; + pbm->mon_fd = -1; + pbm->filemon = NULL; + } else +#endif + fprintf(pbm->mfp, "\n"); /* ensure end with newline */ + return error; +} + +int +meta_job_finish(Job *job) +{ + BuildMon *pbm; + int error = 0; + int x; + + if (job != NULL) { + pbm = &job->bm; + } else { + pbm = &Mybm; + } + if (pbm->mfp != NULL) { + error = meta_cmd_finish(pbm); + x = fclose(pbm->mfp); + if (error == 0 && x != 0) + error = errno; + pbm->mfp = NULL; + pbm->meta_fname[0] = '\0'; + } + return error; +} + +void +meta_finish(void) +{ + if (metaBailiwick != NULL) + Lst_Free(metaBailiwick); + free(metaBailiwickStr); + if (metaIgnorePaths != NULL) + Lst_Free(metaIgnorePaths); + free(metaIgnorePathsStr); +} + +/* + * Fetch a full line from fp - growing bufp if needed + * Return length in bufp. + */ +static int +fgetLine(char **bufp, size_t *szp, int o, FILE *fp) +{ + char *buf = *bufp; + size_t bufsz = *szp; + struct stat fs; + int x; + + if (fgets(&buf[o], (int)bufsz - o, fp) != NULL) { + check_newline: + x = o + (int)strlen(&buf[o]); + if (buf[x - 1] == '\n') + return x; + /* + * We need to grow the buffer. + * The meta file can give us a clue. + */ + if (fstat(fileno(fp), &fs) == 0) { + size_t newsz; + char *p; + + newsz = ROUNDUP(((size_t)fs.st_size / 2), BUFSIZ); + if (newsz <= bufsz) + newsz = ROUNDUP((size_t)fs.st_size, BUFSIZ); + if (newsz <= bufsz) + return x; /* truncated */ + DEBUG2(META, "growing buffer %zu -> %zu\n", bufsz, newsz); + p = bmake_realloc(buf, newsz); + if (p) { + *bufp = buf = p; + *szp = bufsz = newsz; + /* fetch the rest */ + if (!fgets(&buf[x], (int)bufsz - x, fp)) + return x; /* truncated! */ + goto check_newline; + } + } + } + return 0; +} + +/* Lst_ForEachUntil wants 1 to stop search */ +static int +prefix_match(void *p, void *q) +{ + const char *prefix = p; + const char *path = q; + size_t n = strlen(prefix); + + return strncmp(path, prefix, n) == 0; +} + +/* See if the path equals prefix or starts with "prefix/". */ +static Boolean +path_starts_with(const char *path, const char *prefix) +{ + size_t n = strlen(prefix); + + if (strncmp(path, prefix, n) != 0) + return FALSE; + return path[n] == '\0' || path[n] == '/'; +} + +static int +meta_ignore(GNode *gn, const char *p) +{ + char fname[MAXPATHLEN]; + + if (p == NULL) + return TRUE; + + if (*p == '/') { + cached_realpath(p, fname); /* clean it up */ + if (Lst_ForEachUntil(metaIgnorePaths, prefix_match, fname)) { +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_oodate: ignoring path: %s\n", p); +#endif + return TRUE; + } + } + + if (metaIgnorePatterns) { + const char *expr; + char *pm; + + Var_Set(".p.", p, gn); + expr = "${" MAKE_META_IGNORE_PATTERNS ":@m@${.p.:M$m}@}"; + (void)Var_Subst(expr, gn, VARE_WANTRES, &pm); + /* TODO: handle errors */ + if (*pm) { +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_oodate: ignoring pattern: %s\n", p); +#endif + free(pm); + return TRUE; + } + free(pm); + } + + if (metaIgnoreFilter) { + char *fm; + + /* skip if filter result is empty */ + snprintf(fname, sizeof(fname), + "${%s:L:${%s:ts:}}", + p, MAKE_META_IGNORE_FILTER); + (void)Var_Subst(fname, gn, VARE_WANTRES, &fm); + /* TODO: handle errors */ + if (*fm == '\0') { +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_oodate: ignoring filtered: %s\n", p); +#endif + free(fm); + return TRUE; + } + free(fm); + } + return FALSE; +} + +/* + * When running with 'meta' functionality, a target can be out-of-date + * if any of the references in its meta data file is more recent. + * We have to track the latestdir on a per-process basis. + */ +#define LCWD_VNAME_FMT ".meta.%d.lcwd" +#define LDIR_VNAME_FMT ".meta.%d.ldir" + +/* + * 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. + */ +#define CHECK_VALID_META(p) if (!(p && *p)) { \ + warnx("%s: %d: malformed", fname, lineno); \ + oodate = TRUE; \ + continue; \ + } + +#define DEQUOTE(p) if (*p == '\'') { \ + char *ep; \ + p++; \ + if ((ep = strchr(p, '\''))) \ + *ep = '\0'; \ + } + +static void +append_if_new(StringList *list, const char *str) +{ + StringListNode *ln; + + for (ln = list->first; ln != NULL; ln = ln->next) + if (strcmp(ln->datum, str) == 0) + return; + Lst_Append(list, bmake_strdup(str)); +} + +Boolean +meta_oodate(GNode *gn, Boolean oodate) +{ + static char *tmpdir = NULL; + static char cwd[MAXPATHLEN]; + char lcwd_vname[64]; + char ldir_vname[64]; + char lcwd[MAXPATHLEN]; + char latestdir[MAXPATHLEN]; + char fname[MAXPATHLEN]; + char fname1[MAXPATHLEN]; + char fname2[MAXPATHLEN]; + char fname3[MAXPATHLEN]; + const char *dname; + const char *tname; + char *p; + char *cp; + char *link_src; + char *move_target; + static size_t cwdlen = 0; + static size_t tmplen = 0; + FILE *fp; + Boolean needOODATE = FALSE; + StringList *missingFiles; + int have_filemon = FALSE; + void *objdir_freeIt; + + if (oodate) + return oodate; /* we're done */ + + dname = Var_Value(".OBJDIR", gn, &objdir_freeIt); + tname = GNode_VarTarget(gn); + + /* if this succeeds fname3 is realpath of dname */ + if (!meta_needed(gn, dname, fname3, FALSE)) + goto oodate_out; + dname = fname3; + + missingFiles = Lst_New(); + + /* + * We need to check if the target is out-of-date. This includes + * checking if the expanded command has changed. This in turn + * 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); + + meta_name(fname, sizeof(fname), dname, tname, dname); + +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_oodate: %s\n", fname); +#endif + + if ((fp = fopen(fname, "r")) != NULL) { + static char *buf = NULL; + static size_t bufsz; + int lineno = 0; + int lastpid = 0; + int pid; + int x; + StringListNode *cmdNode; + struct make_stat mst; + + if (!buf) { + bufsz = 8 * BUFSIZ; + buf = bmake_malloc(bufsz); + } + + if (!cwdlen) { + if (getcwd(cwd, sizeof(cwd)) == NULL) + err(1, "Could not get current working directory"); + cwdlen = strlen(cwd); + } + strlcpy(lcwd, cwd, sizeof(lcwd)); + strlcpy(latestdir, cwd, sizeof(latestdir)); + + if (!tmpdir) { + tmpdir = getTmpdir(); + tmplen = strlen(tmpdir); + } + + /* we want to track all the .meta we read */ + Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); + + cmdNode = gn->commands->first; + while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) { + lineno++; + if (buf[x - 1] == '\n') + buf[x - 1] = '\0'; + else { + warnx("%s: %d: line truncated at %u", fname, lineno, x); + oodate = TRUE; + break; + } + link_src = NULL; + move_target = NULL; + /* Find the start of the build monitor section. */ + if (!have_filemon) { + if (strncmp(buf, "-- filemon", 10) == 0) { + have_filemon = TRUE; + continue; + } + if (strncmp(buf, "# buildmon", 10) == 0) { + have_filemon = TRUE; + continue; + } + } + + /* Delimit the record type. */ + p = buf; +#ifdef DEBUG_META_MODE + DEBUG3(META, "%s: %d: %s\n", fname, lineno, buf); +#endif + strsep(&p, " "); + if (have_filemon) { + /* + * We are in the 'filemon' output section. + * Each record from filemon follows the general form: + * + * + * + * Where: + * is a single letter, denoting the syscall. + * is the process that made the syscall. + * is the arguments (of interest). + */ + switch(buf[0]) { + case '#': /* comment */ + case 'V': /* version */ + break; + default: + /* + * We need to track pathnames per-process. + * + * Each process run by make, starts off in the 'CWD' + * recorded in the .meta file, if it chdirs ('C') + * elsewhere we need to track that - but only for + * that process. If it forks ('F'), we initialize + * the child to have the same cwd as its parent. + * + * We also need to track the 'latestdir' of + * interest. This is usually the same as cwd, but + * not if a process is reading directories. + * + * Each time we spot a different process ('pid') + * we save the current value of 'latestdir' in a + * variable qualified by 'lastpid', and + * re-initialize 'latestdir' to any pre-saved + * value for the current 'pid' and 'CWD' if none. + */ + CHECK_VALID_META(p); + pid = atoi(p); + if (pid > 0 && pid != lastpid) { + const char *ldir; + void *tp; + + if (lastpid > 0) { + /* We need to remember these. */ + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL); + Var_Set(ldir_vname, latestdir, VAR_GLOBAL); + } + snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid); + snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); + lastpid = pid; + ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); + if (ldir) { + strlcpy(latestdir, ldir, sizeof(latestdir)); + bmake_free(tp); + } + ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp); + if (ldir) { + strlcpy(lcwd, ldir, sizeof(lcwd)); + bmake_free(tp); + } + } + /* Skip past the pid. */ + if (strsep(&p, " ") == NULL) + continue; +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + debug_printf("%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + pid, buf[0], cwd, lcwd, latestdir); +#endif + break; + } + + CHECK_VALID_META(p); + + /* Process according to record type. */ + switch (buf[0]) { + case 'X': /* eXit */ + Var_Delete(lcwd_vname, VAR_GLOBAL); + Var_Delete(ldir_vname, VAR_GLOBAL); + lastpid = 0; /* no need to save ldir_vname */ + break; + + case 'F': /* [v]Fork */ + { + char cldir[64]; + int child; + + child = atoi(p); + if (child > 0) { + snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child); + Var_Set(cldir, lcwd, VAR_GLOBAL); + snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); + Var_Set(cldir, latestdir, VAR_GLOBAL); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + debug_printf( + "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + child, cwd, lcwd, latestdir); +#endif + } + } + break; + + case 'C': /* Chdir */ + /* Update lcwd and latest directory. */ + strlcpy(latestdir, p, sizeof(latestdir)); + strlcpy(lcwd, p, sizeof(lcwd)); + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL); + Var_Set(ldir_vname, lcwd, VAR_GLOBAL); +#ifdef DEBUG_META_MODE + DEBUG4(META, "%s: %d: cwd=%s ldir=%s\n", + fname, lineno, cwd, lcwd); +#endif + break; + + case 'M': /* renaMe */ + /* + * For 'M'oves we want to check + * the src as for 'R'ead + * and the target as for 'W'rite. + */ + cp = p; /* save this for a second */ + /* now get target */ + if (strsep(&p, " ") == NULL) + continue; + CHECK_VALID_META(p); + move_target = p; + p = cp; + /* 'L' and 'M' put single quotes around the args */ + DEQUOTE(p); + DEQUOTE(move_target); + /* FALLTHROUGH */ + case 'D': /* unlink */ + if (*p == '/') { + /* remove any missingFiles entries that match p */ + StringListNode *ln = missingFiles->first; + while (ln != NULL) { + StringListNode *next = ln->next; + if (path_starts_with(ln->datum, p)) { + free(ln->datum); + Lst_Remove(missingFiles, ln); + } + ln = next; + } + } + if (buf[0] == 'M') { + /* the target of the mv is a file 'W'ritten */ +#ifdef DEBUG_META_MODE + DEBUG2(META, "meta_oodate: M %s -> %s\n", + p, move_target); +#endif + p = move_target; + goto check_write; + } + break; + case 'L': /* Link */ + /* + * For 'L'inks check + * the src as for 'R'ead + * and the target as for 'W'rite. + */ + link_src = p; + /* now get target */ + if (strsep(&p, " ") == NULL) + continue; + CHECK_VALID_META(p); + /* 'L' and 'M' put single quotes around the args */ + DEQUOTE(p); + DEQUOTE(link_src); +#ifdef DEBUG_META_MODE + DEBUG2(META, "meta_oodate: L %s -> %s\n", link_src, p); +#endif + /* FALLTHROUGH */ + case 'W': /* Write */ + check_write: + /* + * If a file we generated within our bailiwick + * but outside of .OBJDIR is missing, + * we need to do it again. + */ + /* ignore non-absolute paths */ + if (*p != '/') + break; + + if (Lst_IsEmpty(metaBailiwick)) + break; + + /* ignore cwd - normal dependencies handle those */ + if (strncmp(p, cwd, cwdlen) == 0) + break; + + if (!Lst_ForEachUntil(metaBailiwick, prefix_match, p)) + break; + + /* tmpdir might be within */ + if (tmplen > 0 && strncmp(p, tmpdir, tmplen) == 0) + break; + + /* ignore anything containing the string "tmp" */ + if ((strstr("tmp", p))) + break; + + if ((link_src != NULL && cached_lstat(p, &mst) < 0) || + (link_src == NULL && cached_stat(p, &mst) < 0)) { + if (!meta_ignore(gn, p)) + append_if_new(missingFiles, p); + } + break; + check_link_src: + p = link_src; + link_src = NULL; +#ifdef DEBUG_META_MODE + DEBUG1(META, "meta_oodate: L src %s\n", p); +#endif + /* FALLTHROUGH */ + case 'R': /* Read */ + case 'E': /* Exec */ + /* + * Check for runtime files that can't + * be part of the dependencies because + * they are _expected_ to change. + */ + if (meta_ignore(gn, p)) + break; + + /* + * The rest of the record is the file name. + * Check if it's not an absolute path. + */ + { + char *sdirs[4]; + char **sdp; + int sdx = 0; + int found = 0; + + if (*p == '/') { + sdirs[sdx++] = p; /* done */ + } else { + if (strcmp(".", p) == 0) + continue; /* no point */ + + /* Check vs latestdir */ + snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); + sdirs[sdx++] = fname1; + + if (strcmp(latestdir, lcwd) != 0) { + /* Check vs lcwd */ + snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p); + sdirs[sdx++] = fname2; + } + if (strcmp(lcwd, cwd) != 0) { + /* Check vs cwd */ + snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p); + sdirs[sdx++] = fname3; + } + } + sdirs[sdx++] = NULL; + + for (sdp = sdirs; *sdp && !found; sdp++) { +#ifdef DEBUG_META_MODE + DEBUG3(META, "%s: %d: looking for: %s\n", + fname, lineno, *sdp); +#endif + if (cached_stat(*sdp, &mst) == 0) { + found = 1; + p = *sdp; + } + } + if (found) { +#ifdef DEBUG_META_MODE + DEBUG3(META, "%s: %d: found: %s\n", + fname, lineno, p); +#endif + if (!S_ISDIR(mst.mst_mode) && + mst.mst_mtime > gn->mtime) { + DEBUG3(META, "%s: %d: file '%s' is newer than the target...\n", + fname, lineno, p); + oodate = TRUE; + } else if (S_ISDIR(mst.mst_mode)) { + /* Update the latest directory. */ + cached_realpath(p, latestdir); + } + } else if (errno == ENOENT && *p == '/' && + strncmp(p, cwd, cwdlen) != 0) { + /* + * A referenced file outside of CWD is missing. + * We cannot catch every eventuality here... + */ + append_if_new(missingFiles, p); + } + } + if (buf[0] == 'E') { + /* previous latestdir is no longer relevant */ + strlcpy(latestdir, lcwd, sizeof(latestdir)); + } + break; + default: + break; + } + if (!oodate && buf[0] == 'L' && link_src != NULL) + goto check_link_src; + } else if (strcmp(buf, "CMD") == 0) { + /* + * Compare the current command with the one in the + * meta data file. + */ + 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; + } else { + char *cmd = cmdNode->datum; + Boolean hasOODATE = FALSE; + + if (strstr(cmd, "$?")) + hasOODATE = TRUE; + else if ((cp = strstr(cmd, ".OODATE"))) { + /* check for $[{(].OODATE[:)}] */ + if (cp > cmd + 2 && cp[-2] == '$') + hasOODATE = TRUE; + } + if (hasOODATE) { + needOODATE = TRUE; + DEBUG2(META, "%s: %d: cannot compare command using .OODATE\n", + fname, lineno); + } + (void)Var_Subst(cmd, gn, VARE_WANTRES|VARE_UNDEFERR, &cmd); + /* TODO: handle errors */ + + if ((cp = strchr(cmd, '\n'))) { + int n; + + /* + * This command contains newlines, we need to + * fetch more from the .meta file before we + * attempt a comparison. + */ + /* first put the newline back at buf[x - 1] */ + buf[x - 1] = '\n'; + do { + /* now fetch the next line */ + if ((n = fgetLine(&buf, &bufsz, x, fp)) <= 0) + break; + x = n; + lineno++; + if (buf[x - 1] != '\n') { + warnx("%s: %d: line truncated at %u", fname, lineno, x); + break; + } + cp = strchr(++cp, '\n'); + } while (cp); + if (buf[x - 1] == '\n') + buf[x - 1] = '\0'; + } + if (p && + !hasOODATE && + !(gn->type & OP_NOMETA_CMP) && + strcmp(p, cmd) != 0) { + DEBUG4(META, "%s: %d: a build command has changed\n%s\nvs\n%s\n", + fname, lineno, p, cmd); + if (!metaIgnoreCMDs) + oodate = TRUE; + } + free(cmd); + cmdNode = cmdNode->next; + } + } else if (strcmp(buf, "CWD") == 0) { + /* + * Check if there are extra commands now + * that weren't in the meta data file. + */ + 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; + } + 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; + } + } + } + + fclose(fp); + if (!Lst_IsEmpty(missingFiles)) { + DEBUG2(META, "%s: missing files: %s...\n", + fname, (char *)missingFiles->first->datum); + oodate = TRUE; + } + if (!oodate && !have_filemon && filemonMissing) { + DEBUG1(META, "%s: missing filemon data\n", fname); + oodate = TRUE; + } + } else { + if (writeMeta && (metaMissing || (gn->type & OP_META))) { + cp = NULL; + + /* if target is in .CURDIR we do not need a meta file */ + if (gn->path && (cp = strrchr(gn->path, '/')) && cp > gn->path) { + if (strncmp(curdir, gn->path, (size_t)(cp - gn->path)) != 0) { + cp = NULL; /* not in .CURDIR */ + } + } + if (!cp) { + DEBUG1(META, "%s: required but missing\n", fname); + oodate = TRUE; + needOODATE = TRUE; /* assume the worst */ + } + } + } + + Lst_Destroy(missingFiles, free); + + if (oodate && needOODATE) { + /* + * Target uses .OODATE which is empty; or we wouldn't be here. + * We have decided it is oodate, so .OODATE needs to be set. + * All we can sanely do is set it to .ALLSRC. + */ + Var_Delete(OODATE, gn); + Var_Set(OODATE, GNode_VarAllsrc(gn), gn); + } + + oodate_out: + bmake_free(objdir_freeIt); + return oodate; +} + +/* support for compat mode */ + +static int childPipe[2]; + +void +meta_compat_start(void) +{ +#ifdef USE_FILEMON_ONCE + /* + * We need to re-open filemon for each cmd. + */ + BuildMon *pbm = &Mybm; + + if (pbm->mfp != NULL && useFilemon) { + meta_open_filemon(pbm); + } else { + pbm->mon_fd = -1; + pbm->filemon = NULL; + } +#endif + if (pipe(childPipe) < 0) + Punt("Cannot create pipe: %s", strerror(errno)); + /* Set close-on-exec flag for both */ + (void)fcntl(childPipe[0], F_SETFD, FD_CLOEXEC); + (void)fcntl(childPipe[1], F_SETFD, FD_CLOEXEC); +} + +void +meta_compat_child(void) +{ + meta_job_child(NULL); + if (dup2(childPipe[1], 1) < 0 || dup2(1, 2) < 0) + execDie("dup2", "pipe"); +} + +void +meta_compat_parent(pid_t child) +{ + int outfd, metafd, maxfd, nfds; + char buf[BUFSIZ+1]; + fd_set readfds; + + meta_job_parent(NULL, child); + close(childPipe[1]); /* child side */ + outfd = childPipe[0]; +#ifdef USE_FILEMON + metafd = Mybm.filemon ? filemon_readfd(Mybm.filemon) : -1; +#else + metafd = -1; +#endif + maxfd = -1; + if (outfd > maxfd) + maxfd = outfd; + if (metafd > maxfd) + maxfd = metafd; + + while (outfd != -1 || metafd != -1) { + FD_ZERO(&readfds); + if (outfd != -1) { + FD_SET(outfd, &readfds); + } + if (metafd != -1) { + FD_SET(metafd, &readfds); + } + nfds = select(maxfd + 1, &readfds, NULL, NULL, NULL); + if (nfds == -1) { + if (errno == EINTR) + continue; + err(1, "select"); + } + + if (outfd != -1 && FD_ISSET(outfd, &readfds)) do { + /* XXX this is not line-buffered */ + ssize_t nread = read(outfd, buf, sizeof(buf) - 1); + if (nread == -1) + err(1, "read"); + if (nread == 0) { + close(outfd); + outfd = -1; + break; + } + fwrite(buf, 1, (size_t)nread, stdout); + fflush(stdout); + buf[nread] = '\0'; + meta_job_output(NULL, buf, ""); + } while (0); + if (metafd != -1 && FD_ISSET(metafd, &readfds)) { + if (meta_job_event(NULL) <= 0) + metafd = -1; + } + } +} + +#endif /* USE_META */ Property changes on: vendor/NetBSD/bmake/20201101/meta.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/meta.h =================================================================== --- vendor/NetBSD/bmake/20201101/meta.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/meta.h (revision 367461) @@ -0,0 +1,60 @@ +/* $NetBSD: meta.h,v 1.8 2020/10/19 23:43:55 rillig Exp $ */ + +/* + * Things needed for 'meta' mode. + */ +/* + * Copyright (c) 2009-2010, Juniper Networks, Inc. + * + * 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. + * 3. Neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + * OWNER 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. + */ + +typedef struct BuildMon { + char meta_fname[MAXPATHLEN]; + struct filemon *filemon; + int mon_fd; + FILE *mfp; +} BuildMon; + +struct Job; + +void meta_init(void); +void meta_finish(void); +void meta_mode_init(const char *); +void meta_job_start(struct Job *, GNode *); +void meta_job_child(struct Job *); +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 *, int, 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); +void meta_compat_start(void); +void meta_compat_child(void); +void meta_compat_parent(pid_t); + +extern Boolean useMeta; Property changes on: vendor/NetBSD/bmake/20201101/meta.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/metachar.c =================================================================== --- vendor/NetBSD/bmake/20201101/metachar.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/metachar.c (revision 367461) @@ -0,0 +1,85 @@ +/* $NetBSD: metachar.c,v 1.8 2020/10/30 19:14:20 rillig Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#if defined(MAKE_NATIVE) || defined(HAVE_NBTOOL_CONFIG_H) +#include +#endif + +#include "metachar.h" + +MAKE_RCSID("$NetBSD: metachar.c,v 1.8 2020/10/30 19:14:20 rillig Exp $"); + +/* + * The following array is used to make a fast determination of which + * characters are interpreted specially by the shell. If a command + * contains any of these characters, it is executed by the shell, not + * directly by us. + */ + +unsigned char _metachar[128] = { +/* nul soh stx etx eot enq ack bel */ + 1, 0, 0, 0, 0, 0, 0, 0, +/* bs ht nl vt np cr so si */ + 0, 0, 1, 0, 0, 0, 0, 0, +/* dle dc1 dc2 dc3 dc4 nak syn etb */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* can em sub esc fs gs rs us */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* sp ! " # $ % & ' */ + 0, 1, 1, 1, 1, 0, 1, 1, +/* ( ) * + , - . / */ + 1, 1, 1, 0, 0, 0, 0, 0, +/* 0 1 2 3 4 5 6 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 8 9 : ; < = > ? */ + 0, 0, 0, 1, 1, 0, 1, 1, +/* @ A B C D E F G */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* H I J K L M N O */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* P Q R S T U V W */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* X Y Z [ \ ] ^ _ */ + 0, 0, 0, 1, 1, 1, 1, 0, +/* ` a b c d e f g */ + 1, 0, 0, 0, 0, 0, 0, 0, +/* h i j k l m n o */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* p q r s t u v w */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* x y z { | } ~ del */ + 0, 0, 0, 1, 1, 1, 1, 0, +}; + Property changes on: vendor/NetBSD/bmake/20201101/metachar.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/metachar.h =================================================================== --- vendor/NetBSD/bmake/20201101/metachar.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/metachar.h (revision 367461) @@ -0,0 +1,48 @@ +/* $NetBSD: metachar.h,v 1.11 2020/10/31 18:20:00 rillig Exp $ */ + +/*- + * Copyright (c) 2015 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ +#ifndef MAKE_METACHAR_H +#define MAKE_METACHAR_H + +#include "make.h" + +extern unsigned char _metachar[]; + +#define is_shell_metachar(c) _metachar[(c) & 0x7f] + +static inline MAKE_ATTR_UNUSED int +needshell(const char *cmd) +{ + while (!is_shell_metachar(*cmd) && *cmd != ':' && *cmd != '=') + cmd++; + return *cmd != '\0'; +} + +#endif /* MAKE_METACHAR_H */ Property changes on: vendor/NetBSD/bmake/20201101/metachar.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/ChangeLog =================================================================== --- vendor/NetBSD/bmake/20201101/mk/ChangeLog (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/ChangeLog (revision 367461) @@ -0,0 +1,1709 @@ +2020-11-01 Simon J Gerraty + + * install-mk (MK_VERSION): 20201101 + + * dirdeps.mk: most leaf makefiles are not suitable for building + dirdeps.cache so if RELDIR is not "." use dirdeps.mk + +2020-10-28 Simon J Gerraty + + * install-mk (MK_VERSION): 20201028 + + * dirdeps.mk: if we don't have :range use equivalent of M_RANGE + when building dirdeps.cache for leaf directory use -f dirdeps.mk + + * sys.vars.mk: add M_JOT and M_RANGE + +2020-10-01 Simon J Gerraty + + * install-mk (MK_VERSION): 20201001 + + * meta2deps.{py,sh}: throw an error if we don't see filemon version + +2020-09-09 Simon J Gerraty + + * install-mk (MK_VERSION): 20200909 + + * dirdeps-cache-update.mk: use cache_update_dirdep as guard target + +2020-08-26 Simon J Gerraty + + * dirdeps.mk: ensure we cannot confuse a static cache for dynamic + (even more rare that use of static cache is playing clever tricks + with it) + +2020-08-16 Simon J Gerraty + + * dirdeps-cache-update.mk: allow + MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE to control when we + actually update STATIC_DIRDEPS_CACHE. + + * stage-install.sh: create dest directory if needed + before running install(1) + +2020-08-10 Simon J Gerraty + + * dirdeps-targets.mk: include Makefile.dirdeps.options + + * dirdeps.mk: use _TARGETS if defined for DIRDEPS_CACHE + +2020-08-09 Simon J Gerraty + + * dirdeps.mk: default BUILD_DIRDEPS_MAKEFILE to empty + + * dirdeps-cache-update.mk: building parallel cache update + under the context of dirdeps-cached would be ideal, but + is problematic, so it runs as a sibling. + Use cache-built target to ensure we wait for it to complete if + necessary. + +2020-08-06 Simon J Gerraty + + * install-mk (MK_VERSION): 20200806 + + * dirdeps-options: allow TARGET_SPEC to affect option values. + Use DIRDEPS_OPTIONS_QUALIFIER_LIST before using bare MK_* + + * dirdeps-targets.mk: check for MK_STATIC_DIRDEPS_CACHE defined + before looking for STATIC_DIRDEPS_CACHE + +2020-08-05 Simon J Gerraty + + * host-target.mk: Darwin use MACHINE for HOST_ARCH too + + * dirdeps-options.mk: improve debug output + +2020-07-22 Simon J Gerraty + + * dirdeps.mk: set and export DYNAMIC_DIRDEPS_CACHE + for use by dirdeps-cache-update.mk + + * dirdeps-targets.mk: set and export STATIC_DIRDEPS_CACHE + for use by dirdeps-cache-update.mk even if we don't use it. + + * dirdeps-cache-update.mk: we only need worry about the background + update case, with the above, the update from DIRDEPS_CACHE is + simple. + + * meta2deps.py: R 1234 . is not interesting + +2020-07-20 Simon J Gerraty + + * sys.mk: default MK_STATIC_DIRDEPS_CACHE from MK_DIRDEPS_CACHE + + * dirdeps-options.mk: do not :tu DIRDEPS_OPTIONS + allows use of lower case for pseudo options. + + * dirdeps-cache-update.mk: magic to deal with STATIC_DIRDEPS_CACHE + +2020-07-18 Simon J Gerraty + + * dirdeps-targets.mk: Look for Makefile.dirdeps.cache + which allows us to have a static cache for expensive targets. + Use -DWITHOUT_STATIC_DIRDEPS_CACHE -DWITH_DIRDEPS_CACHE + to regenerate the dirdeps.cache it is a copy of. + +2020-07-17 Simon J Gerraty + + * Get rid of BUILD_AT_LEVEL0, MK_DIRDEPS_BUILD makes more sense. + +2020-07-16 Simon J Gerraty + + * dirdeps.mk (DIRDEP_LOADAVG_REPORT): make it easy to record + load averages at intervals during build. + +2020-07-15 Simon J Gerraty + + * install-mk (MK_VERSION): 20200715 + + * dirdeps.mk: tweak Checking line to make matching Finished + lines for post-build analysis easier. + + * meta.autodep.mk: use !defined(WITHOUT_META_STATS) + + * progs.mk: avoid prog.mk outputting multiple Finished lines + +2020-07-11 Simon J Gerraty + + * dirdeps.mk: further optimize dirdeps.cache + generate a DIRDEPS.${.TARGET} list for other purposes + and improve the layout. + +2020-07-10 Simon J Gerraty + + * dirdeps.mk: optimize content of dirdeps.cache + +2020-06-28 Simon J Gerraty + + * sys/*.mk: make it easier for local*sys.mk to customize by + using ?= + +2020-06-22 Simon J Gerraty + + * gendirdeps.mk (LOCAL_DEPENDS_GUARD): if we don't build at level 0 + it is much safer to guard local depends with a simple check for + .MAKE.LEVEL > 0 + +2020-06-10 Simon J Gerraty + + * install-mk (MK_VERSION): 20200610 + + * mkopt.sh: this needs posix shell so #!/bin/sh should be ok + +2020-06-06 Simon J Gerraty + + * install-mk (MK_VERSION): 20200606 + + * dirdeps-targets.mk: allow for filtering of .TARGETS + + * meta2deps.py: fix bug in processing 'L'ink and 'M'ove + entries - and we don't care about 'W'rite entries. + Also ignore absolute paths that do not exist. + +2020-05-25 Simon J Gerraty + + * install-mk (MK_VERSION): 20200525 + + * init.mk: expand and simplify handling of qualified vars + like CPPFLAGS.${.TARGET:T} + +2020-05-15 Simon J Gerraty + + * install-mk (MK_VERSION): 20200515 + + * dirdeps.mk: set _debug_* earlier and allow passing -d* + flags to submake when building DIRDEPS_CACHE + +2020-05-09 Simon J Gerraty + + * whats.mk: more easily extensible + +2020-05-02 Simon J Gerraty + + * whats.mk: greatly simplify by adding what.c to SRCS + +2020-05-01 Simon J Gerraty + + * whats.mk: for libs take care how we add to *OBJS + + * lib.mk: : works better with whats.mk + +2020-04-25 Simon J Gerraty + + * install-mk (MK_VERSION): 20200420 + + * meta.stage.mk: it is not a STAGE_CONFLICT if some-target.dirdep + contains the same ${RELDIR} and a prefix match for our ${TARGET_SPEC} + +2020-04-16 Simon J Gerraty + + * install-mk (MK_VERSION): 20200416 + + * sys/*.mk: set MAKE_SHELL rather than SHELL so as not to + interfere with user env. + + * sys.mk: default MAKE_SHELL to sh and SHELL to MAKE_SHELL + + * autodep.mk: use MAKE_SHELL. + +2019-11-21 Simon J Gerraty + + * gendirdeps.mk: clear .SUFFIXES to avoid a lot of + wasted effort, and unexport _meta_files when no longer needed as + it consumes space we need for command line. + +2019-11-11 Simon J Gerraty + + * dirdeps.mk _DIRDEP_USE: use DIRDEP_DIR and add + DIRDEP_USE_PRELUDE at start - facilitates job distribution + +2019-10-04 Simon J Gerraty + + * dirdeps-targets.mk: Use TARGET_SPEC_LAST_LIST + defaults to ${${TARGET_SPEC_VARS:[-1]}_LIST} to match valid + TARGET_SPEC qualified depend files. + +2019-10-02 Simon J Gerraty + + * dirdeps-targets.mk: encapsulate logic for finding top-level + targets to set initial DIRDEPS for DIRDEPS_BUILD + +2019-09-27 Simon J Gerraty + + * install-mk (MK_VERSION): 20190911 + + * compiler.mk: set COMPILER_TYPE + +2019-07-17 Simon J Gerraty + + * install-mk (MK_VERSION): 20190704 + + * sys/Darwin.mk: support for Objective-C and clang + +2019-05-30 Simon J Gerraty + + * dirdeps.mk: avoid insanely long command line when generating cache + +2019-05-23 Simon J Gerraty + + * install-mk (MK_VERSION): 20190505 + + * whats.mk: handle corner case SHLIB defined but not LIB + +2018-09-19 Simon J Gerraty + + * install-mk (MK_VERSION): 20180919 + + * dirdeps-options.mk: .undef cannot handle var that expands to + more than one var. + +2018-07-08 Simon J Gerraty + + * meta.stage.mk: allow wildcards in STAGE_FILES.* etc. + +2018-06-01 Simon J Gerraty + + * meta.autodep.mk: export META_FILES to avoid command line limit + * gendirdeps.mk: if we have lots of .meta files put them in + an @list + +2018-05-28 Simon J Gerraty + + * dirdeps-options.mk: use local.dirdeps-options.mk + not local.dirdeps-option.mk + +2018-04-20 Simon J Gerraty + + * install-mk (MK_VERSION): 20180420 + * dirdeps.mk: include local.dirdeps-build.mk when .MAKE.LEVEL > 0 + ie. we are building something. + +2018-04-14 Simon J Gerraty + + * FILES: add dirdeps-options.mk to deal with optional DIRDEPS. + +2018-04-05 Simon J Gerraty + + * install-mk (MK_VERSION): 20180405 + + * ldorder.mk: describe how to use LDORDER_EXTERN_BARRIER + if needed. + +2018-01-18 Simon J Gerraty + + * install-mk (MK_VERSION): 20180118 + + * ldorder.mk: let make compute correct link order + +2017-12-12 Simon J Gerraty + + * install-mk (MK_VERSION): 20171212 + + * gendirdeps.mk: guard against bogus entries in GENDIRDEPS_FILTER + +2017-11-14 Simon J. Gerraty + + * install-mk (MK_VERSION): 20171111 + + * lib.mk: ensure META_NOECHO is set + +2017-10-25 Simon J. Gerraty + + * Allow for host32 on rare occasions. + +2017-10-18 Simon J. Gerraty + + * install-mk (MK_VERSION): 20171018 + + * whats.mk: include what_thing in what_uuid to avoid problem + when building multiple apps in the same directory. + +2017-08-12 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170812 + + * autoconf.mk: Use CONFIGURE_DEPS so Makefile can + add dependencies for config.recheck and config.gen + +2017-06-30 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170630 + + * meta.stage.mk: avoid triggering stage_* targets with nothing to do. + +2017-05-23 Simon J. Gerraty + + * meta2deps.py: take special care of '..' + +2017-05-15 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170515 + + * dirdeps.mk (DEP_EXPORT_VARS): on rare occasions it is + useful/necessary for a Makefile.depend file to export some knobs. + This is complicated when we are doing DIRDEPS_CACHE, so we will + handle export of any variables listed in DEP_EXPORT_VARS. + +2017-05-08 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170505 + + * meta2deps.py: fix botched indenation. + +2017-05-05 Simon J. Gerraty + + * sys/*.mk: Remove setting of MAKE it is unnecessary and + in many cases wrong (basname rather than full path) + + * scripts.mk (SCRIPTSGROUPS): make this more like files.mk and inc.mk + + * init.mk: define realbuild to simplify logic in {lib,prog}.mk etc + +2017-05-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170501 + + * doc.mk: fix typo in DOC_INSTALL_OWN + + * inc.mk: handle INCGROUPS similar to freebsd + + * files.mk: add something for files too + + * add staging logic to lib.mk prog.mk etc. + +2017-04-24 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170424 + + * dirdeps.mk: set NO_DIRDEPS when bootstrapping. + also target of bootstrap-this when sed is needed should be ${_want:T} + +2017-04-18 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170418 + + * auto.obj.mk: if using MAKEOBJDIRPREFIX check if it is a + prefix match for .CURDIR - in which case .CURDIR *is* __objdir. + +2017-04-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170401 + + * meta2deps.py: add is_src so we can check if obj dependency + is also a src dependency. + +2017-03-26 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170326 + + * meta.stage.mk: do nothing if NO_STAGING is defined. + +2017-03-24 Simon J. Gerraty + + * auto.obj.mk: handle the case of __objdir=obj or obj.${MACHINE} etc. + +2017-03-18 Simon J. Gerraty + + * mkopt.sh: treat WITH_*=NO like no; ie. WITHOUT_* + +2017-03-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170301 + + * dirdeps.mk (_build_all_dirs): update this outside test for empty + DIRDEPS. + + * meta.stage.mk: allow multiple inclusion to the extent it makes + sense. + +2017-02-14 Simon J. Gerraty + + * prog.mk (install_links): depends on realinstall + +2017-02-12 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170212 + + * dpadd.mk: avoid applying :T:R twice to DPLIBS entries + +2017-01-30 Simon J. Gerraty + + * install-mk (MK_VERSION): 20170130 + + * dirdeps.mk: use :range if we can. + + * sys.vars.mk: provide M_cmpv if MAKE_VERSION >= 20170130 + + * meta2deps.py: clean paths without using realpath() where possible. + fix sort_unique. + +2016-12-12 Simon J. Gerraty + + * install-mk (MK_VERSION): 20161212 + + * meta2deps.py: set pid_cwd[pid] when we process 'C'hdir, + rather than when we detect pid change. + +2016-12-07 Simon J. Gerraty + + * install-mk (MK_VERSION): 20161207 + + * meta.stage.mk: add stage_as_and_symlink for staging packages. + We build foo.tgz stage_as foo-${VERSION}.tgz but want to be able + to use foo.tgz to reference the latest staged version - so we + make foo.tgz a symlink to it. + Using a target to do both operations ensures we stay in sync. + +2016-11-26 Simon J. Gerraty + + * install-mk (MK_VERSION): 20161126 + + * dirdeps.mk: set DIRDEPS_CACHE before we include local.dirdeps.mk + so it can add dependencies. + +2016-10-10 Simon J. Gerraty + + * dirdeps.mk: set DEP_* before we expand .MAKE.DEPENDFILE_PREFERENCE + do that they can influence the result correctly. + + * dirdeps.mk (${DIRDEPS_CACHE}): make sure we pass on TARGET_SPEC + + * dirdeps.mk: Add ONLY_TARGET_SPEC_LIST and NOT_TARGET_SPEC_LIST + similar to ONLY_MACHINE_LIST and NOT_MACHINE_LIST + +2016-10-05 Simon J. Gerraty + + * dirdeps.mk: remove dependence on jot (normal situations anyway). + Before we read another Makefile.depend* set DEP_* vars from + _DEP_TARGET_SPEC in case it uses any of them with := + When bootstrapping, trim any ,* from extention of chosen _src + Makefile.depend* to get the machine value we subst for. + +2016-09-30 Simon J. Gerraty + + * dirdeps.mk: use TARGET_SPEC_VARS to qualify components added to + DEP_SKIP_DIR and DEP_DIRDEPS_FILTER + + * sys.mk: extract some bits to sys.{debug,vars}.mk + for easier re-use by others. + +2016-09-23 Simon Gerraty + + * lib.mk: Use ${PICO} for extension for PIC objects. + default to .pico (like NetBSD) safe on case insensitive filesystem. + +2016-08-19 Simon J. Gerraty + + * meta.sys.mk (META_COOKIE_TOUCH): use ${.OBJDIR}/${.TARGET:T} as default + +2016-08-15 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160815 + + * dirdeps.mk (.MAKE.META.IGNORE_FILTER): set filter to only + consider Makefile.depend* when checking if DIRDEPS_CACHE is up-to-date. + +2016-08-13 Simon J. Gerraty + + * meta.sys.mk (.MAKE.META.IGNORE_PATHS): + in meta mode we can ignore the mtime of makefiles + +2016-08-02 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160802 + + * lib.mk (libinstall): depends on beforinstall + + * prog.mk (proginstall): depends on beforinstall + patch from Lauri Tirkkonen + + * dirdeps.mk (bootstrap): When bootstrapping; creat + .MAKE.DEPENDFILE_DEFAULT and allow additional filtering via + .MAKE.DEPENDFILE_BOOTSTRAP_SED + + * dirdeps.mk: move some comments to where they make sense. + +2016-07-27 Simon J. Gerraty + + * dirdeps.mk (DIRDEPS_CACHE): no dirname. + +2016-06-02 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160602 + * meta.autodep.mk: when passing META_FILES to gendirdeps.mk + do not apply :T to META_XTRAS + patch from Bryan Drewery at FreeBSD.org. + +2016-05-30 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160530 + * meta.stage.mk: we assume ${CLEANFILES} gets .NOPATH + make it so. + +2016-05-12 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160512 + + * dpadd.mk: always include local.dpadd.mk if it exists + remove some things that better belong in local.dpadd.mk + skip INCLUDES_* for staged libs unless SRC_* defined. + + * own.mk: add INCLUDEDIR + +2016-04-18 Simon J. Gerraty + + * dirdeps.mk: when doing -f dirdeps.mk if target suppies no + TARGET_MACHINE - :E will be empty or match part of path, use + ${MACHINE} + +2016-04-07 Simon J. Gerraty + + * meta.autodep.mk: issue a warning if UPDATE_DEPENDFILE=NO due to + NO_FILEMON_COOKIE + + * dirdeps.mk: move the logic that allows for + make -f dirdeps.mk some/dir.${TARGET_SPEC} + inside the check for !target(_DIRDEP_USE) + +2016-04-04 Simon J. Gerraty + + * Use <> when including local*.mk and others which may exist + elsewhere so that user can better control what they get. + + * meta.autodep.mk (NO_FILEMON_COOKIE): + create a cookie if we ever build dir with nofilemon + so that UPDATE_DEPENDFILE will be forced to NO until cleaned. + +2016-04-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160401 + + * meta2deps.py: fix old print statement when debugging. + + * gendirdeps.mk: META2DEPS_CMD append M2D_EXCLUDES with -X + patch from Bryan Drewery + +2016-03-22 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160317 (St. Pats) + + * warnings.mk: g++ does not like -Wimplicit + + * sys.mk sys/*.mk lib.mk prog.mk: use CXX_SUFFIXES to handle the + pelthora of common suffixes for C++ + + * lib.mk: use .So for shared objects + +2016-03-15 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160315 + + * meta.stage.mk (LN_CP_SCRIPT): do not ln(1) if we have to chmod(1) + normally only applies to scripts. + + * dirdeps.mk: NO_DIRDEPS_BELOW to supress DIRDEPS below RELDIR as + well as outside it. + +2016-03-10 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160310 + + * dirdeps.mk: use targets rather than a list to track DIRDEPS that + we have processed; the list gets very inefficient as number of + DIRDEPS gets large. + + * sys.dependfile.mk: fix comment wrt MACHINE + + * meta.autodep.mk: ignore staged DPADDs when bootstrapping. + patch from Bryan Drewery + +2016-03-02 Simon J. Gerraty + + * meta2deps.sh: don't ignore subdirs. + patch from Bryan Drewery + +2016-02-26 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160226 + + * gendirdeps.mk: mark _DEPENDFILE .NOMETA + +2016-02-20 Simon J. Gerraty + + * dirdeps.mk: we shouldn't normally include .depend but if we do + use .dinclude if we can. + +2016-02-18 Simon J. Gerraty + + * install-mk (MK_VERSION): 20160218 + * sys.clean-env.mk: with recent change to Var_Subst() + we cannot use the '$$' trick, but .export-literal does the job + we need. + * auto.dep.mk: make use .dinclude if we can. + + +2016-02-05 Simon J. Gerraty + + * dirdeps.mk: + Add _build_all_dirs such that local.dirdeps.mk can + add fully qualified dirs to it. + These will be built normally but the current + DEP_RELDIR will not depend on then (to avoid cycles). + This makes it easy to hook things like unit-tests into build. + + +2016-01-21 Simon J. Gerraty + + * dirdeps.mk: add bootstrap-empty + +2015-12-12 Simon J. Gerraty + + * install-mk (MK_VERSION): 20151212 + * auto.obj.mk: do not require MAKEOBJDIRPREFIX to exist. + only apply :tA to __objdir when comparing to .OBJDIR + +2015-11-14 Simon J. Gerraty + + * install-mk (MK_VERSION): 20151111 + + * meta.sys.mk: include sys.dependfile.mk + + * sys.mk (OPTIONS_DEFAULT_NO): use options.mk + to set MK_AUTO_OBJ and MK_DIRDEPS_BUILD + include local.sys.env.mk early + include local.sys.mk later + + * own.mk (OPTIONS_DEFAULT_NO): AUTO_OBJ etc moved to sys.mk + +2015-11-13 Simon J. Gerraty + + * meta.sys.mk (META_COOKIE_TOUCH): + add ${META_COOKIE_TOUCH} to the end of scripts to touch cookie + + * meta.stage.mk: stage_libs should ignore SYMLINKS. + +2015-10-23 Simon J. Gerraty + + * install-mk (MK_VERSION): 20151022 + + * sys.mk: BSD/OS does not have 'type' as a shell builtin. + +2015-10-20 Simon J. Gerraty + + * install-mk (MK_VERSION): 20151020 + + * dirdeps.mk: Add logic for + make -f dirdeps.mk some/dir.${TARGET_SPEC} + +2015-10-14 Simon J. Gerraty + + * install-mk (MK_VERSION): 20151010 + +2015-10-02 Simon J. Gerraty + + * meta.stage.mk: use staging: ${STAGE_TARGETS:... + to have stage_lins run last in non-jobs mode. + Use .ORDER only for jobs mode. + +2015-09-02 Simon J. Gerraty + + * rst2htm.mk: allow for per target flags etc. + +2015-09-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150901 + + * doc.mk: create dir if needed use DOC_INSTALL_OWN + +2015-06-15 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150615 + + * auto.obj.mk: allow use of MAKEOBJDIRPREFIX too. + Follow make's normal precedence rules. + + * gendirdeps.mk: allow customization of the header. + eg. for FreeBSD: + GENDIRDEPS_HEADER= echo '\# ${FreeBSD:L:@v@$$$v$$ @:M*F*}'; + + * meta.autodep.mk: ignore dirdeps.cache* + + * meta.stage.mk: when bootstrapping options it can be handy to + throw warnings rather than errors for staging conflicts. + + * meta.sys.mk: include local.meta.sys.mk for customization + +2015-06-06 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150606 + + * dirdeps.mk: don't rely on manually maintained Makefile.depend + to set DEP_RELDIR and reset DIRDEPS. + By setting DEP_RELDIR ourselves we can skip :tA + + * gendirdeps.mk: skip setting DEP_RELDIR. + +2015-05-24 Simon J. Gerraty + + * dirdeps.mk: avoid wildcards like make(bootstrap*) + +2015-05-20 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150520 + + * dirdeps.mk: when we are building dirdeps cache file we *want* + meta_oodate to look at all the Makefile.depend files, so + set .MAKE.DEPENDFILE to something that won't match. + + * meta.stage.mk: for STAGE_AS_* basename of file may not be unique + so first use absolute path as key. + Also skip staging at level 0. + +2015-04-30 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150430 + + * dirdeps.mk: fix _count_dirdeps for non-cache case. + +2015-04-16 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150411 + bump version + + * own.mk: put AUTO_OBJ in OPTIONS_DEFAULT_NO rather than YES. + it is here mainly for documentation purposes, since + if using auto.obj.mk it is better done via sys.mk + +2015-04-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150401 + + * meta2deps.sh: support @list + + * meta2deps.py: updates from Juniper + o add EXCLUDES + o skip bogus input files. + o treat 'M' and 'L' as both an 'R' and a 'W' + +2015-03-03 Simon J. Gerraty + + * install-mk (MK_VERSION): 20150303 + + * dirdeps.mk: if MK_DIRDEPS_CACHE is yes, use dirdeps-cache + which is built via sub-make so we have a .meta file to tell if + it is out-of-date. + The dirdeps-cache contains the same dependency rules that we + normaly construct on the fly. + This adds a few seconds overhead when the cache is out of date, + but for a large target, the savings can be significant (10-20min). + +2014-11-18 Simon J. Gerraty + + * install-mk (MK_VERSION): 20141118 + + * meta.stage.mk: add stale_staged + + * dirdeps.mk (_DIRDEP_USE_LEVEL): allow this to be tweaked + only useful under very rare conditions such as + FreeBSD's make universe. + + * auto.obj.mk: Allow MK_AUTO_OBJ to set MKOBJDIRS=auto + +2014-11-11 Simon J. Gerraty + + * install-mk (MK_VERSION): 20141111 + + * mkopt.sh: use consistent semantics for _mk_opt and _mk_opts + +2014-11-09 Simon J. Gerraty + + * FILES: include mkopt.sh which allows handling options in shell + scripts in a manner compatible with options.mk + +2014-10-12 Simon J. Gerraty + + * meta.stage.mk: ensure only _STAGED_DIRS under objroot are used + for GENDIRDEPS_FILTER to avoid surprises. + +2014-10-10 Simon J. Gerraty + + * dirdeps.mk (NSkipHostDir): this needs SRCTOP prepended since by + the time it is applied to __depdirs they have. + + * dirdeps.mk fix filtering of _machines since M_dep_qual_fixes + expects patterns like *.${MACHINE} + + * cython.mk (pyprefix?): use pyprefix to find python bits + since prefix might be something else (where we install our + stuff) + +2014-09-11 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140911 + + * dirdeps.mk: add bootstrap target to simplify adding support for + new MACHINE. + +2014-09-01 Simon J. Gerraty + + * gendirdeps.mk: Add handling of GENDIRDEPS_FILTER_DIR_VARS and + GENDIRDEPS_FILTER_VARS to make it easier to produce sharable + Makefile.depend files. + +2014-08-28 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140828 + + * cython.mk: capture logic for building python extension modules + with Cython. + +2014-08-08 Simon J. Gerraty + + * meta.stage.mk (_STAGE_AS_BASENAME_USE): Add StageAs variant + +2014-08-02 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140801 + + * dep.mk: use explicit MKDEP_MK rather than overload MKDEP to + identify the autodep.mk variant. + + * sys.dependfile.mk: delete .MAKE.DEPENDFILE if its + initial value does not match .MAKE.DEPENDFILE_PREFIX + + * meta.autodep.mk: if _bootstrap_dirdeps add RELDIR to DIRDEPS + +2014-05-22 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140522 + + * lib.mk: use CC to link shlib for linux too + patch from Brendan MacDonell + +2014-05-05 Simon J. Gerraty + + * meta.autodep.mk: add _reldir_{finish,failed} for gathering stats + if WITH_META_STATS is defined. + +2014-05-02 Simon J. Gerraty + + * dirdeps.mk: accept -DWITHOUT_DIRDEPS (same a as -DNO_DIRDEPS) + to supress dirdeps outside of .CURDIR. + +2014-04-05 Simon J. Gerraty + + * Fix spelling errors - patch from Pedro Giffuni + +2014-03-14 Simon J. Gerraty + + * install-mk (MK_VERSION): 20140314 + + * dirdeps.mk (beforedirdeps): a handy hook + + * dirdeps.mk (DIRDEP_MAKE): allow the actual command we run + to visit leaf dirs to be intercepted (eg. for distributed + build). + + * dirdeps.mk (__depdirs): ensure // don't sneak in + + * gendirdeps.mk (DIRDEPS): ensure // don't sneak in + + +2014-02-21 Simon J. Gerraty + + * rst2htm.mk (RST2PDF): add support for rst2pdf + +2014-02-14 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * dirdeps.mk (_last_dependfile): use .INCLUDEDFROMFILE if + available. + +2014-02-10 Simon J. Gerraty + + * options.mk: avoid :U so this isn't bmake dependent + +2014-02-09 Simon J. Gerraty + + * options.mk: cleanup and simplify semanitcs + NO_* dominates all, if both WITH_* and WITHOUT_* + are defined then result is DOMINATE_* which defaults to "no". + Ie. WITHOUT_ normally wins. + +2013-12-12 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * meta2deps.py: convert to print function for python3 compat. + we also need to open files with mode 'r' rather than 'rb' + otherwise we get bytes instead of strings. + +2013-10-10 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + + * dirdeps.mk: when TARGET_SPEC_VARS is more than just MACHINE + apply the same filtering (M_dep_qual_fixes) when setting _machines + as _build_dirs. + Also fix the filtering of Makefile.depend files - for reporting + what we are looking for (M_dep_qual_fixes can get confused by + Makefile.depend) + Add some more debug info. + +2013-09-04 Simon J. Gerraty + + * gendirdeps.mk (_objtops): fix typo also + while processing M2D_OBJROOTS to gather qualdir_list + qualify $ql with loop iterator to ensure correct results. + +2013-08-01 Simon J. Gerraty + + * install-mk (MK_VERSION): 20130801 + * libs.mk: update to match progs.mk + +2013-07-26 Simon J. Gerraty + + * install-mk (MK_VERSION): 20130726 + some updates from Juniper and FreeBSD + o meta2deps.py: indicate file and line number when we hit parse + errors + also allow @file to provide huge list of .meta files. + * meta2deps.py: add try_parse() to cleanup the above. + +2013-07-16 Simon J. Gerraty + + * install-mk (MK_VERSION): 20130716 + * own.mk: add GPROG as an option + * prog.mk: honor MK_GPROF==yes + +2013-05-10 Simon J. Gerraty + + * install-mk (MK_VERSION): 20130505 + * gendirdeps.mk, meta2deps.py, meta2deps.sh: handle $TARGET_SPEC + for when $MACHINE isn't enough for objdir distinction. + Bring meta2deps.sh closer to par with meta2deps.py. + +2013-04-18 Simon J. Gerraty + + * meta.stage.mk: set INSTALL to STAGE_INSTALL when making 'all' + also if the target 'beforeinstall' exists, make it depend on + .dirdep (incase it uses STAGE_INSTALL). + +2013-04-17 Simon J. Gerraty + + * install-mk (MK_VERSION): 20130401 ;-) + * meta.stage.mk (STAGE_INSTALL_SH): add stage-install.sh as + wrapper around install(1). + * options.mk (OPTION_PREFIX): Allow a prefix other than MK_ + +2013-03-30 Simon J. Gerraty + + * meta2deps.py (MetaFile.__init__): ensure self.cwd is initialized. + * install-mk (MK_VERSION): bump version + +2013-03-21 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * gendirdeps.mk: do not apply :tA to DPADD entries, since we lose + any trailing /., rather apply :tA only when needed. + * gendirdeps.mk: better mimic meta2deps handling of .dirdep files. + * meta.stage.mk (LN_CP_SCRIPT): Add LnCp to do the ln||cp dance + consistently. + * dirdeps.mk: better describe the dance in sys.mk for TARGET_SPEC. + +2013-03-18 Simon J. Gerraty + + * gendirdeps.mk: revert the dance around .MAKE.DEPENDFILE_DEFAULT + it is simpler to just not update when say building for "host" + (where we know we apply filters to DIRDEPS), and using a + non-machine qualified dependfile. + +2013-03-16 Simon J. Gerraty + + * dirdeps.mk: improve DIRDEPS filtering by allowing DEP_SKIP_DIR + and DEP_DIRDEPS_FILTER to vary by DEP_MACHINE and DEP_TARGET_SPEC + * gendirdeps.mk: ensure _objroot has trailing / if it needs it. + * meta2deps.py: if machine is "host", then also trim + self.host_target from any OBJROOTS. + + +2013-03-11 Simon J. Gerraty + + * gendirdeps.mk: if .MAKE.DEPENDFILE_DEFAULT is not machine + qualified but _DEPENDFILE is, and .MAKE.DEPENDFILE_DEFAULT exists + but _DEPENDFILE does not, compare the new _DEPENDFILE against + .MAKE.DEPENDFILE_DEFAULT and discard if the same. + +2013-03-08 Simon J. Gerraty + + * meta.stage.mk: use STAGE_TARGETS to control .ORDER + and hook to all: via staging: + +2013-03-07 Simon J. Gerraty + + * sys.dependfile.mk (.MAKE.DEPENDFILE_DEFAULT): + use a separate variable for the default .MAKE.DEPENDFILE value + so that it can be controlled independently of + .MAKE.DEPENDFILE_PREFERENCE + + * meta.stage.mk: throw error if cp fails etc. + Stage*() return early if passed no args. + .ORDER stage_* + +2013-03-03 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * gendirdeps.mk: handle multiple M2D_OBJROOTS better. + +2013-02-10 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20130210 + * import latest dirdeps.mk, gendirdeps.mk and meta2deps.py + from Juniper. + o dirdeps.mk now fully supports TARGET_SPEC consisting of more + than just MACHINE. + o no longer use DEP_MACHINE from Makefile.depend* so remove it. + +2013-01-23 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20130123 + * meta.stage.mk: add stage_links (hard links). + if doing hard links, we add dest to link as well. + Default the stage dir for [sym]links to STAGE_OBJTOP since + these are typically specified as absolute paths. + Add -m "mode" flag to StageFiles and StageAs. + +2012-11-11 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20121111 + * autoconf.mk: avoid meta mode seeing changed commands for config.status + * meta.autodep.mk: pass resolved MAKESYSPATH to gendirdeps + in case we were found via .../mk + * sys.clean-env.mk: move it from examples, we and others use it + "as is". + * FILES: add srctop.mk and options.mk + * own.mk: convert to using options.mk + which is modeled after FreeBSD's handling of MK_* + but more flexible. + This allows MK_* for boolean knobs to not be confused + with MK* which can be commands. + + * examples/sys.clean-env.mk: add WITH[OUT]_ to + MAKE_ENV_SAVE_PREFIX_LIST. + Mention that HOME=/var/empty might be a good idea. + +2012-11-08 Simon J. Gerraty + + * sys.dependfile.mk: if not depend file exists, $MACHINE + specific ones are supported but not the default, + check if any exist and follow suit. + +2012-11-06 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20121106 + +2012-11-05 Simon J. Gerraty + + * import latest dirdeps.mk and meta2deps.py from Juniper. + * progs.mk: add MAN and CXXFLAGS to PROG_VARS + also add PROGS_TARGETS and pass on PROG_CXX if it seems + appropriate. + +2012-11-04 Simon J. Gerraty + + * meta.stage.mk: update CLEANFILES + remove redundant cp of .dirdep from STAGE_AS_SCRIPT. + * progs.mk: Add LDADD to PROG_VARS + +2012-10-12 Simon J. Gerraty + + * meta.stage.mk (STAGE_DIR_FILTER): track dirs we stage to in + _STAGED_DIRS so that these can be turned into filters for + GENDIRDEPS_FILTER. + +2012-10-10 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20121010 + * meta.stage.mk (STAGE_DIRDEP_SCRIPT): check that an existing + target.dirdep matches .dirdep + +2012-08-08 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120808 + * import latest meta2deps.py from Juniper. + +2012-07-11 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120711 + * dep.mk: add explicit dependencies on SRCS after applying + SRCS_DEP_FILTER + * meta.autodep.mk: add explicit dependencies on SRCS after + applying SRCS_DEP_FILTER + * meta.autodep.mk: ensure GENDIRDEPS_FILTER is exported if needed. + +2012-06-26 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120626 + * meta.sys.mk: ignore PYTHON if it does not exist + compare ${.MAKE.DEPENDFILE:E} against ${MACHINE} is more reliable. + * meta.stage.mk: examine .MAKE.DEPENDFILE_PREFERENCE for any + entries ending in .${MACHINE} to decide if qualified _dirdep is + needed. + * gendirdeps.mk: only produce unqualified deps if no + .MAKE.DEPENDFILE_PREFERENCE ends in .${MACHINE} + * meta.subdir.mk: apply SUBDIRDEPS_FILTER + +2012-04-20 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120420 + * add sys.dependfile.mk so we can experiment with + .MAKE.DEPENDFILE_PREFERENCE + * meta.autodep.mk: _DEPENDFILE is precious! + +2012-03-15 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120315 + * install-new.mk: avoid being interrupted + +2012-02-26 Simon J. Gerraty + + * man.mk: MAN might have multiple values so be careful with exists(). + +2012-01-19 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20120112 + * fix examples/sys.clean-env.mk so that MAKEOBJDIR is handled + as: MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}' + +2011-12-03 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111201 + * import dirdeps.mk from Juniper sjg@ + o more consistent handling of DEP_MACHINE, especially when + dealing with an odd Makefile.depend, when normally using + Makefile.depend.${MACHINE} + +2011-11-22 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111122 + * meta.autodep.mk: add some debug output, be more crisp about + updating. Use ${.ALLTARGETS:M*.o} as a clue for .depend + +2011-11-13 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111111 + it's too cool to miss + * import meta* updates from Juniper sjg@ + o dirdeps.mk set DEP_MACHINE for Makefile.depend (when we are + normally using Makefile.depend.${MACHINE}), handy for + read-only manually maintained dependencies. + o meta2deps.py add a clear 'ERROR:' token if an exception is raised. + o gendirdeps.mk if ERROR: from meta2deps.py do not update + anything. + +2011-10-30 Simon J. Gerraty + + * install-new.mk separate the cmp and copy logic to its own function. + +2011-10-28 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111028 + * sys.mk: include auto.obj.mk if MKOBJDIRS is set to auto + * subdir.mk: ensure _SUBDIRUSE is provided + * meta.autodep.mk: remove dependency of gendirdeps.mk on auto.obj.mk + * meta.subdir.mk: always allow for Makefile.depend + +2011-10-10 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111010 + o minor tweak to *dirdeps.mk from Juniper sjg@ + +2011-10-01 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20111001 + o add meta2deps.py from Juniper sjg@ + o tweak gendirdeps.mk to work with meta2deps.py when not + cross-building + * autoconf.mk: add autoconf-input as a hook for regenerating + AUTOCONF_INPUTS (configure). + +2011-08-24 Simon J. Gerraty + + * meta.autodep.mk: if we do not have OBJS, .depend isn't a useful + trigger for updating Makefile.depend* + +2011-08-08 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110808 + * obj.mk: minor cleanup + * auto.obj.mk: improve description of Mkdirs and honor NO_OBJ too. + +2011-08-01 Simon J. Gerraty + + * auto.obj.mk (.OBJDIR): throw an error if we cannot use the + specified dir. + +2011-06-28 Simon J. Gerraty + + * meta.autodep.mk: if XMAKE_META_FILE is set + the makefile uses a foreign make, and so dependencies + can only be gathered from a clean tree build. + +2011-06-24 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110622 + * meta.autodep.mk: improve bootstraping + +2011-06-10 Simon J. Gerraty + + * yacc.mk: handle the corner case of .c being removed + while .h remains. + +2011-06-08 Simon J. Gerraty + + * yacc.mk: do .y.h and .y.c separately + +2011-06-04 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110606 + * don't store SRC_DIRDEPS in Makefile.depend* by default + not everyone needs it. + +2011-05-04 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110505 + first release including meta mode makefiles + +2011-05-02 Simon J. Gerraty + + * meta.stage.mk: add STAGE_AS_SETS and stage_as + for things that need to be staged with different names. + +2011-05-01 Simon J. Gerraty + + * meta.stage.mk: add notion of STAGE_SETS + so a makefile can stage to multiple dirs + +2011-04-03 Simon J. Gerraty + + * rst2htm.mk: convert rst to s5 (slides) or plain html depending + on target name. + +2011-03-30 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110330 + +2011-03-29 Simon J. Gerraty + + * sys.mk (_DEBUG_MAKE_FLAGS): use indirection so that DEBUG_MAKE_FLAGS0 + can be used to debug level 0 only and DEBUG_MAKE_FLAGS for the rest. + * sys.mk: re-define M_whence in terms of M_type. + M_type is useful for checking if something is a builtin. + +2011-03-16 Simon J. Gerraty + + * meta.stage.mk: add stage_symlinks and leverage StageLinks for + stage_libs + +2011-03-10 Simon J. Gerraty + + * dirdeps.mk: correct value for _depdir_files depends on + .MAKE.DEPENDFILE + Add our copyright - just to make it clear we have frobbed this + quite a bit. + DEP_MACHINE needs to be set to MACHINE each time, if using only + Makefile.depend (cf. Makefile.depend.${MACHINE}) + + * meta.stage.mk: meta mode version of staging + + * init.mk, final.mk: include local.*.mk to simplify customization + +2011-03-03 Simon J. Gerraty + + * auto.obj.mk: just because we are doing mk destroy, we should + still set .OBJDIR correctly if it exists. + + * install-mk (mksrc): do not exclude meta.sys.mk + +2011-03-01 Simon J. Gerraty + + * host-target.mk: set/export _HOST_ARCH etc separately, + catch junk resulting from uname -p, so we can find sys/Linux.mk + correctly. + +2011-02-18 Simon J. Gerraty + + * meta.sys.mk: throw an error if /dev/filemon is missing and we + expected to be updating Makefile.depend* + +2011-02-14 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20110214 + * meta.subdir.mk: add support for -DBOOTSTRAP_DEPENDFILES + +2010-09-25 Simon J. Gerraty + + * meta.sys.mk: not valid for older bmake + +2010-09-24 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100919 + include dirdeps.mk et al from Juniper Networks, + for meta mode - requires filemon(9). + * sys.mk, subdir.mk: Add hooks for meta mode. + we do this as meta.sys.mk, meta.autodep.mk and meta.subdir.mk + to make turning it on/off simple. + +2010-06-16 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100616 + * fix typo in sys.mk + +2010-06-12 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100612 + * lib.mk: remove duplicate addition to SOBJS + +2010-06-10 Simon J. Gerraty + + * sys.mk: Add a means of selectively turning on debug flags. + Eg. DEBUG_MAKE_FLAGS=-dv DEBUG_MAKE_DIRS="*lib/sjg" + will act as if we did make -dv if .CURDIR ends in lib/sjg + DEBUG_MAKE_SYS_DIRS does the same thing, but we set the flags at + the start of sys.mk rather than the end. + This only makes sense for leaf dirs, so we check that + .MAKE.LEVEL > 0 + +2010-06-09 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100608 + * sys.mk: include sys.env.mk later so it can use M_ListToSkip et al. + * examples/sys.clean-env.mk: require MAKE_VERIONS >= 20100606 + also make it easier for folk to tweak + +2010-06-08 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100606 + do not install examples/* + * FILES: add examples/sys.clean-env.mk + * examples/sys.clean-env.mk: use .export-env to handle MAKEOBJDIR + this requires bmake-20100606 or later to work. + +2010-05-13 Simon J. Gerraty + + * sys.mk (M_tA): better simulate the result of :tA if not available. + +2010-05-04 Simon J. Gerraty + + * sys.mk: canonicalize MAKE_VERSION + old versions reported bmake- build- + whereas we only care about + +2010-04-25 Simon J. Gerraty + + * install-mk: just warn about FORCE_{BSD,SYS}_MK being ignored + * lib.mk: we only build the shared lib if SHLIB_FULLVERSION + is !empty + +2010-04-22 Simon J. Gerraty + + * dpadd.mk: use LDADD_* if defined. + +2010-04-21 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100420 + * sys/NetBSD.mk: add MACHINE_CPU to keep netbsd makefiles happy + * autoconf.mk allow AUTO_AUTOCONF + +2010-04-19 Simon J. Gerraty + + * obj.mk: add objwarn to keep freebsd makefiles happy + * auto.obj.mk: ensure Mkdirs is available. + * FILES: add auto.dep.mk - a simpler version of autodep.mk + * dep.mk: auto.dep.mk does not do 'make depend' so ignore it if + asked to do that. + fix/simplify the tests for when to run mkdep. + * auto.dep.mk: add some explanation of how/what we do. + * autodep.mk: skip the .OPTIONAL frobbing of .depend + bmake's FROM_DEPEND flag makes it redundant. + +2010-04-13 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100404 + * subdir.mk: protect from multiple inclusion using _SUBDIRUSE. + * obj.mk: protect from multiple inclusion even as bsd.obj.mk + Also create a target _SUBDIRUSE so that we can be used without + subdir.mk + +2010-04-12 Simon J. Gerraty + + * dep.mk: use <> when .including so can override. + +2010-01-11 Simon J. Gerraty + + * lib.mk (SHLIB_LINKS): ensure a string comparison. + +2010-01-04 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20100102 + * own.mk: ensure PRINTOBJDIR works + * autoconf.mk: pass on CONFIGURE_ARGS + * init.mk: handle COPTS.${.IMPSRC:T} etc. + * lib.mk: allow sys.mk to control SHLIB_FULLVERSION + fix handling of symlinks for darwin + * libnames.mk: add DSHLIBEXT for libs which only exist as shared. + * man.mk: suppress chown when not root. + * rst2htm.mk: allow srcs from multiple locations. + * sys.mk: M_whence, stop after 1st line of output. + * sys/Darwin.mk: Use .dylib for DSHLIBEXT and HOST_LIBEXT + * sys/SunOS.mk: we need to export PATH + +2009-12-23 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + include rst2htm.mk + +2009-12-17 Simon J. Gerraty + + * sys.mk,libnames.mk add .-include + this allows local customization without the need to edit the + distributed files. + +2009-12-14 Simon J. Gerraty + + * dpadd.mk (__dpadd_libdirs): order -L's to avoid picking up + older versions already installed. + +2009-12-13 Simon J. Gerraty + + * stage.mk (.stage-install): generalize lib.mk's .libinstall + * rules.mk rules for generic Makefile. + * inc.mk install for includes. + +2009-12-11 Simon J. Gerraty + + * sys/NetBSD.mk (MAKE_VERSION): some of our *.mk want to check + this, so provide it if using native make. + +2009-12-10 Simon J. Gerraty + + * FILES: move all the platform *.sys.mk files to sys/*.mk + * Rename Generic.sys.mk to sys.mk - we always want it. + +2009-11-17 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * host-target.mk: only export the expensive stuff + * Generic.sys.mk (sys_mk): for SunOS we need to look for + ${HOST_OS}.${HOST_OSMAJOR} too! + +2009-11-07 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * lib.mk: if sys.mk doesn't give us an lorder, don't use it. + based on patch from Greg Olszewski. + * Generic.sys.mk: if we have nothing to work with + set LORDER etc only if we can find it. + +2009-09-08 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * man.mk: cleanman: remove CLEANMAN if defined. + +2009-09-04 Simon J. Gerraty + + * SunOS.5.sys.mk (CC): Use ?= like the other *sys.mk + +2009-07-17 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + include auto.obj.mk + + +2009-03-26 Simon J. Gerraty + + * prog.mk,lib.mk: ensure test of USE_DPADD_MK doesn't fail. + +2008-11-11 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + man.mk: ensure we generate *.cat1 etc in . + +2008-07-16 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + add prlist.mk + +2007-11-25 Simon J. Gerraty + + * Generic.sys.mk: Allow os specific sys.mk to be in a + subdir of ${.PARSEDIR} + +2007-11-22 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * general cleanup + * dpadd.mk introduce DPMAGIC_LIBS_* + +2007-04-30 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + + * libs.mk, progs.mk, autodep.mk: allow for per lib/prog + depend files and ensure clean is called for each lib/prog. + +2007-03-27 Simon J. Gerraty + + * autodep.mk (.depend): delete lines that do not start with + space and do not contain ':' + +2007-02-16 Simon J. Gerraty + + * autodep.mk (.depend): gcc may wrap lines if pathnames are long + so make sure the transform for .OPTIONAL copes. + +2007-02-03 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + + * own.mk: make sure RM and LN are defined. + + * obj.mk: fix a typo, and objlink target. + +2006-12-30 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version + * added libs.mk - analogous to progs.mk + make both of them always inlcude {lib,prog}.mk + +2006-12-28 Simon J. Gerraty + + * progs.mk: add a means of building multiple apps in one dir. + +2006-11-26 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20061126 + + * warnings.mk: detect invalid WARNINGS_SET + + * warnings.mk: use ${.TARGET:T:R}.o when looking for target + specific warnings. + + * For .cc sources, turn off warnings that g++ vomits on. + +2006-11-08 Simon J. Gerraty + + * own.mk: if __initialized__ target doesn't exist and we are + FreeBSD we got here directly from sys.mk + +2006-11-06 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20061106 + add scripts.mk + +2006-03-18 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20060318 + + * autodep.mk: avoid := when modifying OBJS into __dependsrcs + +2006-03-02 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20060302 + * autodep.mk: use -MF et al to help gcc+ccache DTRT. + +2006-03-01 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20060301 + * autodep.mk (.depend): + if MAKE_VERSION is newer than 20050530 we can make .END depend on + .depend and make .depend depend on __depsrcs that exist. + * dpadd.mk: add SRC_PATHADD + +2005-11-04 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20051104 + * prog.mk: remove all the LIBC?= junk, use + .-include libnames.mk instead (none by default). + also if USE_DPADD_MK is set, include that. + +2005-10-09 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20051001 + Add UnixWare.sys.mk from Klaus Heinz. + +2005-04-05 Simon J. Gerraty + + * install-mk: always install *.sys.mk and if need be symlink one + to sys.mk + +2005-03-22 Simon J. Gerraty + + * subdir.mk, own.mk: use .MAKE rather than MAKE + +2004-02-15 Simon J. Gerraty + + * own.mk: don't use NetBSD's _SRC_TOP_ it can + cause confusion. Also don't take just 'mk' as a + srctop indicator. + +2004-02-14 Simon J. Gerraty + + * warnings.mk: overhauled, now very powerful. + +2004-02-03 Simon J. Gerraty + + * Generic.sys.mk: need to use ${.PARSEDIR} with exists(). + +2004-02-01 Simon J. Gerraty + + * install-mk (MK_VERSION): bump version to 20040201 + * extract HOST_TARGET stuff to host-target.mk so own.mk and + Generic.sys.mk can share. + * fix typo in autodep.mk _SUBDIRUSE not _SUBDIR. + +2003-09-30 Simon J. Gerraty + + * install-mk (MK_VERSION): 20030930 + * rename generic.sys.mk to Generic.sys.mk + so that it does not get installed (unless being used as sys.mk) + * set OS and ROOT_GROUP for those that we know the value. + for others (eg. Generic.sys.mk) wrap the != in an .ifndef so + we don't do it again for each sub-make. + +2003-09-28 Simon J. Gerraty + + * install-mk (MK_VERSION): 20030928 + Add some extra *.sys.mk from bootstrap-pkgsrc + some of these likely still need work. + Make everything default to root:wheel ownership, + sys.mk can set ROOT_GROUP accordingly. + +2003-08-07 Simon J. Gerraty + + * install-mk: if FORCE_BSD_MK={cp,ln} use the ones in SYS_MK_DIR + not the portable ones. + +2003-07-31 Simon J. Gerraty + + * install-mk: add ability to use cp -f when updating + destination .mk files. Also now possible to play games with + FORCE_SYS_MK=ln etc on *BSD machines to link /usr/share/mk/sys.mk + into dest - not recommended unless you seriously want to. + +2003-07-28 Simon J. Gerraty + + * own.mk (IMPFLAGS): add support for COPTS.${IMPSRC:T} etc + for semi-compatability with NetBSD. + +2003-07-23 Simon J. Gerraty + + * install-mk: add a version indicator + +2003-07-22 Simon J. Gerraty + + * prog.mk: don't try and use ${LIBCRT0} if its /dev/null + + * install-mk: Allow FORCE_SYS_MK to come from env + + + Index: vendor/NetBSD/bmake/20201101/mk/dirdeps-cache-update.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dirdeps-cache-update.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dirdeps-cache-update.mk (revision 367461) @@ -0,0 +1,177 @@ +# $Id: dirdeps-cache-update.mk,v 1.22 2020/09/10 00:14:38 sjg Exp $ +# +# @(#) Copyright (c) 2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +## +# +# This makefile deals with the updating of STATIC_DIRDEPS_CACHE. +# Some targets are so huge that computing dirdeps takes a significant +# amount of time. For such targets a STATIC_DIRDEPS_CACHE can make +# sense. +# +# If the target is represented by targets/pseudo/production +# it's normal DIRDEPS would be in +# targets/pseudo/production/Makefile.depend +# and STATIC_DIRDEPS_CACHE would be +# targets/pseudo/production/Makefile.dirdeps.cache +# which is simply initialized by copying dirdeps.cache.production +# from $OBJTOP +# +# When dirdeps-targets.mk is initializing DIRDEPS it will look for +# Makefile.dirdeps.cache and unless told not to +# (MK_STATIC_DIRDEPS_CACHE=no) will use it as DIRDEPS_CACHE. +# +# If MK_STATIC_DIRDEPS_CACHE_UPDATE is "yes", then this makefile +# comes into play. +# +# We usually get included from local.dirdeps.mk +# as well as Makefile.depend of RELDIR with a static Makefile.dirdeps.cache +# +# If we see that STATIC_DIRDEPS_CACHE is in use, we need to hook a +# cache-update target into the build to regenerate dirdeps.cache +# in parallel with the rest of the build. +# If MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE is "yes" we update +# STATIC_DIRDEPS_CACHE as soon as the update is ready, +# otherwise it will be done at the end of the build. +# +# If STATIC_DIRDEPS_CACHE is not in use, but a DIRDEPS_CACHE is, +# then we need do nothing except export STATIC_DIRDEPS_CACHE and +# DYNAMIC_DIRDEPS_CACHE for use when we are include during the visit +# to the ultimate target (targets/pseudo/production). +# +# Regardless of which happens, when included at .MAKE.LEVEL > 0 +# for a target other than cache-update we simply copy +# DYNAMIC_DIRDEPS_CACHE to STATIC_DIRDEPS_CACHE with some optional +# filtering. +# +# If we are included for the target cache-update we take care of +# running dirdeps.mk again to generate the DYNAMIC_DIRDEPS_CACHE. +# + +.if !target(_${.PARSEFILE}_) +_${.PARSEFILE}_: .NOTMAIN + +STATIC_CACHE_SED += \ + -e '/Autogenerated/s,-.*,- edit with care!,' \ + -e '/cache-update/d' + +STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT ?= \ + { echo Saving ${DYNAMIC_DIRDEPS_CACHE} as ${STATIC_DIRDEPS_CACHE}; \ + sed ${STATIC_CACHE_SED} ${DYNAMIC_DIRDEPS_CACHE} > ${STATIC_DIRDEPS_CACHE}; } +.endif + +.if ${MK_DIRDEPS_CACHE:Uno} == "yes" +.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE:Uno} == "yes" +.if ${_debug_reldir:U0} || ${DEBUG_DIRDEPS:U:Mcache*} != "" +_debug_cache = 1 +.else +_debug_cache = 0 +.endif + +.if ${.MAKE.LEVEL} == 0 && !make(cache-update) + +.if ${_debug_cache} +.info ${MK_STATIC_DIRDEPS_CACHE_UPDATE MK_STATIC_DIRDEPS_CACHE MK_DIRDEPS_CACHE DIRDEPS_CACHE STATIC_DIRDEPS_CACHE:L:@v@$v=${$v}@} +.endif + +.if ${MK_STATIC_DIRDEPS_CACHE} == "yes" && defined(STATIC_DIRDEPS_CACHE) && exists(${STATIC_DIRDEPS_CACHE}) +.if !make(dirdeps) && !target(cache_update_dirdep) +# We are using static cache and this is the only look we will get. +# We want to generate an updated cache while we build +# so need to hook cache-update to dirdeps now. +# Note: we are running as a sibling to dirdeps-cached, +# attempting to do this in that context is problematic. + +# One of these should exist - to actually kick off the cache generation +.for d in ${STATIC_DIRDEPS_CACHE:H}/cache-update ${STATIC_DIRDEPS_CACHE:H:H}/cache-update ${STATIC_DIRDEPS_CACHE:H:H:H}/cache-update +.if exists($d) +cache_update_dirdep ?= $d.${TARGET_SPEC} +.endif +.endfor +dirdeps cache_update_dirdep: ${cache_update_dirdep} +${cache_update_dirdep}: _DIRDEP_USE +DYNAMIC_DIRDEPS_CACHE := ${OBJTOP}/dirdeps.cache.${STATIC_DIRDEPS_CACHE:H:T}-update +.export DYNAMIC_DIRDEPS_CACHE STATIC_DIRDEPS_CACHE +.endif # make(dirdeps) +.endif # MK_* + +.endif # .MAKE.LEVEL 0 + +.if ${.MAKE.LEVEL} > 0 && ${.CURDIR:T} == "cache-update" +# we are the background update shim + +.if ${_debug_cache} +.info level ${.MAKE.LEVEL}: ${MK_DIRDEPS_CACHE DYNAMIC_DIRDEPS_CACHE STATIC_DIRDEPS_CACHE:L:@v@$v=${$v}@} +.endif + +all: cache-build +cache-build: .META + @set -x; MAKELEVEL=0 \ + ${.MAKE} -C ${SRCTOP} -f ${RELDIR}/Makefile cache-update \ + -DWITHOUT_STATIC_DIRDEPS_CACHE_UPDATE + +.endif # cache-update + +.elif ${.MAKE.LEVEL} == 0 && make(cache-update) && !target(cache-update) +# we were invoked above +# we just leverage dirdeps.mk +BUILD_DIRDEPS_TARGETS := ${STATIC_DIRDEPS_CACHE:H:T} +DIRDEPS := ${STATIC_DIRDEPS_CACHE:H:S,^${SRCTOP}/,,}.${TARGET_SPEC} +DIRDEPS_CACHE := ${DYNAMIC_DIRDEPS_CACHE} + +.if ${DEBUG_DIRDEPS:U:Mcache*} != "" +.info level 0: ${MK_DIRDEPS_CACHE DIRDEPS_CACHE DIRDEPS:L:@v@$v=${$v}@} +.endif + +# so cache-built below can check on us +x!= echo; echo ${.MAKE.PID} > ${DIRDEPS_CACHE}.new.pid + +cache-update: ${DIRDEPS_CACHE} + @rm -f ${DIRDEPS_CACHE}.new.pid +.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE:Uno} == "yes" + ${STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT} +.endif + +all: + +.include + +.endif # MK_STATIC_DIRDEPS_CACHE_UPDATE +.endif # MK_DIRDEPS_CACHE + +.if ${.MAKE.LEVEL} > 0 && ${MK_STATIC_DIRDEPS_CACHE_UPDATE:Uno} == "yes" && \ + ${STATIC_DIRDEPS_CACHE:Uno:H} == "${SRCTOP}/${RELDIR}" +.if !defined(DYNAMIC_DIRDEPS_CACHE) +all: +.else +# This is the easy bit, time to save the cache + +all: cache-update + +# ensure the cache update is completed +cache-built: + @test -s ${DYNAMIC_DIRDEPS_CACHE}.new || exit 0; \ + pid=`cat ${DYNAMIC_DIRDEPS_CACHE}.new.pid 2> /dev/null`; \ + test $${pid:-0} -gt 1 || exit 0; \ + echo "Waiting for $$pid to finish ${DYNAMIC_DIRDEPS_CACHE} ..."; \ + while 'kill' -0 $$pid; do sleep 30; done > /dev/null 2>&1 + +cache-update: cache-built +.if ${MK_STATIC_DIRDEPS_CACHE_UPDATE_IMMEDIATE:Uno} == "no" + @test ! -s ${DYNAMIC_DIRDEPS_CACHE} || \ + ${STATIC_DIRDEPS_CACHE_UPDATE_SCRIPT} +.endif + +.endif +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/dirdeps-cache-update.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/dirdeps.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dirdeps.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dirdeps.mk (revision 367461) @@ -0,0 +1,871 @@ +# $Id: dirdeps.mk,v 1.130 2020/11/02 00:34:30 sjg Exp $ + +# Copyright (c) 2010-2020, Simon J. Gerraty +# Copyright (c) 2010-2018, Juniper Networks, Inc. +# 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 +# OWNER 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. + +# Much of the complexity here is for supporting cross-building. +# If a tree does not support that, simply using plain Makefile.depend +# should provide sufficient clue. +# Otherwise the recommendation is to use Makefile.depend.${MACHINE} +# as expected below. + +# Note: this file gets multiply included. +# This is what we do with DIRDEPS + +# DIRDEPS: +# This is a list of directories - relative to SRCTOP, it is +# normally only of interest to .MAKE.LEVEL 0. +# In some cases the entry may be qualified with a . +# or . suffix (see TARGET_SPEC_VARS below), +# for example to force building something for the pseudo +# machines "host" or "common" regardless of current ${MACHINE}. +# +# All unqualified entries end up being qualified with .${TARGET_SPEC} +# and partially qualified (if TARGET_SPEC_VARS has multiple +# entries) are also expanded to a full .. +# The _DIRDEP_USE target uses the suffix to set TARGET_SPEC +# correctly when visiting each entry. +# +# The fully qualified directory entries are used to construct a +# dependency graph that will drive the build later. +# +# Also, for each fully qualified directory target, we will search +# using ${.MAKE.DEPENDFILE_PREFERENCE} to find additional +# dependencies. We use Makefile.depend (default value for +# .MAKE.DEPENDFILE_PREFIX) to refer to these makefiles to +# distinguish them from others. +# +# Before each Makefile.depend file is read, we set +# DEP_RELDIR to be the RELDIR (path relative to SRCTOP) for +# its directory, and DEP_MACHINE etc according to the . +# represented by the suffix of the corresponding target. +# +# Since each Makefile.depend file includes dirdeps.mk, this +# processing is recursive and results in .MAKE.LEVEL 0 learning the +# dependencies of the tree wrt the initial directory (_DEP_RELDIR). +# +# TARGET_SPEC_VARS +# The default value is just MACHINE, and for most environments +# this is sufficient. The _DIRDEP_USE target actually sets +# both MACHINE and TARGET_SPEC to the suffix of the current +# target so that in the general case TARGET_SPEC can be ignored. +# +# If more than MACHINE is needed then sys.mk needs to decompose +# TARGET_SPEC and set the relevant variables accordingly. +# It is important that MACHINE be included in and actually be +# the first member of TARGET_SPEC_VARS. This allows other +# variables to be considered optional, and some of the treatment +# below relies on MACHINE being the first entry. +# Note: TARGET_SPEC cannot contain any '.'s so the target +# triple used by compiler folk won't work (directly anyway). +# +# For example: +# +# # Always list MACHINE first, +# # other variables might be optional. +# TARGET_SPEC_VARS = MACHINE TARGET_OS +# .if ${TARGET_SPEC:Uno:M*,*} != "" +# _tspec := ${TARGET_SPEC:S/,/ /g} +# MACHINE := ${_tspec:[1]} +# TARGET_OS := ${_tspec:[2]} +# # etc. +# # We need to stop that TARGET_SPEC affecting any submakes +# # and deal with MACHINE=${TARGET_SPEC} in the environment. +# TARGET_SPEC = +# # export but do not track +# .export-env TARGET_SPEC +# .export ${TARGET_SPEC_VARS} +# .for v in ${TARGET_SPEC_VARS:O:u} +# .if empty($v) +# .undef $v +# .endif +# .endfor +# .endif +# # make sure we know what TARGET_SPEC is +# # as we may need it to find Makefile.depend* +# TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} +# +# The following variables can influence the initial DIRDEPS +# computation with regard to the TARGET_SPECs that will be +# built. +# Most should also be considered by init.mk +# +# ONLY_TARGET_SPEC_LIST +# Defines a list of TARGET_SPECs for which the current +# directory can be built. +# If ALL_MACHINES is defined, we build for all the +# TARGET_SPECs listed. +# +# ONLY_MACHINE_LIST +# As for ONLY_TARGET_SPEC_LIST but only specifies +# MACHINEs. +# +# NOT_TARGET_SPEC_LIST +# A list of TARGET_SPECs for which the current +# directory should not be built. +# +# NOT_MACHINE_LIST +# A list of MACHINEs the current directory should not be +# built for. +# +# _build_xtra_dirs +# local.dirdeps.mk can add targets to this variable. +# They will be hooked into the build, but independent of +# any other DIRDEP. +# +# This allows for adding TESTS to the build, such that the build +# if any test fails, but without the risk of introducing +# circular dependencies. + +now_utc ?= ${%s:L:gmtime} +.if !defined(start_utc) +start_utc := ${now_utc} +.endif + +.if !target(bootstrap) && (make(bootstrap) || \ + make(bootstrap-this) || \ + make(bootstrap-recurse) || \ + make(bootstrap-empty)) +# disable most of below +.MAKE.LEVEL = 1 +.endif + +# touch this at your peril +_DIRDEP_USE_LEVEL?= 0 +.if ${.MAKE.LEVEL} == ${_DIRDEP_USE_LEVEL} +# only the first instance is interested in all this + +.if !target(_DIRDEP_USE) + +# do some setup we only need once +_CURDIR ?= ${.CURDIR} +_OBJDIR ?= ${.OBJDIR} + +.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != "" +# This little trick let's us do +# +# mk -f dirdeps.mk some/dir.${TARGET_SPEC} +# +all: +${.TARGETS:Nall}: all +DIRDEPS := ${.TARGETS:M*[/.]*} +# so that -DNO_DIRDEPS works +DEP_RELDIR := ${DIRDEPS:[1]:R} +# this will become DEP_MACHINE below +TARGET_MACHINE := ${DIRDEPS:[1]:E:C/,.*//} +.if ${TARGET_MACHINE:N*/*} == "" +TARGET_MACHINE := ${MACHINE} +.endif +# disable DIRDEPS_CACHE as it does not like this trick +MK_DIRDEPS_CACHE = no +.endif + +# make sure we get the behavior we expect +.MAKE.SAVE_DOLLARS = no + +# make sure these are empty to start with +_DEP_TARGET_SPEC = + +# If TARGET_SPEC_VARS is other than just MACHINE +# it should be set by sys.mk or similar by now. +# TARGET_SPEC must not contain any '.'s. +TARGET_SPEC_VARS ?= MACHINE +# this is what we started with +TARGET_SPEC = ${TARGET_SPEC_VARS:@v@${$v:U}@:ts,} +# this is what we mostly use below +DEP_TARGET_SPEC = ${TARGET_SPEC_VARS:S,^,DEP_,:@v@${$v:U}@:ts,} +# make sure we have defaults +.for v in ${TARGET_SPEC_VARS} +DEP_$v ?= ${$v} +.endfor + +.if ${TARGET_SPEC_VARS:[#]} > 1 +# Ok, this gets more complex (putting it mildly). +# In order to stay sane, we need to ensure that all the build_dirs +# we compute below are fully qualified wrt DEP_TARGET_SPEC. +# The makefiles may only partially specify (eg. MACHINE only), +# so we need to construct a set of modifiers to fill in the gaps. +.if ${MAKE_VERSION} >= 20170130 +_tspec_x := ${TARGET_SPEC_VARS:range} +.else +# do it the hard way +_tspec_x := ${TARGET_SPEC_VARS:[#]:@x@i=1;while [ $$i -le $x ]; do echo $$i; i=$$((i + 1)); done;@:sh} +.endif +# this handles unqualified entries +M_dep_qual_fixes = C;(/[^/.,]+)$$;\1.$${DEP_TARGET_SPEC}; +# there needs to be at least one item missing for these to make sense +.for i in ${_tspec_x:[2..-1]} +_tspec_m$i := ${TARGET_SPEC_VARS:[2..$i]:@w@[^,]+@:ts,} +_tspec_a$i := ,${TARGET_SPEC_VARS:[$i..-1]:@v@$$$${DEP_$v}@:ts,} +M_dep_qual_fixes += C;(\.${_tspec_m$i})$$;\1${_tspec_a$i}; +.endfor +TARGET_SPEC_VARSr := ${TARGET_SPEC_VARS:[-1..1]} +.else +# A harmless? default. +M_dep_qual_fixes = U +.endif + +.if !defined(.MAKE.DEPENDFILE_PREFERENCE) +# .MAKE.DEPENDFILE_PREFERENCE makes the logic below neater? +# you really want this set by sys.mk or similar +.MAKE.DEPENDFILE_PREFERENCE = ${_CURDIR}/${.MAKE.DEPENDFILE:T} +.if ${.MAKE.DEPENDFILE:E} == "${TARGET_SPEC}" +.if ${TARGET_SPEC} != ${MACHINE} +.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R}.$${MACHINE} +.endif +.MAKE.DEPENDFILE_PREFERENCE += ${_CURDIR}/${.MAKE.DEPENDFILE:T:R} +.endif +.endif + +_default_dependfile := ${.MAKE.DEPENDFILE_PREFERENCE:[1]:T} +_machine_dependfiles := ${.MAKE.DEPENDFILE_PREFERENCE:T:M*${MACHINE}*} + +# for machine specific dependfiles we require ${MACHINE} to be at the end +# also for the sake of sanity we require a common prefix +.if !defined(.MAKE.DEPENDFILE_PREFIX) +# knowing .MAKE.DEPENDFILE_PREFIX helps +.if !empty(_machine_dependfiles) +.MAKE.DEPENDFILE_PREFIX := ${_machine_dependfiles:[1]:T:R} +.else +.MAKE.DEPENDFILE_PREFIX := ${_default_dependfile:T} +.endif +.endif + + +# this is how we identify non-machine specific dependfiles +N_notmachine := ${.MAKE.DEPENDFILE_PREFERENCE:E:N*${MACHINE}*:${M_ListToSkip}} + +.endif # !target(_DIRDEP_USE) + +# First off, we want to know what ${MACHINE} to build for. +# This can be complicated if we are using a mixture of ${MACHINE} specific +# and non-specific Makefile.depend* + +# if we were included recursively _DEP_TARGET_SPEC should be valid. +.if empty(_DEP_TARGET_SPEC) +# we may or may not have included a dependfile yet +.if defined(.INCLUDEDFROMFILE) +_last_dependfile := ${.INCLUDEDFROMFILE:M${.MAKE.DEPENDFILE_PREFIX}*} +.else +_last_dependfile := ${.MAKE.MAKEFILES:M*/${.MAKE.DEPENDFILE_PREFIX}*:[-1]} +.endif +.if ${_debug_reldir:U0} +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _last_dependfile='${_last_dependfile}' +.endif + +.if empty(_last_dependfile) || ${_last_dependfile:E:${N_notmachine}} == "" +# this is all we have to work with +DEP_MACHINE = ${TARGET_MACHINE:U${MACHINE}} +_DEP_TARGET_SPEC := ${DEP_TARGET_SPEC} +.else +_DEP_TARGET_SPEC = ${_last_dependfile:${M_dep_qual_fixes:ts:}:E} +.endif +.if !empty(_last_dependfile) +# record that we've read dependfile for this +_dirdeps_checked.${_CURDIR}.${TARGET_SPEC}: +.endif +.endif + +# by now _DEP_TARGET_SPEC should be set, parse it. +.if ${TARGET_SPEC_VARS:[#]} > 1 +# we need to parse DEP_MACHINE may or may not contain more info +_tspec := ${_DEP_TARGET_SPEC:S/,/ /g} +.for i in ${_tspec_x} +DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]} +.endfor +.for v in ${TARGET_SPEC_VARS:O:u} +.if empty(DEP_$v) +.undef DEP_$v +.endif +.endfor +.else +DEP_MACHINE := ${_DEP_TARGET_SPEC} +.endif + +# reset each time through +_build_all_dirs = +_build_xtra_dirs = + +# the first time we are included the _DIRDEP_USE target will not be defined +# we can use this as a clue to do initialization and other one time things. +.if !target(_DIRDEP_USE) +# make sure this target exists +dirdeps: beforedirdeps .WAIT +beforedirdeps: + +# We normally expect to be included by Makefile.depend.* +# which sets the DEP_* macros below. +DEP_RELDIR ?= ${RELDIR} + +# this can cause lots of output! +# set to a set of glob expressions that might match RELDIR +DEBUG_DIRDEPS ?= no + +# remember the initial value of DEP_RELDIR - we test for it below. +_DEP_RELDIR := ${DEP_RELDIR} + +.endif + +# DIRDEPS_CACHE can be very handy for debugging. +# Also if repeatedly building the same target, +# we can avoid the overhead of re-computing the tree dependencies. +MK_DIRDEPS_CACHE ?= no +BUILD_DIRDEPS_CACHE ?= no +BUILD_DIRDEPS ?= yes + +.if ${MK_DIRDEPS_CACHE} == "yes" +# this is where we will cache all our work +DIRDEPS_CACHE ?= ${_OBJDIR:tA}/dirdeps.cache${_TARGETS:U${.TARGETS}:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.} +.endif + +.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.${DEP_MACHINE}:L:M$x}@} != "" +_debug_reldir = 1 +.else +_debug_reldir = 0 +.endif +.if ${DEBUG_DIRDEPS:@x@${DEP_RELDIR:M$x}${${DEP_RELDIR}.depend:L:M$x}@} != "" +_debug_search = 1 +.else +_debug_search = 0 +.endif + +# pickup customizations +# as below you can use !target(_DIRDEP_USE) to protect things +# which should only be done once. +.-include + +.if !target(_DIRDEP_USE) +# things we skip for host tools +SKIP_HOSTDIR ?= + +NSkipHostDir = ${SKIP_HOSTDIR:N*.host*:S,$,.host*,:N.host*:S,^,${SRCTOP}/,:${M_ListToSkip}} + +# things we always skip +# SKIP_DIRDEPS allows for adding entries on command line. +SKIP_DIR += .host *.WAIT ${SKIP_DIRDEPS} +SKIP_DIR.host += ${SKIP_HOSTDIR} + +DEP_SKIP_DIR = ${SKIP_DIR} \ + ${SKIP_DIR.${DEP_TARGET_SPEC}:U} \ + ${TARGET_SPEC_VARS:@v@${SKIP_DIR.${DEP_$v}:U}@} \ + ${SKIP_DIRDEPS.${DEP_TARGET_SPEC}:U} \ + ${TARGET_SPEC_VARS:@v@${SKIP_DIRDEPS.${DEP_$v}:U}@} + + +NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}} + +.if defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS) +NO_DIRDEPS = +.elif defined(WITHOUT_DIRDEPS_BELOW) +NO_DIRDEPS_BELOW = +.endif + +.if defined(NO_DIRDEPS) +# confine ourselves to the original dir and below. +DIRDEPS_FILTER += M${_DEP_RELDIR}* +.elif defined(NO_DIRDEPS_BELOW) +DIRDEPS_FILTER += M${_DEP_RELDIR} +.endif + +# this is what we run below +DIRDEP_MAKE ?= ${.MAKE} +DIRDEP_DIR ?= ${.TARGET:R} + +# if you want us to report load averages during build +# DIRDEP_USE_PRELUDE += ${DIRDEP_LOADAVG_REPORT}; + +DIRDEP_LOADAVG_CMD ?= ${UPTIME:Uuptime} | sed 's,.*\(load\),\1,' +DIRDEP_LOADAVG_LAST = 0 +# yes the expression here is a bit complicated, +# the trick is to only eval ${DIRDEP_LOADAVG_LAST::=${now_utc}} +# when we want to report. +DIRDEP_LOADAVG_REPORT = \ + test -z "${"${expr ${now_utc} - ${DIRDEP_LOADAVG_INTEVAL:U60} - ${DIRDEP_LOADAVG_LAST}:L:sh:N-*}":?yes${DIRDEP_LOADAVG_LAST::=${now_utc}}:}" || \ + echo "${TRACER}`${DIRDEP_LOADAVG_CMD}`" + +# we suppress SUBDIR when visiting the leaves +# we assume sys.mk will set MACHINE_ARCH +# you can add extras to DIRDEP_USE_ENV +# if there is no makefile in the target directory, we skip it. +_DIRDEP_USE: .USE .MAKE + @for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \ + test -s ${.TARGET:R}/$$m || continue; \ + echo "${TRACER}Checking ${.TARGET:S,${SRCTOP}/,,} for ${.TARGET:E} ..."; \ + ${DIRDEP_USE_PRELUDE} \ + MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \ + TARGET_SPEC=${.TARGET:E} \ + MACHINE=${.TARGET:E} \ + ${DIRDEP_MAKE} -C ${DIRDEP_DIR} || exit 1; \ + break; \ + 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 +.endif +_only_machines := ${_machine_list:${NIgnoreFiles:UN*.bak}:E:O:u} +.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}}} +.endif + +.else # ! ALL_MACHINES +# if ONLY_TARGET_SPEC_LIST or ONLY_MACHINE_LIST is set, we are limited to that. +# Note that ONLY_TARGET_SPEC_LIST should be fully qualified. +# if TARGET_MACHINE is set - it is really the same as ONLY_MACHINE_LIST +# otherwise DEP_MACHINE is it - so DEP_MACHINE will match. +_only_machines := ${ONLY_TARGET_SPEC_LIST:U:M${DEP_MACHINE},*} +.if empty(_only_machines) +_only_machines := ${ONLY_MACHINE_LIST:U${TARGET_MACHINE:U${DEP_MACHINE}}:M${DEP_MACHINE}} +.endif +.endif + +.if !empty(NOT_MACHINE_LIST) +_only_machines := ${_only_machines:${NOT_MACHINE_LIST:${M_ListToSkip}}} +.endif +.if !empty(NOT_TARGET_SPEC_LIST) +# we must first qualify +_dm := ${DEP_MACHINE} +_only_machines := ${_only_machines:M*,*} ${_only_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,} +DEP_MACHINE := ${_dm} +_only_machines := ${_only_machines:${NOT_TARGET_SPEC_LIST:${M_ListToSkip}}} +.endif +# clean up +_only_machines := ${_only_machines:O:u} + +# make sure we have a starting place? +DIRDEPS ?= ${RELDIR} +.endif # target + +.if !defined(NO_DIRDEPS) && !defined(NO_DIRDEPS_BELOW) +.if ${MK_DIRDEPS_CACHE} == "yes" + +# just ensure this exists +build-dirdeps: + +M_oneperline = @x@\\${.newline} $$x@ + +.if ${BUILD_DIRDEPS_CACHE} == "no" +.if !target(dirdeps-cached) +# we do this via sub-make +BUILD_DIRDEPS = no + +# ignore anything but these +.MAKE.META.IGNORE_FILTER = M*/${.MAKE.DEPENDFILE_PREFIX}* + +dirdeps: dirdeps-cached +dirdeps-cached: ${DIRDEPS_CACHE} .MAKE + @echo "${TRACER}Using ${DIRDEPS_CACHE}" + @MAKELEVEL=${.MAKE.LEVEL} ${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \ + dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no + +# leaf makefiles rarely work for building DIRDEPS_CACHE +.if ${RELDIR} != "." +BUILD_DIRDEPS_MAKEFILE ?= -f dirdeps.mk +.endif + +# these should generally do +BUILD_DIRDEPS_MAKEFILE ?= +BUILD_DIRDEPS_TARGETS ?= ${.TARGETS} + +.if ${DIRDEPS_CACHE} != ${STATIC_DIRDEPS_CACHE:Uno} && ${DIRDEPS_CACHE:M${SRCTOP}/*} == "" +# export this for dirdeps-cache-update.mk +DYNAMIC_DIRDEPS_CACHE := ${DIRDEPS_CACHE} +.export DYNAMIC_DIRDEPS_CACHE +# we need the .meta file to ensure we update if +# any of the Makefile.depend* changed. +# We do not want to compare the command line though. +${DIRDEPS_CACHE}: .META .NOMETA_CMP + +@{ echo '# Autogenerated - do NOT edit!'; echo; \ + echo 'BUILD_DIRDEPS=no'; echo; \ + echo '.include '; echo; \ + } > ${.TARGET}.new + +@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \ + DIRDEPS="${DIRDEPS}" \ + TARGET_SPEC=${TARGET_SPEC} \ + MAKEFLAGS= ${DIRDEP_CACHE_MAKE:U${.MAKE}} -C ${_CURDIR} \ + ${BUILD_DIRDEPS_MAKEFILE} \ + ${BUILD_DIRDEPS_TARGETS} BUILD_DIRDEPS_CACHE=yes \ + .MAKE.DEPENDFILE=.none \ + ${"${DEBUG_DIRDEPS:Nno}":?DEBUG_DIRDEPS='${DEBUG_DIRDEPS}':} \ + ${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \ + ${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \ + 3>&1 1>&2 | sed 's,${SRCTOP},$${SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \ + mv ${.TARGET}.new ${.TARGET} + +.endif +.endif +.elif !target(_count_dirdeps) +# we want to capture the dirdeps count in the cache +.END: _count_dirdeps +_count_dirdeps: .NOMETA + @{ echo; echo '.info $${.newline}$${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} ${DIRDEP_INFO_XTRAS}'; } >&3 + +.endif +.elif !make(dirdeps) && !target(_count_dirdeps) +beforedirdeps: _count_dirdeps +_count_dirdeps: .NOMETA + @echo "${TRACER}Makefiles read: total=${.MAKE.MAKEFILES:[#]} depend=${.MAKE.MAKEFILES:M*depend*:[#]} dirdeps=${.ALLTARGETS:M${SRCTOP}*:O:u:[#]} ${DIRDEP_INFO_XTRAS} seconds=`expr ${now_utc} - ${start_utc}`" + +.endif +.endif + +.if ${BUILD_DIRDEPS} == "yes" + +# the rest is done repeatedly for every Makefile.depend we read. +# if we are anything but the original dir we care only about the +# machine type we were included for.. + +.if ${DEP_RELDIR} == "." +_this_dir := ${SRCTOP} +.else +_this_dir := ${SRCTOP}/${DEP_RELDIR} +.endif + +# on rare occasions, there can be a need for extra help +_dep_hack := ${_this_dir}/${.MAKE.DEPENDFILE_PREFIX}.inc +.-include <${_dep_hack}> +.-include <${_dep_hack:R}.options> + +.if ${DEP_RELDIR} != ${_DEP_RELDIR} || ${DEP_TARGET_SPEC} != ${TARGET_SPEC} +# this should be all +_machines := ${DEP_MACHINE} +.else +# this is the machine list we actually use below +_machines := ${_only_machines} + +.if defined(HOSTPROG) || ${DEP_MACHINE:Nhost*} == "" +# we need to build this guy's dependencies for host as well. +.if ${DEP_MACHINE:Nhost*} == "" +_machines += ${DEP_MACHINE} +.else +_machines += host +.endif +.endif + +_machines := ${_machines:O:u} +.endif + +.if ${TARGET_SPEC_VARS:[#]} > 1 +# we need to tweak _machines +_dm := ${DEP_MACHINE} +# apply the same filtering that we do when qualifying DIRDEPS. +# M_dep_qual_fixes expects .${MACHINE}* so add (and remove) '.' +# Again we expect that any already qualified machines are fully qualified. +_machines := ${_machines:M*,*} ${_machines:N*,*:@DEP_MACHINE@${DEP_TARGET_SPEC}@:S,^,.,:${M_dep_qual_fixes:ts:}:O:u:S,^.,,} +DEP_MACHINE := ${_dm} +_machines := ${_machines:O:u} +.endif + +# reset each time through +_build_dirs = + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# pickup other machines for this dir if necessary +_build_dirs += ${_machines:@m@${_CURDIR}.$m@} +.endif + +.if ${_debug_reldir} +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: DIRDEPS='${DIRDEPS}' +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: _machines='${_machines}' +.endif + +.if !empty(DIRDEPS) +# these we reset each time through as they can depend on DEP_MACHINE +DEP_DIRDEPS_FILTER = \ + ${DIRDEPS_FILTER.${DEP_TARGET_SPEC}:U} \ + ${TARGET_SPEC_VARS:@v@${DIRDEPS_FILTER.${DEP_$v}:U}@} \ + ${DIRDEPS_FILTER:U} +.if empty(DEP_DIRDEPS_FILTER) +# something harmless +DEP_DIRDEPS_FILTER = U +.endif + +# this is what we start with +__depdirs := ${DIRDEPS:${NSkipDir}:${DEP_DIRDEPS_FILTER:ts:}:C,//+,/,g:O:u:@d@${SRCTOP}/$d@} + +# some entries may be qualified with . +# the :M*/*/*.* just tries to limit the dirs we check to likely ones. +# the ${d:E:M*/*} ensures we don't consider junos/usr.sbin/mgd +__qual_depdirs := ${__depdirs:M*/*/*.*:@d@${exists($d):?:${"${d:E:M*/*}":?:${exists(${d:R}):?$d:}}}@} +__unqual_depdirs := ${__depdirs:${__qual_depdirs:Uno:${M_ListToSkip}}} + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# if it was called out - we likely need it. +__hostdpadd := ${DPADD:U.:M${HOST_OBJTOP}/*:S,${HOST_OBJTOP}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host,:N.*:@d@${SRCTOP}/$d@} \ + ${DPADD:U.:M${HOST_OBJTOP32:Uno}/*:S,${HOST_OBJTOP32:Uno}/,,:H:${NSkipDir}:${DIRDEPS_FILTER:ts:}:S,$,.host32,:N.*:@d@${SRCTOP}/$d@} +__qual_depdirs += ${__hostdpadd} +.endif + +.if ${_debug_reldir} +.info DEP_DIRDEPS_FILTER=${DEP_DIRDEPS_FILTER:ts:} +.info depdirs=${__depdirs} +.info qualified=${__qual_depdirs} +.info unqualified=${__unqual_depdirs} +.endif + +# _build_dirs is what we will feed to _DIRDEP_USE +_build_dirs += \ + ${__qual_depdirs:M*.host:${NSkipHostDir}:N.host} \ + ${__qual_depdirs:N*.host} \ + ${_machines:Mhost*:@m@${__unqual_depdirs:@d@$d.$m@}@:${NSkipHostDir}:N.host} \ + ${_machines:Nhost*:@m@${__unqual_depdirs:@d@$d.$m@}@} + +# qualify everything now +_build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u} + +.endif # empty DIRDEPS + +_build_all_dirs += ${_build_dirs} ${_build_xtra_dirs} +_build_all_dirs := ${_build_all_dirs:O:u} + +# Normally if doing make -V something, +# we do not want to waste time chasing DIRDEPS +# but if we want to count the number of Makefile.depend* read, we do. +.if ${.MAKEFLAGS:M-V${_V_READ_DIRDEPS}} == "" +.if !empty(_build_all_dirs) +.if ${BUILD_DIRDEPS_CACHE} == "yes" +x!= echo; { echo; echo '\# ${DEP_RELDIR}.${DEP_TARGET_SPEC}'; } >&3 +# guard against _new_dirdeps being too big for a single command line +_new_dirdeps := ${_build_all_dirs:@x@${target($x):?:$x}@} +.export _build_xtra_dirs _new_dirdeps +.if !empty(DEP_EXPORT_VARS) +# Discouraged, but there are always exceptions. +# Handle it here rather than explain how. +x!= echo; { echo; ${DEP_EXPORT_VARS:@v@echo '$v=${$v}';@} echo '.export ${DEP_EXPORT_VARS}'; echo; } >&3 +.endif +.else +# this makes it all happen +dirdeps: ${_build_all_dirs} +.endif +${_build_all_dirs}: _DIRDEP_USE + +.if ${_debug_reldir} +.info ${DEP_RELDIR}.${DEP_TARGET_SPEC}: needs: ${_build_dirs} +.endif + +.if !empty(DEP_EXPORT_VARS) +.export ${DEP_EXPORT_VARS} +DEP_EXPORT_VARS= +.endif + +# this builds the dependency graph +.for m in ${_machines} +.if ${BUILD_DIRDEPS_CACHE} == "yes" && !empty(_build_dirs) +x!= echo; { echo; echo 'DIRDEPS.${_this_dir}.$m = \'; } >&3 +_cache_deps = +.endif +# it would be nice to do :N${.TARGET} +.if !empty(__qual_depdirs) +.for q in ${__qual_depdirs:${M_dep_qual_fixes:ts:}:E:O:u:N$m} +.if ${_debug_reldir} || ${DEBUG_DIRDEPS:@x@${${DEP_RELDIR}.$m:L:M$x}${${DEP_RELDIR}.$q:L:M$x}@} != "" +.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q} +.endif +.if ${BUILD_DIRDEPS_CACHE} == "yes" +_cache_deps += ${_build_dirs:M*.$q} +.else +${_this_dir}.$m: ${_build_dirs:M*.$q} +.endif +.endfor +.endif +.if ${_debug_reldir} +.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m} +.endif +.if ${BUILD_DIRDEPS_CACHE} == "yes" +.if !empty(_build_dirs) +_cache_deps += ${_build_dirs:M*.$m:N${_this_dir}.$m} +.if !empty(_cache_deps) +.export _cache_deps +x!= echo; for x in $$_cache_deps; do echo " $$x \\"; done >&3 +.endif +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; \ + echo; for x in $$_new_dirdeps; do echo "$$x: _DIRDEP_USE"; done; } >&3 +.endif +.else +${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m} +.endif +.endfor + +.endif + +# Now find more dependencies - and recurse. +.for d in ${_build_all_dirs} +.if !target(_dirdeps_checked.$d) +# once only +_dirdeps_checked.$d: +.if ${_debug_search} +.info checking $d +.endif +# Note: _build_all_dirs is fully qualifed so d:R is always the directory +.if exists(${d:R}) +# we pass _DEP_TARGET_SPEC to tell the next step what we want +_DEP_TARGET_SPEC := ${d:E} +# some makefiles may still look at this +_DEP_MACHINE := ${d:E:C/,.*//} +# set these too in case Makefile.depend* uses them +.if ${TARGET_SPEC_VARS:[#]} > 1 +_dtspec := ${_DEP_TARGET_SPEC:S/,/ /g} +.for i in ${_tspec_x} +DEP_${TARGET_SPEC_VARS:[$i]} := ${_dtspec:[$i]} +.endfor +.else +DEP_MACHINE := ${_DEP_MACHINE} +.endif +# 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]} +.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:}} +.if ${_debug_search} +.info Looking for ${_qm} +.endif +# set this "just in case" +# we can skip :tA since we computed the path above +DEP_RELDIR := ${_m:H:S,${SRCTOP}/,,} +# and reset this +DIRDEPS = +.if ${_debug_reldir} && ${_qm} != ${_m} +.info loading ${_m} for ${d:E} +.endif +.include <${_m}> +.else +.-include +.endif +.endif +.endif +.endfor + +.endif # -V +.endif # BUILD_DIRDEPS + +.elif ${.MAKE.LEVEL} > 42 +.error You should have stopped recursing by now. +.else +# we are building something +DEP_RELDIR := ${RELDIR} +_DEP_RELDIR := ${RELDIR} +# Since we are/should be included by .MAKE.DEPENDFILE +# This is a final opportunity to add/hook global rules. +.-include + +# skip _reldir_{finish,failed} if not included from Makefile.depend* +# or not in meta mode +.if !defined(WITHOUT_META_STATS) && ${.INCLUDEDFROMFILE:U:M${.MAKE.DEPENDFILE_PREFIX}*} != "" && ${.MAKE.MODE:Mmeta} != "" + +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 +_reldir_finish: .NOMETA + @echo "${TRACER}Finished ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}" +.endif + +.if !target(_reldir_failed) +.ERROR: _reldir_failed +_reldir_failed: .NOMETA + @echo "${TRACER}Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}" +.endif + +.endif + +# pickup local dependencies +.if ${MAKE_VERSION} < 20160220 +.-include <.depend> +.else +.dinclude <.depend> +.endif +.endif + +# bootstrapping new dependencies made easy? +.if !target(bootstrap) && (make(bootstrap) || \ + make(bootstrap-this) || \ + make(bootstrap-recurse) || \ + make(bootstrap-empty)) + +# if we are bootstrapping create the default +_want = ${.CURDIR}/${.MAKE.DEPENDFILE_DEFAULT:T} + +.if exists(${_want}) +# stop here +${.TARGETS:Mboot*}: +.elif !make(bootstrap-empty) +# find a Makefile.depend to use as _src +_src != cd ${.CURDIR} && for m in ${.MAKE.DEPENDFILE_PREFERENCE:T:S,${MACHINE},*,}; do test -s $$m || continue; echo $$m; break; done; echo +.if empty(_src) +.error cannot find any of ${.MAKE.DEPENDFILE_PREFERENCE:T}${.newline}Use: bootstrap-empty +.endif + +_src?= ${.MAKE.DEPENDFILE} + +.MAKE.DEPENDFILE_BOOTSTRAP_SED+= -e 's/${_src:E:C/,.*//}/${MACHINE}/g' + +# just create Makefile.depend* for this dir +bootstrap-this: .NOTMAIN + @echo Bootstrapping ${RELDIR}/${_want:T} from ${_src:T}; \ + echo You need to build ${RELDIR} to correctly populate it. +.if ${_src:T} != ${.MAKE.DEPENDFILE_PREFIX:T} + (cd ${.CURDIR} && sed ${.MAKE.DEPENDFILE_BOOTSTRAP_SED} ${_src} > ${_want:T}) +.else + cp ${.CURDIR}/${_src:T} ${_want} +.endif + +# create Makefile.depend* for this dir and its dependencies +bootstrap: bootstrap-recurse +bootstrap-recurse: bootstrap-this + +_mf := ${.PARSEFILE} +bootstrap-recurse: .NOTMAIN .MAKE + @cd ${SRCTOP} && \ + for d in `cd ${RELDIR} && ${.MAKE} -B -f ${"${.MAKEFLAGS:M-n}":?${_src}:${.MAKE.DEPENDFILE:T}} -V DIRDEPS`; do \ + test -d $$d || d=$${d%.*}; \ + test -d $$d || continue; \ + echo "Checking $$d for bootstrap ..."; \ + (cd $$d && ${.MAKE} -f ${_mf} bootstrap-recurse); \ + done + +.endif + +# create an empty Makefile.depend* to get the ball rolling. +bootstrap-empty: .NOTMAIN .NOMETA + @echo Creating empty ${RELDIR}/${_want:T}; \ + echo You need to build ${RELDIR} to correctly populate it. + @{ echo DIRDEPS=; echo ".include "; } > ${_want} + +.endif Index: vendor/NetBSD/bmake/20201101/mk/install-mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/install-mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/install-mk (revision 367461) @@ -0,0 +1,185 @@ +: +# NAME: +# install-mk - install mk files +# +# SYNOPSIS: +# install-mk [options] [var=val] [dest] +# +# DESCRIPTION: +# This tool installs mk files in a semi-intelligent manner into +# "dest". +# +# Options: +# +# -n just say what we want to do, but don't touch anything. +# +# -f use -f when copying sys,mk. +# +# -v be verbose +# +# -q be quiet +# +# -m "mode" +# Use "mode" for installed files (444). +# +# -o "owner" +# Use "owner" for installed files. +# +# -g "group" +# Use "group" for installed files. +# +# var=val +# Set "var" to "val". See below. +# +# All our *.mk files are copied to "dest" with appropriate +# ownership and permissions. +# +# By default if a sys.mk can be found in a standard location +# (that bmake will find) then no sys.mk will be put in "dest". +# +# SKIP_SYS_MK: +# If set, we will avoid installing our 'sys.mk' +# This is probably a bad idea. +# +# SKIP_BSD_MK: +# If set, we will skip making bsd.*.mk links to *.mk +# +# sys.mk: +# +# By default (and provided we are not installing to the system +# mk dir - '/usr/share/mk') we install our own 'sys.mk' which +# includes a sys specific file, or a generic one. +# +# +# AUTHOR: +# Simon J. Gerraty + +# RCSid: +# $Id: install-mk,v 1.183 2020/11/02 16:34:12 sjg Exp $ +# +# @(#) Copyright (c) 1994 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +MK_VERSION=20201101 +OWNER= +GROUP= +MODE=444 +BINMODE=555 +ECHO=: +SKIP= +cp_f=-f + +while : +do + case "$1" in + *=*) eval "$1"; shift;; + +f) cp_f=; shift;; + -f) cp_f=-f; shift;; + -m) MODE=$2; shift 2;; + -o) OWNER=$2; shift 2;; + -g) GROUP=$2; shift 2;; + -v) ECHO=echo; shift;; + -q) ECHO=:; shift;; + -n) ECHO=echo SKIP=:; shift;; + --) shift; break;; + *) break;; + esac +done + +case $# in +0) echo "$0 [options] []" + echo "eg." + echo "$0 -o bin -g bin -m 444 /usr/local/share/mk" + exit 1 + ;; +esac +dest=$1 +os=${2:-`uname`} +osrel=${3:-`uname -r`} + +Do() { + $ECHO "$@" + $SKIP "$@" +} + +Error() { + echo "ERROR: $@" >&2 + exit 1 +} + +Warning() { + echo "WARNING: $@" >&2 +} + +[ "$FORCE_SYS_MK" ] && Warning "ignoring: FORCE_{BSD,SYS}_MK (no longer supported)" + +SYS_MK_DIR=${SYS_MK_DIR:-/usr/share/mk} +SYS_MK=${SYS_MK:-$SYS_MK_DIR/sys.mk} + +realpath() { + [ -d $1 ] && cd $1 && 'pwd' && return + echo $1 +} + +if [ -s $SYS_MK -a -d $dest ]; then + # if this is a BSD system we don't want to touch $SYS_MK + dest=`realpath $dest` + sys_mk_dir=`realpath $SYS_MK_DIR` + if [ $dest = $sys_mk_dir ]; then + case "$os" in + *BSD*) SKIP_SYS_MK=: + SKIP_BSD_MK=: + ;; + *) # could be fake? + if [ ! -d $dest/sys -a ! -s $dest/Generic.sys.mk ]; then + SKIP_SYS_MK=: # play safe + SKIP_BSD_MK=: + fi + ;; + esac + fi +fi + +[ -d $dest/sys ] || Do mkdir -p $dest/sys +[ -d $dest/sys ] || Do mkdir $dest/sys || exit 1 +[ -z "$SKIP" ] && dest=`realpath $dest` + +cd `dirname $0` +mksrc=`'pwd'` +if [ $mksrc = $dest ]; then + SKIP_MKFILES=: +else + # we do not install the examples + mk_files=`grep '^[a-z].*\.mk' FILES | egrep -v '(examples/|^sys\.mk|sys/)'` + mk_scripts=`egrep '^[a-z].*\.(sh|py)' FILES | egrep -v '/'` + sys_mk_files=`grep 'sys/.*\.mk' FILES` + SKIP_MKFILES= + [ -z "$SKIP_SYS_MK" ] && mk_files="sys.mk $mk_files" +fi +$SKIP_MKFILES Do cp $cp_f $mk_files $dest +$SKIP_MKFILES Do cp $cp_f $sys_mk_files $dest/sys +$SKIP_MKFILES Do cp $cp_f $mk_scripts $dest +$SKIP cd $dest +$SKIP_MKFILES Do chmod $MODE $mk_files $sys_mk_files +$SKIP_MKFILES Do chmod $BINMODE $mk_scripts +[ "$GROUP" ] && $SKIP_MKFILES Do chgrp $GROUP $mk_files $sys_mk_files +[ "$OWNER" ] && $SKIP_MKFILES Do chown $OWNER $mk_files $sys_mk_files +# if this is a BSD system the bsd.*.mk should exist and be used. +if [ -z "$SKIP_BSD_MK" ]; then + for f in dep doc files inc init lib links man nls obj own prog subdir + do + b=bsd.$f.mk + [ -s $b ] || Do ln -s $f.mk $b + done +fi +exit 0 Index: vendor/NetBSD/bmake/20201101/mk/meta2deps.py =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta2deps.py (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta2deps.py (revision 367461) @@ -0,0 +1,768 @@ +#!/usr/bin/env python + +from __future__ import print_function + +""" +This script parses each "meta" file and extracts the +information needed to deduce build and src dependencies. + +It works much the same as the original shell script, but is +*much* more efficient. + +The parsing work is handled by the class MetaFile. +We only pay attention to a subset of the information in the +"meta" files. Specifically: + +'CWD' to initialize our notion. + +'C' to track chdir(2) on a per process basis + +'R' files read are what we really care about. + directories read, provide a clue to resolving + subsequent relative paths. That is if we cannot find + them relative to 'cwd', we check relative to the last + dir read. + +'W' files opened for write or read-write, + for filemon V3 and earlier. + +'E' files executed. + +'L' files linked + +'V' the filemon version, this record is used as a clue + that we have reached the interesting bit. + +""" + +""" +RCSid: + $Id: meta2deps.py,v 1.34 2020/10/02 03:11:17 sjg Exp $ + + Copyright (c) 2011-2020, Simon J. Gerraty + Copyright (c) 2011-2017, Juniper Networks, Inc. + 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 + OWNER 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. + +""" + +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. + """ + if path.endswith('/.'): + path = path[0:-2] + if len(path) > 0 and path[0] == '/': + if os.path.exists(path): + return path + if debug > 2: + print("skipping non-existent:", path, file=debug_out) + return None + if path == '.': + return cwd + if path.startswith('./'): + return cwd + path[1:] + if last_dir == cwd: + last_dir = None + for d in [last_dir, cwd]: + if not d: + continue + if path == '..': + dw = d.split('/') + p = '/'.join(dw[:-1]) + if not p: + p = '/' + return p + p = '/'.join([d,path]) + if debug > 2: + print("looking for:", p, end=' ', file=debug_out) + if not os.path.exists(p): + if debug > 2: + print("nope", file=debug_out) + p = None + continue + if debug > 2: + print("found:", p, file=debug_out) + return p + return None + +def cleanpath(path): + """cleanup path without using realpath(3)""" + if path.startswith('/'): + r = '/' + else: + r = '' + p = [] + w = path.split('/') + for d in w: + if not d or d == '.': + continue + if d == '..': + try: + p.pop() + continue + except: + break + p.append(d) + + return r + '/'.join(p) + +def abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): + """ + Return an absolute path, resolving via cwd or last_dir if needed. + this gets called a lot, so we try to avoid calling realpath. + """ + rpath = resolve(path, cwd, last_dir, debug, debug_out) + if rpath: + path = rpath + elif len(path) > 0 and path[0] == '/': + return None + if (path.find('/') < 0 or + path.find('./') > 0 or + path.endswith('/..')): + path = cleanpath(path) + return path + +def sort_unique(list, cmp=None, key=None, reverse=False): + list.sort(cmp, key, reverse) + nl = [] + le = None + for e in list: + if e == le: + continue + le = e + nl.append(e) + return nl + +def add_trims(x): + return ['/' + x + '/', + '/' + x, + x + '/', + x] + +class MetaFile: + """class to parse meta files generated by bmake.""" + + conf = None + dirdep_re = None + host_target = None + srctops = [] + objroots = [] + excludes = [] + seen = {} + obj_deps = [] + src_deps = [] + file_deps = [] + + def __init__(self, name, conf={}): + """if name is set we will parse it now. + conf can have the follwing keys: + + SRCTOPS list of tops of the src tree(s). + + CURDIR the src directory 'bmake' was run from. + + RELDIR the relative path from SRCTOP to CURDIR + + MACHINE the machine we built for. + set to 'none' if we are not cross-building. + More specifically if machine cannot be deduced from objdirs. + + TARGET_SPEC + Sometimes MACHINE isn't enough. + + HOST_TARGET + when we build for the pseudo machine 'host' + the object tree uses HOST_TARGET rather than MACHINE. + + OBJROOTS a list of the common prefix for all obj dirs it might + end in '/' or '-'. + + DPDEPS names an optional file to which per file dependencies + will be appended. + For example if 'some/path/foo.h' is read from SRCTOP + then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. + This can allow 'bmake' to learn all the dirs within + the tree that depend on 'foo.h' + + EXCLUDES + A list of paths to ignore. + ccache(1) can otherwise be trouble. + + debug desired debug level + + debug_out open file to send debug output to (sys.stderr) + + """ + + self.name = name + self.debug = getv(conf, 'debug', 0) + self.debug_out = getv(conf, '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.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', []): + if srctop[-1] != '/': + srctop += '/' + if not srctop in self.srctops: + self.srctops.append(srctop) + _srctop = os.path.realpath(srctop) + if _srctop[-1] != '/': + _srctop += '/' + if not _srctop in self.srctops: + self.srctops.append(_srctop) + + trim_list = add_trims(self.machine) + if self.machine == 'host': + trim_list += add_trims(self.host_target) + if self.target_spec: + trim_list += add_trims(self.target_spec) + + for objroot in getv(conf, 'OBJROOTS', []): + for e in trim_list: + if objroot.endswith(e): + # this is not what we want - fix it + objroot = objroot[0:-len(e)] + + if objroot[-1] != '/': + objroot += '/' + if not objroot in self.objroots: + self.objroots.append(objroot) + _objroot = os.path.realpath(objroot) + if objroot[-1] == '/': + _objroot += '/' + if not _objroot in self.objroots: + self.objroots.append(_objroot) + + # we want the longest match + self.srctops.sort(reverse=True) + self.objroots.sort(reverse=True) + + self.excludes = getv(conf, 'EXCLUDES', []) + + if self.debug: + print("host_target=", self.host_target, file=self.debug_out) + print("srctops=", self.srctops, file=self.debug_out) + print("objroots=", self.objroots, file=self.debug_out) + print("excludes=", self.excludes, file=self.debug_out) + + self.dirdep_re = re.compile(r'([^/]+)/(.+)') + + if self.dpdeps and not self.reldir: + if self.debug: + print("need reldir:", end=' ', file=self.debug_out) + if self.curdir: + srctop = self.find_top(self.curdir, self.srctops) + if srctop: + self.reldir = self.curdir.replace(srctop,'') + if self.debug: + print(self.reldir, file=self.debug_out) + if not self.reldir: + self.dpdeps = None # we cannot do it? + + self.cwd = os.getcwd() # make sure this is initialized + self.last_dir = self.cwd + + if name: + self.try_parse() + + def reset(self): + """reset state if we are being passed meta files from multiple directories.""" + self.seen = {} + self.obj_deps = [] + self.src_deps = [] + self.file_deps = [] + + def dirdeps(self, sep='\n'): + """return DIRDEPS""" + return sep.strip() + sep.join(self.obj_deps) + + def src_dirdeps(self, sep='\n'): + """return SRC_DIRDEPS""" + return sep.strip() + sep.join(self.src_deps) + + def file_depends(self, out=None): + """Append DPDEPS_${file} += ${RELDIR} + for each file we saw, to the output file.""" + if not self.reldir: + return None + for f in sort_unique(self.file_deps): + print('DPDEPS_%s += %s' % (f, self.reldir), file=out) + # these entries provide for reverse DIRDEPS lookup + for f in self.obj_deps: + print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) + + def seenit(self, dir): + """rememer that we have seen dir.""" + self.seen[dir] = 1 + + def add(self, list, data, clue=''): + """add data to list if it isn't already there.""" + if data not in list: + list.append(data) + if self.debug: + print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) + + def find_top(self, path, list): + """the logical tree may be split across multiple trees""" + for top in list: + if path.startswith(top): + if self.debug > 2: + print("found in", top, file=self.debug_out) + return top + return None + + def find_obj(self, objroot, dir, path, input): + """return path within objroot, taking care of .dirdep files""" + ddep = None + for ddepf in [path + '.dirdep', dir + '/.dirdep']: + if not ddep and os.path.exists(ddepf): + ddep = open(ddepf, 'r').readline().strip('# \n') + if self.debug > 1: + print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) + if ddep.endswith(self.machine): + ddep = ddep[0:-(1+len(self.machine))] + elif self.target_spec and ddep.endswith(self.target_spec): + ddep = ddep[0:-(1+len(self.target_spec))] + + if not ddep: + # no .dirdeps, so remember that we've seen the raw input + self.seenit(input) + self.seenit(dir) + if self.machine == 'none': + if dir.startswith(objroot): + return dir.replace(objroot,'') + return None + m = self.dirdep_re.match(dir.replace(objroot,'')) + if m: + ddep = m.group(2) + dmachine = m.group(1) + if dmachine != self.machine: + if not (self.machine == 'host' and + dmachine == self.host_target): + if self.debug > 2: + print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) + ddep += '.' + dmachine + + return ddep + + def try_parse(self, name=None, file=None): + """give file and line number causing exception""" + try: + self.parse(name, file) + except: + # give a useful clue + print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) + raise + + def parse(self, name=None, file=None): + """A meta file looks like: + + # Meta data file "path" + CMD "command-line" + CWD "cwd" + TARGET "target" + -- command output -- + -- filemon acquired metadata -- + # buildmon version 3 + V 3 + C "pid" "cwd" + E "pid" "path" + F "pid" "child" + R "pid" "path" + W "pid" "path" + X "pid" "status" + D "pid" "path" + L "pid" "src" "target" + M "pid" "old" "new" + S "pid" "path" + # Bye bye + + We go to some effort to avoid processing a dependency more than once. + Of the above record types only C,E,F,L,R,V and W are of interest. + """ + + version = 0 # unknown + if name: + self.name = name; + if file: + f = file + cwd = self.last_dir = self.cwd + else: + f = open(self.name, 'r') + skip = True + pid_cwd = {} + pid_last_dir = {} + last_pid = 0 + + self.line = 0 + if self.curdir: + self.seenit(self.curdir) # we ignore this + + interesting = 'CEFLRV' + for line in f: + self.line += 1 + # ignore anything we don't care about + if not line[0] in interesting: + continue + if self.debug > 2: + print("input:", line, end=' ', file=self.debug_out) + w = line.split() + + if skip: + if w[0] == 'V': + skip = False + version = int(w[1]) + """ + if version < 4: + # we cannot ignore 'W' records + # as they may be 'rw' + interesting += 'W' + """ + elif w[0] == 'CWD': + self.cwd = cwd = self.last_dir = w[1] + self.seenit(cwd) # ignore this + if self.debug: + print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) + continue + + pid = int(w[1]) + 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) + last_pid = pid + + # process operations + if w[0] == 'F': + npid = int(w[2]) + pid_cwd[npid] = cwd + pid_last_dir[npid] = cwd + last_pid = npid + continue + elif w[0] == 'C': + cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) + if not cwd: + cwd = w[2] + if self.debug > 1: + print("missing cwd=", cwd, file=self.debug_out) + if cwd.endswith('/.'): + cwd = cwd[0:-2] + self.last_dir = pid_last_dir[pid] = cwd + pid_cwd[pid] = cwd + if self.debug > 1: + print("cwd=", cwd, file=self.debug_out) + continue + + if w[2] in self.seen: + if self.debug > 2: + print("seen:", w[2], file=self.debug_out) + continue + # file operations + if w[0] in 'ML': + # these are special, tread src as read and + # target as write + self.parse_path(w[2].strip("'"), cwd, 'R', w) + self.parse_path(w[3].strip("'"), cwd, 'W', w) + continue + elif w[0] in 'ERWS': + path = w[2] + if path == '.': + continue + self.parse_path(path, cwd, w[0], w) + + assert(version > 0) + if not file: + f.close() + + def is_src(self, base, dir, rdir): + """is base in srctop""" + for dir in [dir,rdir]: + if not dir: + continue + path = '/'.join([dir,base]) + srctop = self.find_top(path, self.srctops) + if srctop: + if self.dpdeps: + self.add(self.file_deps, path.replace(srctop,''), 'file') + self.add(self.src_deps, dir.replace(srctop,''), 'src') + self.seenit(dir) + return True + return False + + def parse_path(self, path, cwd, op=None, w=[]): + """look at a path for the op specified""" + + if not op: + op = w[0] + + # we are never interested in .dirdep files as dependencies + if path.endswith('.dirdep'): + return + for p in self.excludes: + if p and path.startswith(p): + if self.debug > 2: + print("exclude:", p, path, file=self.debug_out) + return + # we don't want to resolve the last component if it is + # a symlink + path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) + if not path: + return + dir,base = os.path.split(path) + if dir in self.seen: + if self.debug > 2: + print("seen:", dir, file=self.debug_out) + return + # we can have a path in an objdir which is a link + # 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 rdir == dir: + rdir = None + # now put path back together + path = '/'.join([dir,base]) + if self.debug > 1: + print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) + if op in 'RWS': + if path in [self.last_dir, cwd, self.cwd, self.curdir]: + if self.debug > 1: + print("skipping:", path, file=self.debug_out) + return + if os.path.isdir(path): + if op in 'RW': + self.last_dir = path; + if self.debug > 1: + print("ldir=", self.last_dir, file=self.debug_out) + return + + if op in 'ER': + # finally, we get down to it + if dir == self.cwd or dir == self.curdir: + return + if self.is_src(base, dir, rdir): + self.seenit(w[2]) + if not rdir: + return + + objroot = None + for dir in [dir,rdir]: + if not dir: + continue + objroot = self.find_top(dir, self.objroots) + if objroot: + break + if objroot: + ddep = self.find_obj(objroot, dir, path, w[2]) + if ddep: + self.add(self.obj_deps, ddep, 'obj') + if self.dpdeps and objroot.endswith('/stage/'): + sp = '/'.join(path.replace(objroot,'').split('/')[1:]) + self.add(self.file_deps, sp, 'file') + else: + # don't waste time looking again + self.seenit(w[2]) + self.seenit(dir) + + +def main(argv, klass=MetaFile, xopts='', xoptf=None): + """Simple driver for class MetaFile. + + Usage: + script [options] [key=value ...] "meta" ... + + Options and key=value pairs contribute to the + dictionary passed to MetaFile. + + -S "SRCTOP" + add "SRCTOP" to the "SRCTOPS" list. + + -C "CURDIR" + + -O "OBJROOT" + add "OBJROOT" to the "OBJROOTS" list. + + -m "MACHINE" + + -a "MACHINE_ARCH" + + -H "HOST_TARGET" + + -D "DPDEPS" + + -d bumps debug level + + """ + import getopt + + # import Psyco if we can + # it can speed things up quite a bit + have_psyco = 0 + try: + import psyco + psyco.full() + have_psyco = 1 + except: + pass + + conf = { + 'SRCTOPS': [], + 'OBJROOTS': [], + 'EXCLUDES': [], + } + + try: + machine = os.environ['MACHINE'] + if machine: + conf['MACHINE'] = machine + machine_arch = os.environ['MACHINE_ARCH'] + if machine_arch: + conf['MACHINE_ARCH'] = machine_arch + srctop = os.environ['SB_SRC'] + if srctop: + conf['SRCTOPS'].append(srctop) + objroot = os.environ['SB_OBJROOT'] + if objroot: + conf['OBJROOTS'].append(objroot) + except: + pass + + debug = 0 + output = True + + opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) + for o, a in opts: + if o == '-a': + conf['MACHINE_ARCH'] = a + elif o == '-d': + debug += 1 + elif o == '-q': + output = False + elif o == '-H': + conf['HOST_TARGET'] = a + elif o == '-S': + if a not in conf['SRCTOPS']: + conf['SRCTOPS'].append(a) + elif o == '-C': + conf['CURDIR'] = a + elif o == '-O': + if a not in conf['OBJROOTS']: + conf['OBJROOTS'].append(a) + elif o == '-R': + conf['RELDIR'] = a + elif o == '-D': + conf['DPDEPS'] = a + elif o == '-m': + conf['MACHINE'] = a + elif o == '-T': + conf['TARGET_SPEC'] = a + elif o == '-X': + if a not in conf['EXCLUDES']: + conf['EXCLUDES'].append(a) + elif xoptf: + xoptf(o, a, conf) + + conf['debug'] = debug + + # get any var=val assignments + eaten = [] + for a in args: + if a.find('=') > 0: + k,v = a.split('=') + if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: + if k == 'SRCTOP': + k = 'SRCTOPS' + elif k == 'OBJROOT': + k = 'OBJROOTS' + if v not in conf[k]: + conf[k].append(v) + else: + conf[k] = v + eaten.append(a) + continue + break + + for a in eaten: + args.remove(a) + + debug_out = getv(conf, 'debug_out', sys.stderr) + + if debug: + print("config:", file=debug_out) + print("psyco=", have_psyco, file=debug_out) + for k,v in list(conf.items()): + print("%s=%s" % (k,v), file=debug_out) + + m = None + for a in args: + if a.endswith('.meta'): + if not os.path.exists(a): + continue + m = klass(a, conf) + elif a.startswith('@'): + # there can actually multiple files per line + for line in open(a[1:]): + for f in line.strip().split(): + if not os.path.exists(f): + continue + m = klass(f, conf) + + if output and m: + print(m.dirdeps()) + + print(m.src_dirdeps('\nsrc:')) + + dpdeps = getv(conf, 'DPDEPS') + if dpdeps: + m.file_depends(open(dpdeps, 'wb')) + + return m + +if __name__ == '__main__': + try: + main(sys.argv) + except: + # yes, this goes to stdout + print("ERROR: ", sys.exc_info()[1]) + raise + Property changes on: vendor/NetBSD/bmake/20201101/mk/meta2deps.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/meta2deps.sh =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta2deps.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta2deps.sh (revision 367461) @@ -0,0 +1,420 @@ +#!/bin/sh + +# NAME: +# meta2deps.sh - extract useful info from .meta files +# +# SYNOPSIS: +# meta2deps.sh SB="SB" "meta" ... +# +# DESCRIPTION: +# This script looks each "meta" file and extracts the +# information needed to deduce build and src dependencies. +# +# To do this, we extract the 'CWD' record as well as all the +# syscall traces which describe 'R'ead, 'C'hdir and 'E'xec +# syscalls. +# +# The typical meta file looks like:: +#.nf +# +# # Meta data file "path" +# CMD "command-line" +# CWD "cwd" +# TARGET "target" +# -- command output -- +# -- filemon acquired metadata -- +# # buildmon version 2 +# V 2 +# E "pid" "path" +# R "pid" "path" +# C "pid" "cwd" +# R "pid" "path" +# X "pid" "status" +#.fi +# +# The fact that all the syscall entry lines start with a single +# character make these files quite easy to process using sed(1). +# +# To simplify the logic the 'CWD' line is made to look like a +# normal 'C'hdir entry, and "cwd" is remembered so that it can +# be prefixed to any "path" which is not absolute. +# +# If the "path" being read ends in '.srcrel' it is the content +# of (actually the first line of) that file that we are +# interested in. +# +# Any "path" which lies outside of the sandbox "SB" is generally +# not of interest and is ignored. +# +# The output, is a set of absolute paths with "SB" like: +#.nf +# +# $SB/obj-i386/bsd/gnu/lib/csu +# $SB/obj-i386/bsd/gnu/lib/libgcc +# $SB/obj-i386/bsd/include +# $SB/obj-i386/bsd/lib/csu/i386-elf +# $SB/obj-i386/bsd/lib/libc +# $SB/src/bsd/include +# $SB/src/bsd/sys/i386/include +# $SB/src/bsd/sys/sys +# $SB/src/pan-release/rtsock +# $SB/src/pfe-shared/include/jnx +#.fi +# +# Which can then be further processed by 'gendirdeps.mk' +# +# If we are passed 'DPDEPS='"dpdeps", then for each src file +# outside of "CURDIR" we read, we output a line like: +#.nf +# +# DPDEPS_$path += $RELDIR +#.fi +# +# with "$path" geting turned into reldir's, so that we can end +# up with a list of all the directories which depend on each src +# file in another directory. This can allow for efficient yet +# complete testing of changes. + + +# RCSid: +# $Id: meta2deps.sh,v 1.14 2020/10/02 03:11:17 sjg Exp $ + +# Copyright (c) 2010-2013, Juniper Networks, Inc. +# 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 +# OWNER 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. + +meta2src() { + cat /dev/null "$@" | + sed -n '/^R .*\.[chyl]$/s,^..[0-9]* ,,p' | + sort -u +} + +meta2dirs() { + cat /dev/null "$@" | + sed -n '/^R .*\/.*\.[a-z0-9][^\/]*$/s,^..[0-9]* \(.*\)/[^/]*$,\1,p' | + sort -u +} + +add_list() { + sep=' ' + suffix= + while : + do + case "$1" in + "|") sep="$1"; shift;; + -s) suffix="$2"; shift 2;; + *) break;; + esac + done + name=$1 + shift + eval list="\$$name" + for top in "$@" + do + case "$sep$list$sep" in + *"$sep$top$suffix$sep"*) continue;; + esac + list="${list:+$list$sep}$top$suffix" + done + eval "$name=\"$list\"" +} + +_excludes_f() { + egrep -v "$EXCLUDES" +} + +error() { + echo "ERROR: $@" >&2 + exit 1 +} + +meta2deps() { + DPDEPS= + SRCTOPS=$SRCTOP + OBJROOTS= + EXCLUDES= + while : + do + case "$1" in + *=*) eval export "$1"; shift;; + -a) MACHINE_ARCH=$2; shift 2;; + -m) MACHINE=$2; shift 2;; + -C) CURDIR=$2; shift 2;; + -H) HOST_TARGET=$2; shift 2;; + -S) add_list SRCTOPS $2; shift 2;; + -O) add_list OBJROOTS $2; shift 2;; + -X) add_list EXCLUDES '|' $2; shift 2;; + -R) RELDIR=$2; shift 2;; + -T) TARGET_SPEC=$2; shift 2;; + *) break;; + esac + done + + _th= _o= + case "$MACHINE" in + host) _ht=$HOST_TARGET;; + esac + + for o in $OBJROOTS + do + case "$MACHINE,/$o/" in + host,*$HOST_TARGET*) ;; + *$MACHINE*|*${TARGET_SPEC:-$MACHINE}*) ;; + *) add_list _o $o; continue;; + esac + for x in $_ht $TARGET_SPEC $MACHINE + do + case "$o" in + "") continue;; + */$x/) add_list _o ${o%$x/}; o=;; + */$x) add_list _o ${o%$x}; o=;; + *$x/) add_list _o ${o%$x/}; o=;; + *$x) add_list _o ${o%$x}; o=;; + esac + done + done + OBJROOTS="$_o" + + case "$OBJTOP" in + "") + for o in $OBJROOTS + do + OBJTOP=$o${TARGET_SPEC:-$MACHINE} + break + done + ;; + esac + src_re= + obj_re= + add_list '|' -s '/*' src_re $SRCTOPS + add_list '|' -s '*' obj_re $OBJROOTS + + [ -z "$RELDIR" ] && unset DPDEPS + tf=/tmp/m2d$$-$USER + rm -f $tf.* + trap 'rm -f $tf.*; trap 0' 0 + + > $tf.dirdep + > $tf.qual + > $tf.srcdep + > $tf.srcrel + > $tf.dpdeps + + seenit= + seensrc= + lpid= + case "$EXCLUDES" in + "") _excludes=cat;; + *) _excludes=_excludes_f;; + esac + # handle @list files + case "$@" in + *@[!.]*) + for f in "$@" + do + case "$f" in + *.meta) cat $f;; + @*) xargs cat < ${f#@};; + *) cat $f;; + esac + done + ;; + *) cat /dev/null "$@";; + esac 2> /dev/null | + sed -e 's,^CWD,C C,;/^[CREFLMV] /!d' -e "s,',,g" | + $_excludes | ( version=no + while read op pid path junk + do + : op=$op pid=$pid path=$path + # we track cwd and ldir (of interest) per pid + # CWD is bmake's cwd + case "$lpid,$pid" in + ,C) CWD=$path cwd=$path ldir=$path + if [ -z "$SB" ]; then + SB=`echo $CWD | sed 's,/obj.*,,'` + fi + SRCTOP=${SRCTOP:-$SB/src} + case "$verion" in + no) ;; # ignore + 0) error "no filemon data";; + *) ;; + esac + version=0 + continue + ;; + $pid,$pid) ;; + *) + case "$lpid" in + "") ;; + *) eval ldir_$lpid=$ldir;; + esac + eval ldir=\${ldir_$pid:-$CWD} cwd=\${cwd_$pid:-$CWD} + lpid=$pid + ;; + esac + + case "$op,$path" in + V,*) version=$path; continue;; + W,*srcrel|*.dirdep) continue;; + C,*) + case "$path" in + /*) cwd=$path;; + *) cwd=`cd $cwd/$path 2> /dev/null && /bin/pwd`;; + esac + # watch out for temp dirs that no longer exist + test -d ${cwd:-/dev/null/no/such} || cwd=$CWD + eval cwd_$pid=$cwd + continue + ;; + F,*) # $path is new pid + eval cwd_$path=$cwd ldir_$path=$ldir + continue + ;; + *) dir=${path%/*} + case "$path" in + $src_re|$obj_re) ;; + /*/stage/*) ;; + /*) continue;; + *) for path in $ldir/$path $cwd/$path + do + test -e $path && break + done + dir=${path%/*} + ;; + esac + ;; + esac + # avoid repeating ourselves... + case "$DPDEPS,$seensrc," in + ,*) + case ",$seenit," in + *,$dir,*) continue;; + esac + ;; + *,$path,*) continue;; + esac + # canonicalize if needed + case "/$dir/" in + */../*|*/./*) + rdir=$dir + dir=`cd $dir 2> /dev/null && /bin/pwd` + seen="$rdir,$dir" + ;; + *) seen=$dir;; + esac + case "$dir" in + ${CURDIR:-.}|"") continue;; + $src_re) + # avoid repeating ourselves... + case "$DPDEPS,$seensrc," in + ,*) + case ",$seenit," in + *,$dir,*) continue;; + esac + ;; + esac + ;; + *) + case ",$seenit," in + *,$dir,*) continue;; + esac + ;; + esac + if [ -d $path ]; then + case "$path" in + */..) ldir=${dir%/*};; + *) ldir=$path;; + esac + continue + fi + [ -f $path ] || continue + case "$dir" in + $CWD) continue;; # ignore + $src_re) + seenit="$seenit,$seen" + echo $dir >> $tf.srcdep + case "$DPDEPS,$reldir,$seensrc," in + ,*) ;; + *) seensrc="$seensrc,$path" + echo "DPDEPS_$dir/${path##*/} += $RELDIR" >> $tf.dpdeps + ;; + esac + continue + ;; + esac + # if there is a .dirdep we cannot skip + # just because we've seen the dir before. + if [ -s $path.dirdep ]; then + # this file contains: + # '# ${RELDIR}.' + echo $path.dirdep >> $tf.qual + continue + elif [ -s $dir.dirdep ]; then + echo $dir.dirdep >> $tf.qual + seenit="$seenit,$seen" + continue + fi + seenit="$seenit,$seen" + case "$dir" in + $obj_re) + echo $dir;; + esac + done > $tf.dirdep + case "$version" in + 0) error "no filemon data";; + esac ) || exit 1 + _nl=echo + for f in $tf.dirdep $tf.qual $tf.srcdep + do + [ -s $f ] || continue + case $f in + *qual) # a list of .dirdep files + # we can prefix everything with $OBJTOP to + # tell gendirdeps.mk that these are + # DIRDEP entries, since they are already + # qualified with . as needed. + # We strip .$MACHINE though + xargs cat < $f | sort -u | + sed "s,^# ,,;s,^,$OBJTOP/,;s,\.${TARGET_SPEC:-$MACHINE}\$,,;s,\.$MACHINE\$,," + ;; + *) sort -u $f;; + esac + _nl=: + done + if [ -s $tf.dpdeps ]; then + case "$DPDEPS" in + */*) ;; + *) echo > $DPDEPS;; # the echo is needed! + esac + sort -u $tf.dpdeps | + sed "s,${SRCTOP}/,,;s,${SB_BACKING_SB:-$SB}/src/,," >> $DPDEPS + fi + # ensure we produce _something_ else egrep -v gets upset + $_nl +} + +case /$0 in +*/meta2dep*) meta2deps "$@";; +*/meta2dirs*) meta2dirs "$@";; +*/meta2src*) meta2src "$@";; +esac Property changes on: vendor/NetBSD/bmake/20201101/mk/meta2deps.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/sys.vars.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys.vars.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys.vars.mk (revision 367461) @@ -0,0 +1,99 @@ +# $Id: sys.vars.mk,v 1.6 2020/10/28 20:50:04 sjg Exp $ +# +# @(#) Copyright (c) 2003-2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# We use the following paradigm for preventing multiple inclusion. +# It relies on the fact that conditionals and dependencies are resolved +# at the time they are read. +# +# _this ?= ${.PARSEFILE} +# .if !target(__${_this}__) +# __${_this}__: +# +.if ${MAKE_VERSION:U0} > 20100408 +_this = ${.PARSEDIR:tA}/${.PARSEFILE} +.else +_this = ${.PARSEDIR}/${.PARSEFILE} +.endif + +# if this is an ancient version of bmake +MAKE_VERSION ?= 0 +.if ${MAKE_VERSION:M*make-*} +# turn it into what we want - just the date +MAKE_VERSION := ${MAKE_VERSION:[1]:C,.*-,,} +.endif + +# some useful modifiers + +# A useful trick for testing multiple :M's against something +# :L says to use the variable's name as its value - ie. literal +# got = ${clean* destroy:${M_ListToMatch:S,V,.TARGETS,}} +M_ListToMatch = L:@m@$${V:M$$m}@ +# match against our initial targets (see above) +M_L_TARGETS = ${M_ListToMatch:S,V,_TARGETS,} + +# turn a list into a set of :N modifiers +# NskipFoo = ${Foo:${M_ListToSkip}} +M_ListToSkip= O:u:S,^,N,:ts: + +# type should be a builtin in any sh since about 1980, +# but sadly there are exceptions! +.if ${.MAKE.OS:Unknown:NBSD/OS} == "" +_type_sh = which +.endif + +# AUTOCONF := ${autoconf:L:${M_whence}} +M_type = @x@(${_type_sh:Utype} $$x) 2> /dev/null; echo;@:sh:[0]:N* found*:[@]:C,[()],,g +M_whence = ${M_type}:M/*:[1] + +# produce similar output to jot(1) +# eg. ${LIST:[#]:${M_JOT}} +# would be 1 2 3 4 5 if LIST has 5 words +# ${9:L:${M_JOT}} +# would be 1 2 3 4 5 6 7 8 9 +M_JOT = @x@i=1;while [ $$$$i -le $$x ]; do echo $$$$i; i=$$$$((i + 1)); done;@:sh + +# ${LIST:${M_RANGE}} is 1 2 3 4 5 if LIST has 5 words +.if ${MAKE_VERSION} >= 20170130 +M_RANGE = range +.else +M_RANGE = [#]:${M_JOT} +.endif + +# convert a path to a valid shell variable +M_P2V = tu:C,[./-],_,g + +# convert path to absolute +.if ${MAKE_VERSION:U0} > 20100408 +M_tA = tA +.else +M_tA = C,.*,('cd' & \&\& 'pwd') 2> /dev/null || echo &,:sh +.endif + +.if ${MAKE_VERSION:U0} >= 20170130 +# M_cmpv allows comparing dotted versions like 3.1.2 +# ${3.1.2:L:${M_cmpv}} -> 3001002 +# we use big jumps to handle 3 digits per dot: +# ${123.456.789:L:${M_cmpv}} -> 123456789 +M_cmpv.units = 1 1000 1000000 +M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh +.endif + +# absoulte path to what we are reading. +_PARSEDIR = ${.PARSEDIR:${M_tA}} + +# many projects use MAJOR MINOR PATCH versioning +# ${OPENSSL:${M_M.M.P_VERSION}} is equivalent to +# ${OPENSSL_MAJOR_VERSION}.${OPENSSL_MINOR_VERSION}.${OPENSSL_PATCH_VERSION} +M_M.M.P_VERSION = L:@v@$${MAJOR MINOR PATCH:L:@t@$${$$v_$$t_VERSION:U0}@}@:ts. Property changes on: vendor/NetBSD/bmake/20201101/mk/sys.vars.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/FILES =================================================================== --- vendor/NetBSD/bmake/20201101/mk/FILES (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/FILES (revision 367461) @@ -0,0 +1,74 @@ +ChangeLog +FILES +LICENSE +README +auto.obj.mk +autoconf.mk +autodep.mk +auto.dep.mk +compiler.mk +cython.mk +dep.mk +doc.mk +dpadd.mk +files.mk +final.mk +host-target.mk +host.libnames.mk +inc.mk +init.mk +install-mk +java.mk +ldorder.mk +lib.mk +libnames.mk +libs.mk +links.mk +man.mk +manifest.mk +mk-files.txt +mkopt.sh +nls.mk +obj.mk +options.mk +own.mk +prlist.mk +prog.mk +progs.mk +rst2htm.mk +scripts.mk +srctop.mk +stage-install.sh +subdir.mk +sys.mk +sys.clean-env.mk +sys.debug.mk +sys.dependfile.mk +sys.vars.mk +sys/AIX.mk +sys/Darwin.mk +sys/Generic.mk +sys/HP-UX.mk +sys/IRIX.mk +sys/Linux.mk +sys/NetBSD.mk +sys/OSF1.mk +sys/OpenBSD.mk +sys/SunOS.mk +sys/UnixWare.mk +target-flags.mk +warnings.mk +whats.mk +yacc.mk +dirdeps.mk +dirdeps-cache-update.mk +dirdeps-options.mk +dirdeps-targets.mk +gendirdeps.mk +install-new.mk +meta2deps.py +meta2deps.sh +meta.sys.mk +meta.autodep.mk +meta.stage.mk +meta.subdir.mk Index: vendor/NetBSD/bmake/20201101/mk/README =================================================================== --- vendor/NetBSD/bmake/20201101/mk/README (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/README (revision 367461) @@ -0,0 +1,401 @@ +# $Id: README,v 1.2 2020/08/19 17:51:53 sjg Exp $ + +This directory contains some macro's derrived from the NetBSD bsd.*.mk +macros. They have the same names but without the bsd., separate macro +files are needed to ensure we can make them do what we want for +builing things outside of /usr/src. Nearly all the comments below +apply. + +# $NetBSD: bsd.README,v 1.18 1997/01/13 00:54:23 mark Exp $ +# @(#)bsd.README 5.1 (Berkeley) 5/11/90 + +This is the README file for the new make "include" files for the BSD +source tree. The files are installed in /usr/share/mk, and are, by +convention, named with the suffix ".mk". + +Note, this file is not intended to replace reading through the .mk +files for anything tricky. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +RANDOM THINGS WORTH KNOWING: + +The files are simply C-style #include files, and pretty much behave like +you'd expect. The syntax is slightly different in that a single '.' is +used instead of the hash mark, i.e. ".include ". + +One difference that will save you lots of debugging time is that inclusion +of the file is normally done at the *end* of the Makefile. The reason for +this is because .mk files often modify variables and behavior based on the +values of variables set in the Makefile. To make this work, remember that +the FIRST target found is the target that is used, i.e. if the Makefile has: + + a: + echo a + a: + echo a number two + +the command "make a" will echo "a". To make things confusing, the SECOND +variable assignment is the overriding one, i.e. if the Makefile has: + + a= foo + a= bar + + b: + echo ${a} + +the command "make b" will echo "bar". This is for compatibility with the +way the V7 make behaved. + +It's fairly difficult to make the BSD .mk files work when you're building +multiple programs in a single directory. It's a lot easier split up the +programs than to deal with the problem. Most of the agony comes from making +the "obj" directory stuff work right, not because we switch to a new version +of make. So, don't get mad at us, figure out a better way to handle multiple +architectures so we can quit using the symbolic link stuff. (Imake doesn't +count.) + +The file .depend in the source directory is expected to contain dependencies +for the source files. This file is read automatically by make after reading +the Makefile. + +The variable DESTDIR works as before. It's not set anywhere but will change +the tree where the file gets installed. + +The profiled libraries are no longer built in a different directory than +the regular libraries. A new suffix, ".po", is used to denote a profiled +object. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file has the default rules for all makes, in the BSD +environment or otherwise. You probably don't want to touch this file. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file handles installing manual pages and their +links. + +It has a single target: + + maninstall: + Install the manual pages and their links. + +It sets/uses the following variables: + +MANDIR Base path for manual installation. + +MANGRP Manual group. + +MANOWN Manual owner. + +MANMODE Manual mode. + +MANSUBDIR Subdirectory under the manual page section, i.e. "/vax" + or "/tahoe" for machine specific manual pages. + +MAN The manual pages to be installed (use a .1 - .9 suffix). + +MLINKS List of manual page links (using a .1 - .9 suffix). The + linked-to file must come first, the linked file second, + and there may be multiple pairs. The files are soft-linked. + +The include file includes a file named "../Makefile.inc" if +it exists. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file contains source tree configuration parameters, +such as the owners, groups, etc. for both manual pages and binaries, and +a few global "feature configuration" parameters. + +It has no targets. + +To get system-specific configuration parameters, bsd.own.mk will try to +include the file specified by the "MAKECONF" variable. If MAKECONF is not +set, or no such file exists, the system make configuration file, /etc/mk.conf +is included. These files may define any of the variables described below. + +bsd.own.mk sets the following variables, if they are not already defined +(defaults are in brackets): + +BSDSRCDIR The real path to the system sources, so that 'make obj' + will work correctly. [/usr/src] + +BSDOBJDIR The real path to the system 'obj' tree, so that 'make obj' + will work correctly. [/usr/obj] + +BINGRP Binary group. [bin] + +BINOWN Binary owner. [bin] + +BINMODE Binary mode. [555] + +NONBINMODE Mode for non-executable files. [444] + +MANDIR Base path for manual installation. [/usr/share/man/cat] + +MANGRP Manual group. [bin] + +MANOWN Manual owner. [bin] + +MANMODE Manual mode. [${NONBINMODE}] + +LIBDIR Base path for library installation. [/usr/lib] + +LINTLIBDIR Base path for lint(1) library installation. [/usr/libdata/lint] + +LIBGRP Library group. [${BINGRP}] + +LIBOWN Library owner. [${BINOWN}] + +LIBMODE Library mode. [${NONBINMODE}] + +DOCDIR Base path for system documentation (e.g. PSD, USD, etc.) + installation. [/usr/share/doc] + +DOCGRP Documentation group. [bin] + +DOCOWN Documentation owner. [bin] + +DOCMODE Documentation mode. [${NONBINMODE}] + +NLSDIR Base path for National Language Support files installation. + [/usr/share/nls] + +NLSGRP National Language Support files group. [bin] + +NLSOWN National Language Support files owner. [bin] + +NLSMODE National Language Support files mode. [${NONBINMODE}] + +STRIP The flag passed to the install program to cause the binary + to be stripped. This is to be used when building your + own install script so that the entire system can be made + stripped/not-stripped using a single knob. [-s] + +COPY The flag passed to the install program to cause the binary + to be copied rather than moved. This is to be used when + building our own install script so that the entire system + can either be installed with copies, or with moves using + a single knob. [-c] + +Additionally, the following variables may be set by bsd.own.mk or in a +make configuration file to modify the behaviour of the system build +process (default values are in brackets along with comments, if set by +bsd.own.mk): + +EXPORTABLE_SYSTEM + Do not build /usr/src/domestic, even if it is present. + +SKEY Compile in support for S/key authentication. [yes, set + unconditionally] + +KERBEROS Compile in support for Kerberos 4 authentication. + +KERBEROS5 Compile in support for Kerberos 5 authentication. + +MANZ Compress manual pages at installation time. + +SYS_INCLUDE Copy or symlink kernel include files into /usr/include. + Possible values are "symlinks" or "copies" (which is + the same as the variable being unset). + +NOPROFILE Do not build profiled versions of system libraries + +NOPIC Do not build PIC versions of system libraries, and + do not build shared libraries. [set if ${MACHINE_ARCH} + is "mips", "vax", "alpha" or "arm32", unset otherwise.] + +NOLINT Do not build lint libraries. [set, set unconditionally] + +bsd.own.mk is generally useful when building your own Makefiles so that +they use the same default owners etc. as the rest of the tree. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file handles building programs from one or +more source files, along with their manual pages. It has a limited number +of suffixes, consistent with the current needs of the BSD tree. + +It has eight targets: + + all: + build the program and its manual page + clean: + remove the program, any object files and the files a.out, + Errs, errs, mklog, and core. + cleandir: + remove all of the files removed by the target clean, as + well as .depend, tags, and any manual pages. + depend: + make the dependencies for the source files, and store + them in the file .depend. + includes: + install any header files. + install: + install the program and its manual pages; if the Makefile + does not itself define the target install, the targets + beforeinstall and afterinstall may also be used to cause + actions immediately before and after the install target + is executed. + lint: + run lint on the source files + tags: + create a tags file for the source files. + +It sets/uses the following variables: + +BINGRP Binary group. + +BINOWN Binary owner. + +BINMODE Binary mode. + +CLEANFILES Additional files to remove for the clean and cleandir targets. + +COPTS Additional flags to the compiler when creating C objects. + +HIDEGAME If HIDEGAME is defined, the binary is installed in + /usr/games/hide, and a symbolic link is created to + /usr/games/dm. + +LDADD Additional loader objects. Usually used for libraries. + For example, to load with the compatibility and utility + libraries, use: + + LDADD+=-lutil -lcompat + +LDFLAGS Additional loader flags. + +LINKS The list of binary links; should be full pathnames, the + linked-to file coming first, followed by the linked + file. The files are hard-linked. For example, to link + /bin/test and /bin/[, use: + + LINKS= ${DESTDIR}/bin/test ${DESTDIR}/bin/[ + +MAN Manual pages (should end in .1 - .9). If no MAN variable is + defined, "MAN=${PROG}.1" is assumed. + +PROG The name of the program to build. If not supplied, nothing + is built. + +SRCS List of source files to build the program. If PROG is not + defined, it's assumed to be ${PROG}.c. + +DPADD Additional dependencies for the program. Usually used for + libraries. For example, to depend on the compatibility and + utility libraries use: + + DPADD+=${LIBCOMPAT} ${LIBUTIL} + + The following libraries are predefined for DPADD: + + LIBC /lib/libc.a + LIBCOMPAT /usr/lib/libcompat.a + LIBCRYPT /usr/lib/libcrypt.a + LIBCURSES /usr/lib/libcurses.a + LIBDBM /usr/lib/libdbm.a + LIBDES /usr/lib/libdes.a + LIBL /usr/lib/libl.a + LIBKDB /usr/lib/libkdb.a + LIBKRB /usr/lib/libkrb.a + LIBKVM /usr/lib/libkvm.a + LIBM /usr/lib/libm.a + LIBMP /usr/lib/libmp.a + LIBPC /usr/lib/libpc.a + LIBPLOT /usr/lib/libplot.a + LIBRPC /usr/lib/sunrpc.a + LIBTERM /usr/lib/libterm.a + LIBUTIL /usr/lib/libutil.a + +SHAREDSTRINGS If defined, a new .c.o rule is used that results in shared + strings, using xstr(1). Note that this will not work with + parallel makes. + +STRIP The flag passed to the install program to cause the binary + to be stripped. + +SUBDIR A list of subdirectories that should be built as well. + Each of the targets will execute the same target in the + subdirectories. + +The include file includes the file named "../Makefile.inc" +if it exists, as well as the include file . + +Some simple examples: + +To build foo from foo.c with a manual page foo.1, use: + + PROG= foo + + .include + +To build foo from foo.c with a manual page foo.2, add the line: + + MAN= foo.2 + +If foo does not have a manual page at all, add the line: + + NOMAN= noman + +If foo has multiple source files, add the line: + + SRCS= a.c b.c c.c d.c + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file contains the default targets for building +subdirectories. It has the same eight targets as : all, +clean, cleandir, depend, includes, install, lint, and tags. For all of +the directories listed in the variable SUBDIRS, the specified directory +will be visited and the target made. There is also a default target which +allows the command "make subdir" where subdir is any directory listed in +the variable SUBDIRS. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file is used by and +. It contains overrides that are used when building +the NetBSD source tree. For instance, if "PARALLEL" is defined by +the program/library Makefile, it includes a set of rules for lex and +yacc that allow multiple lex and yacc targets to be built in parallel. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +The include file has support for building libraries. It has +the same eight targets as : all, clean, cleandir, depend, +includes, install, lint, and tags. It has a limited number of suffixes, +consistent with the current needs of the BSD tree. + +It sets/uses the following variables: + +LIB The name of the library to build. + +LIBDIR Target directory for libraries. + +LINTLIBDIR Target directory for lint libraries. + +LIBGRP Library group. + +LIBOWN Library owner. + +LIBMODE Library mode. + +LDADD Additional loader objects. + +MAN The manual pages to be installed (use a .1 - .9 suffix). + +SRCS List of source files to build the library. Suffix types + .s, .c, and .f are supported. Note, .s files are preferred + to .c files of the same name. (This is not the default for + versions of make.) + +The include file includes the file named "../Makefile.inc" +if it exists, as well as the include file . + +It has rules for building profiled objects; profiled libraries are +built by default. + +Libraries are ranlib'd when made. Index: vendor/NetBSD/bmake/20201101/mk/auto.dep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/auto.dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/auto.dep.mk (revision 367461) @@ -0,0 +1,74 @@ +# +# RCSid: +# $Id: auto.dep.mk,v 1.6 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2010, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# This module provides automagic dependency generation along the +# lines suggested in the GNU make.info + +# set MKDEP_MK=auto.dep.mk and dep.mk will include us + +# This version differs from autodep.mk, in that +# we use ${.TARGET:T}.d rather than ${.TARGET:T:R}.d +# this makes it simpler to get the args to -MF and -MT right +# and ensure we can simply include all the .d files. +# +# However suffix rules do not work with something like .o.d so we +# don't even try to handle 'make depend' gracefully. +# dep.mk will handle that itself. +# +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# this what bmake > 20100401 will look for +.MAKE.DEPENDFILE ?= .depend + +# set this to -MMD to ignore /usr/include +# actually it ignores <> so may not be a great idea +CFLAGS_MD ?= -MD +# -MF etc not available on all gcc versions. +CFLAGS_MF ?= -MF ${.TARGET:T}.d -MT ${.TARGET:T} +CFLAGS += ${CFLAGS_MD} ${CFLAGS_MF} +CXXFLAGS += ${CFLAGS_MD} ${CFLAGS_MF} + +CLEANFILES += .depend ${.MAKE.DEPENDFILE} *.d + +.if ${MAKE_VERSION} < 20160218 +# skip generating dependfile for misc targets +.if ${.TARGETS:Uall:M*all} != "" +.END: ${.MAKE.DEPENDFILE} +.endif + +# doing 'make depend' isn't a big win with this model +.if !target(depend) +depend: ${.MAKE.DEPENDFILE} +.endif + +# this is trivial +${.MAKE.DEPENDFILE}: ${OBJS} ${POBJS} ${SOBJS} + -@for f in ${.ALLSRC:M*o:T:O:u:%=%.d}; do \ + echo ".-include \"$$f\""; \ + done > $@ +.else +# we have .dinclude +.if empty(_SKIP_BUILD) +_all_objs = ${OBJS} ${POBJS} ${SOBJS} +.for d in ${_all_objs:M*o:T:O:u:%=%.d} +.dinclude <$d> +.endfor +.endif + +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/auto.obj.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/auto.obj.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/auto.obj.mk (revision 367461) @@ -0,0 +1,76 @@ +# $Id: auto.obj.mk,v 1.16 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2004, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +ECHO_TRACE ?= echo + +.ifndef Mkdirs +# A race condition in some versions of mkdir, means that it can bail +# if another process made a dir that mkdir expected to. +# We repeat the mkdir -p a number of times to try and work around this. +# We stop looping as soon as the dir exists. +# If we get to the end of the loop, a plain mkdir will issue an error. +Mkdirs= Mkdirs() { \ + for d in $$*; do \ + for i in 1 2 3 4 5 6; do \ + mkdir -p $$d; \ + test -d $$d && return 0; \ + done > /dev/null 2>&1; \ + mkdir $$d || exit $$?; \ + done; } +.endif + +# if MKOBJDIRS is set to auto (and NOOBJ isn't defined) do some magic... +# This will automatically create objdirs as needed. +# Skip it if we are just doing 'clean'. +.if ${MK_AUTO_OBJ:Uno} == "yes" +MKOBJDIRS= auto +.endif +.if !defined(NOOBJ) && !defined(NO_OBJ) && ${MKOBJDIRS:Uno} == auto +# Use __objdir here so it is easier to tweak without impacting +# the logic. +.if !empty(MAKEOBJDIRPREFIX) +.if ${.CURDIR:M${MAKEOBJDIRPREFIX}/*} != "" +# we are already in obj tree! +__objdir?= ${.CURDIR} +.endif +__objdir?= ${MAKEOBJDIRPREFIX}${.CURDIR} +.endif +__objdir?= ${MAKEOBJDIR:Uobj} +__objdir:= ${__objdir} +.if ${.OBJDIR:tA} != ${__objdir:tA} +# We need to chdir, make the directory if needed +.if !exists(${__objdir}/) && \ + (${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "") +# This will actually make it... +__objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \ + ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \ + ${Mkdirs}; Mkdirs ${__objdir} +.endif +# This causes make to use the specified directory as .OBJDIR +.OBJDIR: ${__objdir} +.if ${.OBJDIR:tA} != ${__objdir:tA} +# we did not get what we want - do we care? +.if ${__objdir_made:Uno:M${__objdir}/*} != "" +# watch out for __objdir being relative path +.if !(${__objdir:M/*} == "" && ${.OBJDIR:tA} == ${${.CURDIR}/${__objdir}:L:tA}) +.error could not use ${__objdir}: .OBJDIR=${.OBJDIR} +.endif +.endif +# apparently we can live with it +# make sure we know what we have +.OBJDIR: ${.CURDIR} +.endif +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/autoconf.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/autoconf.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/autoconf.mk (revision 367461) @@ -0,0 +1,80 @@ +# $Id: autoconf.mk,v 1.10 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 1996-2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.NOPATH: config.h config.status + +CONFIGURE_DEPS += ${.CURDIR}/config.h.in ${.CURDIR}/configure + +.if !target(config.h) +config.h: ${CONFIGURE_DEPS} config.status + ./config.status +.endif + +.if !target(config.status) +# avoid the targets behaving differently +.if exists(${.OBJDIR}/config.status) +config.status: config.recheck +.else +config.status: config.gen +.endif + +config.recheck: ${CONFIGURE_DEPS} + ./config.status --recheck + @touch $@ + +config.gen: ${CONFIGURE_DEPS} + CC="${CC} ${CCMODE}" ${.CURDIR}/configure --no-create ${CONFIGURE_ARGS} + @touch $@ config.recheck + +CLEANFILES+= config.recheck config.gen config.status *.meta +.endif + +# avoid things blowing up if these are not here... +# this is not quite per the autoconf manual, +# and is extremely convoluted - but all utterly necessary! + +.if make(autoconf-in) || make(configure) || make(config.h.in) || ${AUTO_AUTOCONF:Uno:tl} == "yes" +AUTOCONF ?= autoconf +AUTOHEADER ?= autoheader + +# expand it to a full path +AUTOCONF := ${AUTOCONF:${M_whence}} + +.if exists(${AUTOCONF}) + +.PRECIOUS: configure config.h.in config.status + +ACLOCAL = +ACCONFIG = + +.if exists(${.CURDIR}/aclocal.m4) +ACLOCAL += aclocal.m4 +.endif +# use of acconfig.h is deprecated! +.if exists(${.CURDIR}/acconfig.h) +ACCONFIG += acconfig.h +.endif + +config.h.in: ${.CURDIR}/configure.in ${ACCONFIG} + (cd ${.CURDIR} && ${AUTOHEADER}) + +configure: ${.CURDIR}/configure.in ${ACLOCAL} + (cd ${.CURDIR} && ${AUTOCONF}) + +AUTOCONF_INPUTS += configure +autoconf-input: ${AUTOCONF_INPUTS} + +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/autodep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/autodep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/autodep.mk (revision 367461) @@ -0,0 +1,219 @@ +# +# RCSid: +# $Id: autodep.mk,v 1.38 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 1999-2010, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net + +# This module provides automagic dependency generation along the +# lines suggested in the GNU make.info +# The depend target is mainly for backwards compatibility, +# dependencies are normally updated as part of compilation. + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +DEPENDFILE?= .depend +.for d in ${DEPENDFILE:N.depend} +# bmake only groks .depend +.if ${MAKE_VERSION} < 20160218 +.-include <$d> +.else +.dinclude <$d> +.endif +.endfor + +# it does nothing if SRCS is not defined or is empty +.if defined(SRCS) && !empty(SRCS) +DEPSRCS?=${SRCS} +__depsrcs=${DEPSRCS:M*.c} +__depsrcs+=${DEPSRCS:M*.y} +__depsrcs+=${DEPSRCS:M*.l} +__depsrcs+=${DEPSRCS:M*.s} +__depsrcs+=${DEPSRCS:M*.S} +__depsrcs+=${DEPSRCS:M*.cc} +__depsrcs+=${DEPSRCS:M*.cpp} +__depsrcs+=${DEPSRCS:M*.C} +__depsrcs+=${DEPSRCS:M*.cxx} +__depsrcs+=${DEPSRCS:M*.pc} + +.for s in ${__depsrcs} +${s:T:R}.d: $s +.endfor + +__depsrcs:=${__depsrcs:T:R:S/$/.d/g} +# we also need to handle makefiles where the .d's from __depsrcs +# don't match those from OBJS +# we avoid using := here, since the modifier applied to OBJS +# can cause trouble if there are any undefined vars in OBJS. +__dependsrcsx?= ${__depsrcs} ${OBJS:S/.o/.d/} +__dependsrcs= ${__dependsrcsx:O:u} + +# clean up any .c files we may have generated +#__gensrcs:= ${DEPSRCS:M*.y} ${DEPSRCS:M*.l} +#CLEANFILES+= ${__gensrcs:T:R:S/$/.c/g} + +# set this to -MMD to ignore /usr/include +# actually it ignores <> so may not be a great idea +CFLAGS_MD?=-MD +# -MF etc not available on all gcc versions. +# we "fix" the .o later +CFLAGS_MF?=-MF ${.TARGET:T:R}.d -MT ${.TARGET:T:R}.o +CFLAGS+= ${CFLAGS_MD} ${CFLAGS_MF} +RM?= rm +MAKE_SHELL?= sh + +# watch out for people who don't use CPPFLAGS +CPPFLAGS_MD=${CFLAGS:M-[IUD]*} ${CPPFLAGS} +CXXFLAGS_MD=${CXXFLAGS:M-[IUD]*} ${CPPFLAGS} + +# just in case these need to be different +CC_MD?=${CC} +CXX_MD?=${CXX} + +# should have been set by sys.mk +CXX_SUFFIXES?= .cc .cpp .cxx .C + +# so we can do an explicit make depend, but not otherwise +.if make(depend) +.SUFFIXES: .d + +.if empty(CFLAGS_MD) +.y.d: + @echo updating dependencies for $< + @${YACC} ${YFLAGS} $< + @${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} y.tab.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f y.tab.c $@; false; } + @${RM} -f y.tab.c + +.l.d: + @echo updating dependencies for $< + ${LEX} ${LFLAGS} $< + @${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} lex.yy.c | sed '/:/s/^/$@ /' > $@" || { ${RM} -f lex.yy.c $@; false; } + @${RM} -f lex.yy.c + +.c.d: + @echo updating dependencies for $< + @${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; } + +.s.d .S.d: + @echo updating dependencies for $< + @${MAKE_SHELL} -ec "${CC_MD} -M ${CPPFLAGS_MD} ${AINC} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; } + +${CXX_SUFFIXES:%=%.d}: + @echo updating dependencies for $< + @${MAKE_SHELL} -ec "${CXX_MD} -M ${CXXFLAGS_MD} $< | sed '/:/s/^/$@ /' > $@" || { ${RM} -f $@; false; } +.else +.y.d: + ${YACC} ${YFLAGS} $< + ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} y.tab.c > $@ || { ${RM} -f y.tab.c $@; false; } + ${RM} -f y.tab.c + +.l.d: + ${LEX} ${LFLAGS} $< + ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} lex.yy.c > $@ || { ${RM} -f lex.yy.c $@; false; } + ${RM} -f lex.yy.c + +.c.d: + ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} $< > $@ || { ${RM} -f $@; false; } + +.s.d .S.d: + ${CC_MD} ${CFLAGS_MD:S/D//} ${CPPFLAGS_MD} ${AINC} $< > $@ || { ${RM} -f $@; false; } + +${CXX_SUFFIXES:%=%.d}: + ${CXX_MD} ${CFLAGS_MD:S/D//} ${CXXFLAGS_MD} $< > $@ || { ${RM} -f $@; false; } +.endif + +.if !target(depend) +depend: beforedepend ${DEPENDFILE} afterdepend _SUBDIRUSE + +${DEPENDFILE}: ${DEPSRCS} ${__dependsrcs} +.NOPATH: ${__dependsrcs} +.OPTIONAL: ${__dependsrcs} +.endif +.endif # make(depend) + +.if empty(CFLAGS_MD) +# make sure the .d's are generated/updated +${PROG} ${_LIBS}: ${DEPENDFILE} +.endif + +.ORDER: beforedepend ${DEPENDFILE} afterdepend + +.if ${.OBJDIR} != ${.CURDIR} +__depfiles= *.d +.else +__depfiles= ${__dependsrcs} +.endif + +DEPCLEANFILES= ${DEPENDFILE} ${__depfiles} y.tab.d *.tmp.d + +cleandir: cleanautodepend +cleanautodepend: + ${RM} -f ${DEPCLEANFILES} + +CLEANFILES+= ${DEPCLEANFILES} + +.if defined(__dependsrcs) && !empty(__dependsrcs) +.if make(depend) || !(make(clean*) || make(destroy*) || make(obj) || make(*install) || make(install-*)) +# this ensures we do the right thing if only building a shared or +# profiled lib +OBJ_EXTENSIONS?=.o .po .so .So +MDLIB_SED= -e '/:/s,^\([^\.:]*\)\.[psS]*o,${OBJ_EXTENSIONS:S,^,\1,},' +.ifdef NOMD_SED +.ifdef LIB +MD_SED=sed ${MDLIB_SED} +.else +MD_SED=cat +.endif +.else +# arrange to put some variable names into ${DEPENDFILE} +.ifdef LIB +MD_SED=sed ${MDLIB_SED} +.else +MD_SED=sed +.endif +SUBST_DEPVARS+= SB TOP BACKING SRC SRCDIR BASE BASEDIR +.for v in ${SUBST_DEPVARS} +.if defined(${v}) && !empty(${v}) +MD_SED+= -e 's,${$v},$${$v},' +.endif +.endfor +.endif +.if (${MD_SED} == "sed") +MD_SED=cat +.endif + +# this will be done whenever make finishes successfully +.if ${MAKE_VERSION:U0:[1]:C/.*-//} < 20050530 +.END: +.else +.END: ${DEPENDFILE} +# we do not want to trigger building .d's just use them if they exist +${DEPENDFILE}: ${__dependsrcs:@d@${exists($d):?$d:}@} +.endif + -@${MD_SED} ${__depfiles} > ${DEPENDFILE}.new 2> /dev/null && \ + test -s ${DEPENDFILE}.new && mv ${DEPENDFILE}.new ${DEPENDFILE}; \ + ${RM} -f ${DEPENDFILE}.new +.endif +.endif +.else +depend: beforedepend afterdepend _SUBDIRUSE +.endif + +.if !target(beforedepend) +beforedepend: +.endif +.if !target(afterdepend) +afterdepend: +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/compiler.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/compiler.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/compiler.mk (revision 367461) @@ -0,0 +1,43 @@ +# $Id: compiler.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2019, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.if ${MACHINE} == "common" +COMPILER_TYPE = none +COMPILER_VERSION = 0 +.endif +.if empty(COMPILER_TYPE) || empty(COMPILER_VERSION) +# gcc does not always say gcc +_v != ${CC} --version 2> /dev/null | \ + egrep -i 'clang|cc|[1-9]\.[0-9]|Free Software Foundation' +.if empty(COMPILER_TYPE) +.if ${_v:Mclang} != "" +COMPILER_TYPE = clang +.elif ${_v:M[Gg][Cc][Cc]} != "" || ${_v:MFoundation*} != "" +COMPILER_TYPE = gcc +.endif +.endif +.if empty(COMPILER_VERSION) +COMPILER_VERSION != echo "${_v:M[1-9].[0-9]*}:[1]" | \ + awk -F. '{print $$1 * 10000 + $$2 * 100 + $$3;}' +.endif +.undef _v +.endif +# just in case we don't recognize compiler +COMPILER_TYPE ?= unknown +COMPILER_VERSION ?= 0 +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/compiler.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/cython.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/cython.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/cython.mk (revision 367461) @@ -0,0 +1,101 @@ +# RCSid: +# $Id: cython.mk,v 1.8 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# pyprefix is where python bits are +# which may not be where we want to put ours (prefix) +.if exists(/usr/pkg/include) +pyprefix?= /usr/pkg +.endif +pyprefix?= /usr/local + +PYTHON_VERSION?= 2.7 +PYTHON_H?= ${pyprefix}/include/python${PYTHON_VERSION}/Python.h +PYVERSION:= ${PYTHON_VERSION:C,\..*,,} + +CFLAGS+= -I${PYTHON_H:H} + +# conf.host_target() is limited to uname -m rather than uname -p +_HOST_MACHINE!= uname -m +.if ${HOST_TARGET:M*${_HOST_MACHINE}} == "" +PY_HOST_TARGET:= ${HOST_TARGET:S,${_HOST_ARCH:U${uname -p:L:sh}}$,${_HOST_MACHINE},} +.endif + +COMPILE.c?= ${CC} -c ${CFLAGS} +PICO?= .pico + +.SUFFIXES: ${PICO} .c + +.c${PICO}: + ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET} + +# this is what we build +.if !empty(CYTHON_MODULE_NAME) +CYTHON_MODULE = ${CYTHON_MODULE_NAME}${CYTHON_PYVERSION}.so + +CYTHON_SRCS?= ${CYTHON_MODULE_NAME}.pyx + +# this is where we save generated src +CYTHON_SAVEGENDIR?= ${.CURDIR}/gen + +# set this empty if you don't want to handle multiple versions +.if !defined(CYTHON_PYVERSION) +CYTHON_PYVERSION:= ${PYVERSION} +.endif + +CYTHON_GENSRCS= ${CYTHON_SRCS:R:S,$,${CYTHON_PYVERSION}.c,} +SRCS+= ${CYTHON_GENSRCS} + +.SUFFIXES: .pyx .c .So + +CYTHON?= ${pyprefix}/bin/cython + +# if we don't have cython we can use pre-generated srcs +.if ${type ${CYTHON} 2> /dev/null || echo:L:sh:M/*} == "" +.PATH: ${CYTHON_SAVEGENDIR} +.else + +.if !empty(CYTHON_PYVERSION) +.for c in ${CYTHON_SRCS} +${c:R}${CYTHON_PYVERSION}.${c:E}: $c + ln -sf ${.ALLSRC:M*pyx} ${.TARGET} +.endfor +.endif + +.pyx.c: + ${CYTHON} ${CYTHON_FLAGS} -${PYVERSION} -o ${.TARGET} ${.IMPSRC} + + +save-gen: ${CYTHON_GENSRCS} + mkdir -p ${CYTHON_SAVEGENDIR} + cp -p ${.ALLSRC} ${CYTHON_SAVEGENDIR} + +.endif + +${CYTHON_MODULE}: ${SRCS:S,.c,${PICO},} + ${CC} ${CC_SHARED:U-shared} -o ${.TARGET} ${.ALLSRC:M*${PICO}} ${LDADD} + +MODULE_BINDIR?= ${.CURDIR:H}/${PY_HOST_TARGET:U${HOST_TARGET}} + +build-cython-module: ${CYTHON_MODULE} + +install-cython-module: ${CYTHON_MODULE} + test -d ${DESTDIR}${MODULE_BINDIR} || \ + ${INSTALL} -d ${DESTDIR}${MODULE_BINDIR} + ${INSTALL} -m 755 ${.ALLSRC} ${DESTDIR}${MODULE_BINDIR} + +CLEANFILES+= *${PICO} ${CYTHON_MODULE} + +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/cython.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/dirdeps-options.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dirdeps-options.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dirdeps-options.mk (revision 367461) @@ -0,0 +1,100 @@ +# $Id: dirdeps-options.mk,v 1.17 2020/08/07 01:57:38 sjg Exp $ +# +# @(#) Copyright (c) 2018-2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +## +# +# This makefile is used to deal with optional DIRDEPS. +# +# It is to be included by Makefile.depend.options in a +# directory which has DIRDEPS affected by optional features. +# Makefile.depend.options should set DIRDEPS_OPTIONS and +# may also set specific DIRDEPS.* for those options. +# +# If a Makefile.depend.options file exists, it will be included by +# dirdeps.mk and meta.autodep.mk +# +# We include local.dirdeps-options.mk which may also define DIRDEPS.* +# for options. +# +# Thus a directory, that is affected by an option FOO would have +# a Makefile.depend.options that sets +# DIRDEPS_OPTIONS= FOO +# It can also set either/both of +# DIRDEPS.FOO.yes +# DIRDEPS.FOO.no +# to whatever applies for that dir, or it can rely on globals +# set in local.dirdeps-options.mk +# Either way, we will .undef DIRDEPS.* when done. +# +# In some cases the value of MK_FOO might depend on TARGET_SPEC +# so we qualify MK_FOO with .${TARGET_SPEC} and each component +# TARGET_SPEC_VAR (in reverse order) before using MK_FOO. +# + +# This should have been set by Makefile.depend.options +# before including us +DIRDEPS_OPTIONS ?= + +# pickup any DIRDEPS.* we need +.-include + +.if ${.MAKE.LEVEL} == 0 +# :U below avoids potential errors when we := +# some options can depend on TARGET_SPEC! +DIRDEPS_OPTIONS_QUALIFIER_LIST ?= \ + ${DEP_TARGET_SPEC:U${TARGET_SPEC}} \ + ${TARGET_SPEC_VARSr:U${TARGET_SPEC_VARS}:@v@${DEP_$v:U${$v}}@} +# note that we need to include $o in the variable _o$o +# to ensure correct evaluation. +.for o in ${DIRDEPS_OPTIONS} +.undef _o$o _v$o +.for x in ${DIRDEPS_OPTIONS_QUALIFIER_LIST} +.if defined(MK_$o.$x) +_o$o ?= MK_$o.$x +_v$o ?= ${MK_$o.$x} +.endif +.endfor +_v$o ?= ${MK_$o} +.if ${_debug_reldir:U0} +.info ${DEP_RELDIR:U${RELDIR}}.${DEP_TARGET_SPEC:U${TARGET_SPEC}}: o=$o ${_o$o:UMK_$o}=${_v$o:U} DIRDEPS += ${DIRDEPS.$o.${_v$o:U}:U} +.endif +DIRDEPS += ${DIRDEPS.$o.${_v$o:U}:U} +.endfor +DIRDEPS := ${DIRDEPS:O:u} +.if ${_debug_reldir:U0} +.info ${DEP_RELDIR:U${RELDIR}}: DIRDEPS=${DIRDEPS} +.endif +# avoid cross contamination +.for o in ${DIRDEPS_OPTIONS} +.undef DIRDEPS.$o.yes +.undef DIRDEPS.$o.no +.undef _o$o +.undef _v$o +.endfor +.else +# whether options are enabled or not, +# we want to filter out the relevant DIRDEPS.* +# we should only be included by meta.autodep.mk +# if dependencies are to be updated +.for o in ${DIRDEPS_OPTIONS} +.for d in ${DIRDEPS.$o.yes} ${DIRDEPS.$o.no} +.if exists(${SRCTOP}/$d) +GENDIRDEPS_FILTER += N$d* +.elif exists(${SRCTOP}/${d:R}) +GENDIRDEPS_FILTER += N${d:R}* +.endif +.endfor +.endfor +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/dirdeps-options.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/dirdeps-targets.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dirdeps-targets.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dirdeps-targets.mk (revision 367461) @@ -0,0 +1,171 @@ +# RCSid: +# $Id: dirdeps-targets.mk,v 1.22 2020/08/15 18:00:11 sjg Exp $ +# +# @(#) Copyright (c) 2019-2020 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +## +# This makefile is used to set initial DIRDEPS for top-level build +# targets. +# +# The basic idea is that we have a list of directories in +# DIRDEPS_TARGETS_DIRS which are relative to SRCTOP. +# When asked to make 'foo' we look for any directory named 'foo' +# under DIRDEPS_TARGETS_DIRS. +# We then search those dirs for any Makefile.depend* +# Finally we select any that match conditions like REQUESTED_MACHINE +# or TARGET_SPEC and initialize DIRDEPS accordingly. +# +# We will check each of the initial DIRDEPS for Makefile.dirdeps.options +# and include any found. +# This makes it feasible to tweak options like MK_DIRDEPS_CACHE +# for a specific target. +# +# If MK_STATIC_DIRDEPS_CACHE is defined we will check if the +# initial DIRDEPS has a static cache (Makefile.dirdeps.cache). +# This only makes sense for seriously expensive targets. +# + +.if ${.MAKE.LEVEL} == 0 +# pickup customizations +.-include + +# for DIRDEPS_BUILD this is how we prime the pump +DIRDEPS_TARGETS_DIRS ?= targets targets/pseudo +# these prefixes can modify how we behave +# they need to be stripped when looking for target dirs +DIRDEPS_TARGETS_PREFIX_LIST ?= pkg- build- + +# some .TARGETS need filtering +DIRDEPS_TARGETS_FILTER += Nall + +# matching target dirs if any +tdirs := ${.TARGETS:${DIRDEPS_TARGETS_FILTER:ts:}:${DIRDEPS_TARGETS_PREFIX_LIST:@p@S,^$p,,@:ts:}:@t@${DIRDEPS_TARGETS_DIRS:@d@$d/$t@}@:@d@${exists(${SRCTOP}/$d):?$d:}@} + +.if !empty(DEBUG_DIRDEPS_TARGETS) +.info tdirs=${tdirs} +.endif + +.if !empty(tdirs) +# some things we know we want to ignore +DIRDEPS_TARGETS_SKIP_LIST += \ + *~ \ + *.bak \ + *.inc \ + *.old \ + *.options \ + *.orig \ + *.rej \ + +# the list of MACHINEs we consider +DIRDEPS_TARGETS_MACHINE_LIST += \ + ${ALL_MACHINE_LIST:U} \ + ${PSEUDO_MACHINE_LIST:Ucommon host host32} \ + ${TARGET_MACHINE_LIST} + +DIRDEPS_TARGETS_MACHINE_LIST := ${DIRDEPS_TARGETS_MACHINE_LIST:O:u} + +# raw Makefile.depend* list +tdeps != 'cd' ${SRCTOP} && 'ls' -1 ${tdirs:O:u:@d@$d/${.MAKE.DEPENDFILE_PREFIX}*@} 2> /dev/null; echo +.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != "" +.info tdeps=${tdeps} +.endif +# remove things we know we don't want +tdeps := ${tdeps:${DIRDEPS_TARGETS_SKIP_LIST:${M_ListToSkip}}} +.if ${DEBUG_DIRDEPS_TARGETS:U:Mdep*} != "" +.info tdeps=${tdeps} +.endif + +# plain entries (no qualifiers) these apply to any TARGET_SPEC +ptdeps := ${tdeps:M*${.MAKE.DEPENDFILE_PREFIX}:S,/${.MAKE.DEPENDFILE_PREFIX},,} + +# MACHINE qualified entries +mqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m}@:S,/${.MAKE.DEPENDFILE_PREFIX},,} + +tqtdeps = +.if ${TARGET_SPEC_VARS:[#]} > 1 +# TARGET_SPEC qualified entries +.if !empty(TARGET_SPEC_LIST) +# we have a list of valid TARGET_SPECS; use it +tqtdeps := ${TARGET_SPEC_LIST:U:O:u:@t@${tdeps:M*.$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,} +.else +# do we have a list of valid tuple members for at least +# the last tupple element? if so match on that +TARGET_SPEC_LAST_LIST ?= ${${TARGET_SPEC_VARS:[-1]}_LIST} +.if !empty(TARGET_SPEC_LAST_LIST) +tqtdeps := ${TARGET_SPEC_LAST_LIST:U:O:u:@t@${tdeps:M*,$t}@:S,/${.MAKE.DEPENDFILE_PREFIX},,} +.else +# this is sub-optimal match MACHINE, +tqtdeps := ${DIRDEPS_TARGETS_MACHINE_LIST:@m@${tdeps:M*.$m,*}@:S,/${.MAKE.DEPENDFILE_PREFIX},,} +.endif +.endif +.endif + +# now work out what we want in DIRDEPS +.if empty(REQUESTED_MACHINE) +# we want them all just as found +DIRDEPS = ${ptdeps} ${mqtdeps} ${tqtdeps} +.else +# we only want those that match REQUESTED_MACHINE/REQUESTED_TARGET_SPEC +# or REQUESTED_TARGET_SPEC (TARGET_SPEC) +DIRDEPS = \ + ${ptdeps:@d@$d.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC:U${REQUESTED_MACHINE}}}@} \ + ${mqtdeps:M*.${REQUESTED_MACHINE}} \ + ${tqtdeps:M*.${REQUESTED_TARGET_SPEC:U${TARGET_SPEC}}} +.endif +# clean up +DIRDEPS := ${DIRDEPS:O:u} + +.if !empty(DEBUG_DIRDEPS_TARGETS) +.for x in tdeps ptdeps mqtdeps tqtdeps DIRDEPS +.info $x=${$x} +.endfor +.endif +.endif +# if we got DIRDEPS get to work +.if !empty(DIRDEPS) +DIRDEPS.dirs := ${DIRDEPS:S,^,${SRCTOP}/,:@d@${exists($d):?$d:${d:R}}@} +# some targets what to tweak options we might want to process now +.for m in ${DIRDEPS.dirs:S,$,/Makefile.dirdeps.options,} +.-include <$m> +.endfor +.if defined(MK_STATIC_DIRDEPS_CACHE) +# some targets are very expensive to compute dirdeps for +# so we may have a static cache +.for c in ${DIRDEPS.dirs:S,$,/Makefile.dirdeps.cache,} +.if exists($c) +STATIC_DIRDEPS_CACHE ?= $c +.if ${MK_STATIC_DIRDEPS_CACHE} == "yes" +DIRDEPS_CACHE ?= $c +MK_DIRDEPS_CACHE = yes +.endif +.endif +.endfor +.if defined(STATIC_DIRDEPS_CACHE) +.export STATIC_DIRDEPS_CACHE +.endif +.endif + +# allow a top-level makefile to do other stuff +# before including dirdeps.mk +.if ${MK_DIRDEPS_TARGETS_INCLUDE_DIRDEPS:Uyes} == "yes" +.include +.endif + +DIRDEPS_TARGETS_SKIP += all clean* destroy* + +.for t in ${.TARGETS:${DIRDEPS_TARGETS_SKIP:${M_ListToSkip}}} +$t: dirdeps +.endfor +.endif +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/dirdeps-targets.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/dpadd.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dpadd.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dpadd.mk (revision 367461) @@ -0,0 +1,339 @@ +# $Id: dpadd.mk,v 1.28 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2004, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +## +# DESCRIPTION: +# This makefile manages a number of variables that simplify +# dealing with libs in a build. +# +# Primary inputs are DPLIBS, DPADD and SRC_LIBS: +# +# DPLIBS +# List of LIB* that we will actually link with +# should be in correct link order. +# DPLIBS is a short-cut to ensure that DPADD and LDADD are +# kept in sync. +# +# DPADD List of LIB* that should already be built. +# +# SRC_LIBS +# List of LIB* that we want headers from, we do *not* +# require that such libs have been built. +# +# The above all get added to DPMAGIC_LIBS which is what we +# process. +# +# We expect LIB* to be set to absolute path of a library - +# suitable for putting in DPADD. +# eg. +# +# LIBC ?= ${OBJTOP}/lib/libc/libc.a +# +# From such a path we can derrive a number of other variables +# for which we can supply sensible default values. +# We name all these variables for the basename of the library +# (libc in our example above -- ${__lib:T:R} in below): +# +# LDADD_${__lib:T:R}: +# What should be added to LDADD (eg -lc) +# +# OBJ_${__lib:T:R}: +# This is trivial - just the dirname of the built library. +# +# SRC_${__lib:T:R}: +# Where the src for ${__lib} is, if LIB* is set as above +# we can simply substitute ${SRCTOP} for ${OBJTOP} in +# the dirname. +# +# INCLUDES_${__lib:T:R}: +# What should be added to CFLAGS +# +# If the directory ${SRC_${__lib:T:R}}/h exists we will +# only add -I${SRC_${__lib:T:R}}/h on the basis that +# this is where the public api is kept. +# +# Otherwise default will be -I${OBJ_${__lib:T:R}} +# -I${SRC_${__lib:T:R}} +# +# Note much of the above is skipped for staged libs +# eg. +# LIBC ?= ${STAGE_OBJTOP}/usr/lib/libc.a +# +# Since we can safely assume that -I${STAGE_OBJTOP}/usr/include +# and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should +# have no need of anything else. +# + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# sometimes we play games with .CURDIR etc +# _* hold the original values of .* +_OBJDIR?= ${.OBJDIR} +_CURDIR?= ${.CURDIR} + +.if ${_CURDIR} == ${SRCTOP} +RELDIR=. +RELTOP=. +.else +RELDIR?= ${_CURDIR:S,${SRCTOP}/,,} +.if ${RELDIR} == ${_CURDIR} +RELDIR?= ${_OBJDIR:S,${OBJTOP}/,,} +.endif +RELTOP?= ${RELDIR:C,[^/]+,..,g} +.endif +RELOBJTOP?= ${OBJTOP} +RELSRCTOP?= ${SRCTOP} + +# we get included just about everywhere so this is handy... +# C*DEBUG_XTRA are for defining on cmd line etc +# so do not use in makefiles. +.ifdef CFLAGS_DEBUG_XTRA +CFLAGS_LAST += ${CFLAGS_DEBUG_XTRA} +.endif +.ifdef CXXFLAGS_DEBUG_XTRA +CXXFLAGS_LAST += ${CXXFLAGS_DEBUG_XTRA} +.endif + +.-include + +# DPLIBS helps us ensure we keep DPADD and LDADD in sync +DPLIBS+= ${DPLIBS_LAST} +DPADD+= ${DPLIBS:N-*} +.for __lib in ${DPLIBS} +.if "${__lib:M-*}" != "" +LDADD += ${__lib} +.else +LDADD += ${LDADD_${__lib:T:R}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}} +.endif +.endfor + +# DPADD can contain things other than libs +__dpadd_libs := ${DPADD:M*/lib*} + +.if defined(PROG) && ${MK_PROG_LDORDER_MK:Uno} != "no" +# some libs have dependencies... +# DPLIBS_* allows bsd.libnames.mk to flag libs which must be included +# in DPADD for a given library. +# Gather all such dependencies into __ldadd_all_xtras +# dups will be dealt with later. +# Note: libfoo_pic uses DPLIBS_libfoo +__ldadd_all_xtras= +.for __lib in ${__dpadd_libs:@d@${DPLIBS_${d:T:R:S,_pic,,}}@} +__ldadd_all_xtras+= ${LDADD_${__lib}:U${__lib:T:R:S/lib/-l/:C/\.so.*//}} +.if "${DPADD:M${__lib}}" == "" +DPADD+= ${__lib} +.endif +.endfor +.endif +# Last of all... for libc and libgcc +DPADD+= ${DPADD_LAST} + +# de-dupuplicate __ldadd_all_xtras into __ldadd_xtras +# in reverse order so that libs end up listed after all that needed them. +__ldadd_xtras= +.for __lib in ${__ldadd_all_xtras:[-1..1]} +.if "${__ldadd_xtras:M${__lib}}" == "" || ${NEED_IMPLICIT_LDADD:tl:Uno} != "no" +__ldadd_xtras+= ${__lib} +.endif +.endfor + +.if !empty(__ldadd_xtras) +# now back to the original order +__ldadd_xtras:= ${__ldadd_xtras:[-1..1]} +LDADD+= ${__ldadd_xtras} +.endif + +# Convert DPADD into -I and -L options and add them to CPPFLAGS and LDADD +# For the -I's convert the path to a relative one. For separate objdirs +# the DPADD paths will be to the obj tree so we need to subst anyway. + +# update this +__dpadd_libs := ${DPADD:M*/lib*} + +# Order -L's to search ours first. +# Avoids picking up old versions already installed. +__dpadd_libdirs := ${__dpadd_libs:R:H:S/^/-L/g:O:u:N-L} +LDADD += ${__dpadd_libdirs:M-L${OBJTOP}/*} +LDADD += ${__dpadd_libdirs:N-L${OBJTOP}/*:N-L${HOST_LIBDIR:U/usr/lib}} +.if defined(HOST_LIBDIR) && ${HOST_LIBDIR} != "/usr/lib" +LDADD+= -L${HOST_LIBDIR} +.endif + +.if !make(dpadd) +.ifdef LIB +# Each lib is its own src_lib, we want to include it in SRC_LIBS +# so that the correct INCLUDES_* will be picked up automatically. +SRC_LIBS+= ${_OBJDIR}/lib${LIB}.a +.endif +.endif + +# +# This little bit of magic, assumes that SRC_libfoo will be +# set if it cannot be correctly derrived from ${LIBFOO} +# Note that SRC_libfoo and INCLUDES_libfoo should be named for the +# actual library name not the variable name that might refer to it. +# 99% of the time the two are the same, but the DPADD logic +# only has the library name available, so stick to that. +# + +SRC_LIBS?= +# magic_libs includes those we want to link with +# as well as those we might look at +__dpadd_magic_libs += ${__dpadd_libs} ${SRC_LIBS} +DPMAGIC_LIBS += ${__dpadd_magic_libs} \ + ${__dpadd_magic_libs:@d@${DPMAGIC_LIBS_${d:T:R}}@} + +# we skip this for staged libs +.for __lib in ${DPMAGIC_LIBS:O:u:N${STAGE_OBJTOP:Unot}*/lib/*} +# +# if SRC_libfoo is not set, then we assume that the srcdir corresponding +# to where we found the library is correct. +# +SRC_${__lib:T:R} ?= ${__lib:H:S,${OBJTOP},${RELSRCTOP},} +# +# This is a no-brainer but just to be complete... +# +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}}} + +.endfor + +# even for staged libs we sometimes +# need to allow direct -I to avoid cicular dependencies +.for __lib in ${DPMAGIC_LIBS:O:u:T:R} +.if !empty(SRC_${__lib}) && empty(INCLUDES_${__lib}) +# must be a staged lib +.if exists(${SRC_${__lib}}/h) +INCLUDES_${__lib} = -I${SRC_${__lib}}/h +.else +INCLUDES_${__lib} = -I${SRC_${__lib}} +.endif +.endif +.endfor + +# when linking a shared lib, avoid non pic libs +SHLDADD+= ${LDADD:N-[lL]*} +.for __lib in ${__dpadd_libs:u} +.if defined(SHLIB_NAME) && ${LDADD:M-l${__lib:T:R:S,lib,,}} != "" +.if ${__lib:T:N*_pic.a:N*.so} == "" || exists(${__lib:R}.so) +SHLDADD+= -l${__lib:T:R:S,lib,,} +.elif exists(${__lib:R}_pic.a) +SHLDADD+= -l${__lib:T:R:S,lib,,}_pic +.else +.warning ${RELDIR}.${TARGET_SPEC} needs ${__lib:T:R}_pic.a +SHLDADD+= -l${__lib:T:R:S,lib,,} +.endif +SHLDADD+= -L${__lib:H} +.endif +.endfor + +# Now for the bits we actually need +__dpadd_incs= +.for __lib in ${__dpadd_libs:u} +.if (make(${PROG}_p) || defined(NEED_GPROF)) && exists(${__lib:R}_p.a) +__ldadd=-l${__lib:T:R:S,lib,,} +LDADD := ${LDADD:S,^${__ldadd}$,${__ldadd}_p,g} +.endif +.endfor + +# +# We take care of duplicate suppression later. +# don't apply :T:R too early +__dpadd_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_${x:T:R}}@} +__dpadd_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_${x:T:R}}@} + +__dpadd_last_incs += ${__dpadd_magic_libs:u:@x@${INCLUDES_LAST_${x:T:R}}@} +__dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${INCLUDES_LAST_${x:T:R}}@} + +.if defined(HOSTPROG) || ${MACHINE:Nhost*} == "" +# we want any -I/usr/* last +__dpadd_last_incs := \ + ${__dpadd_last_incs:N-I/usr/*} \ + ${__dpadd_incs:M-I/usr/*} \ + ${__dpadd_last_incs:M-I/usr/*} +__dpadd_incs := ${__dpadd_incs:N-I/usr/*} +.endif + +# +# eliminate any duplicates - but don't mess with the order +# force evaluation now - to avoid giving make a headache +# +.for t in CFLAGS CXXFLAGS +# avoid duplicates +__$t_incs:=${$t:M-I*:O:u} +.for i in ${__dpadd_incs} +.if "${__$t_incs:M$i}" == "" +$t+= $i +__$t_incs+= $i +.endif +.endfor +.endfor + +.for t in CFLAGS_LAST CXXFLAGS_LAST +# avoid duplicates +__$t_incs:=${$t:M-I*:u} +.for i in ${__dpadd_last_incs} +.if "${__$t_incs:M$i}" == "" +$t+= $i +__$t_incs+= $i +.endif +.endfor +.endfor + +# This target is used to gather a list of +# dir: ${DPADD} +# entries +.if make(*dpadd*) +.if !target(dpadd) +dpadd: .NOTMAIN +.if defined(DPADD) && ${DPADD} != "" + @echo "${RELDIR}: ${DPADD:S,${OBJTOP}/,,}" +.endif +.endif +.endif + +.ifdef SRC_PATHADD +# We don't want to assume that we need to .PATH every element of +# SRC_LIBS, but the Makefile cannot do +# .PATH: ${SRC_libfoo} +# since the value of SRC_libfoo must be available at the time .PATH: +# is read - and we only just worked it out. +# Further, they can't wait until after include of {lib,prog}.mk as +# the .PATH is needed before then. +# So we let the Makefile do +# SRC_PATHADD+= ${SRC_libfoo} +# and we defer the .PATH: until now so that SRC_libfoo will be available. +.PATH: ${SRC_PATHADD} +.endif + +# after all that, if doing -n we don't care +.if ${.MAKEFLAGS:Ux:M-n} != "" +DPADD = +.elif ${.MAKE.MODE:Mmeta*} != "" && exists(${.MAKE.DEPENDFILE}) +DPADD_CLEAR_DPADD ?= yes +.if ${DPADD_CLEAR_DPADD} == "yes" +# save this +__dpadd_libs := ${__dpadd_libs} +# we have made what use of it we can of DPADD +DPADD = +.endif +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/files.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/files.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/files.mk (revision 367461) @@ -0,0 +1,83 @@ +# $Id: files.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2017, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.include + +FILES_INSTALL_OWN ?= -o ${SHAREOWN} -g ${SHAREGRP} +FILESMODE ?= ${SHAREMODE} +FILES_COPY ?= -C + +FILESGROUPS ?= FILES +FILESGROUPS := ${FILESGROUPS:O:u} + +.if !target(buildfiles) +.for group in ${FILESGROUPS} +buildfiles: ${${group}} +.endfor +.endif +buildfiles: +realbuild: buildfiles + +# there is no default FILESDIR so +# ignore group if ${group}DIR is not defined +.for group in ${FILESGROUPS} +.if !empty(${group}) && defined(${group}DIR) +.if ${group} != "FILES" +${group}_INSTALL_OWN ?= ${FILES_INSTALL_OWN} +.endif +# incase we are staging +STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR} + +.for file in ${${group}:O:u} +${group}_INSTALL_OWN.${file:T} ?= ${${group}_INSTALL_OWN} +${group}DIR.${file:T} ?= ${${group}DIR} +file_mkdir_list += ${${group}DIR.${file:T}} + +.if defined(${group}NAME.${file:T}) +STAGE_AS_SETS += ${group} +STAGE_AS_${file} = ${${group}NAME.${file:T}} +stage_as.${group}: ${file} + +installfiles: installfiles.${group}.${file:T} +installfiles.${group}.${file:T}: ${file} file_mkdirs + ${INSTALL} ${FILES_COPY} ${${group}_INSTALL_OWN.${file:T}} \ + -m ${FILESMODE} ${.ALLSRC:Nfile_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${file:T}} + +.else +STAGE_SETS += ${group} +stage_files.${group}: ${file} +installfiles.${group}: ${file} +installfiles: installfiles.${group} +.endif + +.endfor # file + +installfiles.${group}: file_mkdirs + ${INSTALL} ${FILES_COPY} ${${group}_INSTALL_OWN} -m ${FILESMODE} \ + ${.ALLSRC:Nfile_mkdirs:O:u} ${DESTDIR}${${group}DIR} + +.endif # !empty +.endfor # group + +file_mkdirs: + @for d in ${file_mkdir_list:O:u}; do \ + test -d ${DESTDIR}$$d || \ + ${INSTALL} -d ${FILES_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \ + done + +beforeinstall: +installfiles: +realinstall: installfiles +.ORDER: beforeinstall installfiles Property changes on: vendor/NetBSD/bmake/20201101/mk/files.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/gendirdeps.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/gendirdeps.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/gendirdeps.mk (revision 367461) @@ -0,0 +1,385 @@ +# $Id: gendirdeps.mk,v 1.46 2020/08/19 17:51:53 sjg Exp $ + +# Copyright (c) 2011-2020, Simon J. Gerraty +# Copyright (c) 2010-2018, Juniper Networks, Inc. +# 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 +# OWNER 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. + +# +# This makefile [re]generates ${.MAKE.DEPENDFILE} +# + +.include + +# Assumptions: +# RELDIR is the relative path from ${SRCTOP} to ${_CURDIR} +# (SRCTOP is ${SB}/src) +# _CURDIR is the absolute version of ${.CURDIR} +# _OBJDIR is the absolute version of ${.OBJDIR} +# _objroot is realpath of ${_OBJTOP} without ${MACHINE} +# this may be different from _OBJROOT if $SB/obj is a +# symlink to another filesystem. +# _objroot must be a prefix match for _objtop + +.MAIN: all + +# keep this simple +.MAKE.MODE = compat + +all: + +_CURDIR ?= ${.CURDIR} +_OBJDIR ?= ${.OBJDIR} +_OBJTOP ?= ${OBJTOP} +_OBJROOT ?= ${OBJROOT:U${_OBJTOP:H}} +.if ${_OBJROOT:M*/} +_slash=/ +.else +_slash= +.endif +_objroot ?= ${_OBJROOT:tA}${_slash} + +_this = ${.PARSEDIR}/${.PARSEFILE} + +# remember what to make +_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T} + +# We do _not_ want to read our own output! +.MAKE.DEPENDFILE = /dev/null + +# caller should have set this +META_FILES ?= ${.MAKE.META.FILES} + +.if !empty(META_FILES) + +.if ${.MAKE.LEVEL} > 0 && !empty(GENDIRDEPS_FILTER) +# so we can compare below +.-include <${_DEPENDFILE}> +# yes, I mean :U with no value +_DIRDEPS := ${DIRDEPS:U:O:u} +.endif + +META_FILES := ${META_FILES:T:O:u} + +# pickup customizations +.-include + +# these are actually prefixes that we'll skip +# they should all be absolute paths +SKIP_GENDIRDEPS ?= +.if !empty(SKIP_GENDIRDEPS) +_skip_gendirdeps = egrep -v '^(${SKIP_GENDIRDEPS:O:u:ts|})' | +.else +_skip_gendirdeps = +.endif + +# Below we will turn _{VAR} into ${VAR} which keeps this simple +# GENDIRDEPS_FILTER_DIR_VARS is a list of dirs to be substiuted for. +# GENDIRDEPS_FILTER_VARS is more general. +# In each case order matters. +.if !empty(GENDIRDEPS_FILTER_DIR_VARS) +GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@} +.endif +.if !empty(GENDIRDEPS_FILTER_VARS) +GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u} +.endif + +# this (*should* be set in meta.sys.mk) +# is the script that extracts what we want. +META2DEPS ?= ${.PARSEDIR}/meta2deps.sh +META2DEPS := ${META2DEPS} + +.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" && ${DEBUG_GENDIRDEPS:Uno:Mmeta2d*} != "" +_time = time +_sh_x = sh -x +_py_d = -ddd +.else +_time = +_sh_x = +_py_d = +.endif + +.if ${META2DEPS:E} == "py" +# we can afford to do this all the time. +DPDEPS ?= no +META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d} +.if ${DPDEPS:tl} != "no" +META2DEPS_CMD += -D ${DPDEPS} +.endif +META2DEPS_FILTER = sed 's,^src:,${SRCTOP}/,;s,^\([^/]\),${OBJTOP}/\1,' | +.elif ${META2DEPS:E} == "sh" +META2DEPS_CMD = ${_time} ${_sh_x} ${META2DEPS} OBJTOP=${_OBJTOP} +.else +META2DEPS_CMD ?= ${META2DEPS} +.endif + +.if ${TARGET_OBJ_SPEC:U${MACHINE}} != ${MACHINE} +META2DEPS_CMD += -T ${TARGET_OBJ_SPEC} +.endif +META2DEPS_CMD += \ + -R ${RELDIR} -H ${HOST_TARGET} \ + ${M2D_OBJROOTS:O:u:@o@-O $o@} \ + ${M2D_EXCLUDES:O:u:@o@-X $o@} \ + + +M2D_OBJROOTS += ${OBJTOP} ${_OBJROOT} ${_objroot} +.if defined(SB_OBJROOT) +M2D_OBJROOTS += ${SB_OBJROOT} +.endif +.if defined(STAGE_ROOT) +M2D_OBJROOTS += ${STAGE_ROOT} +.endif +.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} == "" +# meta2deps.py only groks objroot +# so we need to give it what it expects +# and tell it not to add machine qualifiers +META2DEPS_ARGS += MACHINE=none +.endif +.if defined(SB_BACKING_SB) +META2DEPS_CMD += -S ${SB_BACKING_SB}/src +M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX} +.endif + +GENDIRDEPS_SEDCMDS += \ + -e 's,//*$$,,;s,\.${HOST_TARGET:Uhost}$$,.host,' \ + -e 's,\.${HOST_TARGET32:Uhost32}$$,.host32,' \ + -e 's,\.${MACHINE}$$,,' \ + -e 's:\.${TARGET_SPEC:U${MACHINE}}$$::' + +# we are only interested in the dirs +# specifically those we read something from. +# we canonicalize them to keep things simple +# if we are using a split-fs sandbox, it gets a little messier. +_objtop := ${_OBJTOP:tA} + +# some people put *.meta in META_XTRAS to make sure we get here +_meta_files := ${META_FILES:N\*.meta:O:u} +# assume a big list +_meta_files_arg= @meta.list +.if empty(_meta_files) && ${META_FILES:M\*.meta} != "" +# XXX this should be considered a bad idea, +# since we cannot ignore stale .meta +x != cd ${_OBJDIR} && find . -name '*.meta' -print -o \( -type d ! -name . -prune \) | sed 's,^./,,' > meta.list; echo +.elif ${_meta_files:[#]} > 500 +.export _meta_files +x != echo; for m in $$_meta_files; do echo $$m; done > meta.list +# _meta_files is consuming a lot of env space +# that can impact command line length, +# and we do not need it any more +.undef _meta_files +.unexport _meta_files +.else +_meta_files_arg:= ${_meta_files} +.endif + +dir_list != cd ${_OBJDIR} && \ + ${META2DEPS_CMD} MACHINE=${MACHINE} \ + SRCTOP=${SRCTOP} RELDIR=${RELDIR} CURDIR=${_CURDIR} \ + ${META2DEPS_ARGS} \ + ${_meta_files_arg} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \ + sed ${GENDIRDEPS_SEDCMDS} + +.if ${dir_list:M*ERROR\:*} != "" +.warning ${dir_list:tW:C,.*(ERROR),\1,} +.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,} +# we are not going to update anything +.else +dpadd_dir_list= +.if !empty(DPADD) +_nonlibs := ${DPADD:T:Nlib*:N*include} +.if !empty(_nonlibs) +ddep_list = +.for f in ${_nonlibs:@x@${DPADD:M*/$x}@} +.if exists($f.dirdep) +ddep_list += $f.dirdep +.elif exists(${f:H}.dirdep) +ddep_list += ${f:H}.dirdep +.else +dir_list += ${f:H:tA} +dpadd_dir_list += ${f:H:tA} +.endif +.endfor +.if !empty(ddep_list) +ddeps != cat ${ddep_list:O:u} | ${META2DEPS_FILTER} ${_skip_gendirdeps} \ + sed ${GENDIRDEPS_SEDCMDS} + +.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" +.info ${RELDIR}: raw_dir_list='${dir_list}' +.info ${RELDIR}: ddeps='${ddeps}' +.endif +dir_list += ${ddeps} +.endif +.endif +.endif + +# DIRDEPS represent things that had to have been built first +# so they should all be undir OBJTOP. +# Note that ${_OBJTOP}/bsd/include/machine will get reported +# to us as $SRCTOP/bsd/sys/$MACHINE_ARCH/include meaning we +# will want to visit bsd/include +# so we add +# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:} +# to GENDIRDEPS_DIR_LIST_XTRAS +_objtops = ${OBJTOP} ${_OBJTOP} ${_objtop} +_objtops := ${_objtops:O:u} +dirdep_list = \ + ${_objtops:@o@${dir_list:M$o*/*:C,$o[^/]*/,,}@} \ + ${GENDIRDEPS_DIR_LIST_XTRAS} + +# sort longest first +M2D_OBJROOTS := ${M2D_OBJROOTS:O:u:[-1..1]} + +# anything we use from an object dir other than ours +# needs to be qualified with its . suffix +# (we used the pseudo machine "host" for the HOST_TARGET). +skip_ql= ${SRCTOP}* ${_objtops:@o@$o*@} +.for o in ${M2D_OBJROOTS:${skip_ql:${M_ListToSkip}}} +# we need := so only skip_ql to this point applies +ql.$o := ${dir_list:${skip_ql:${M_ListToSkip}}:M$o*/*/*:C,$o([^/]+)/(.*),\2.\1,:S,.${HOST_TARGET},.host,} +qualdir_list += ${ql.$o} +.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" +.info ${RELDIR}: o=$o ${ql.$o qualdir_list:L:@v@$v=${$v}@} +.endif +skip_ql+= $o* +.endfor + +dirdep_list := ${dirdep_list:O:u} +qualdir_list := ${qualdir_list:N*.${MACHINE}:O:u} + +DIRDEPS = \ + ${dirdep_list:N${RELDIR}:N${RELDIR}/*} \ + ${qualdir_list:N${RELDIR}.*:N${RELDIR}/*} + +# We only consider things below $RELDIR/ if they have a makefile. +# This is the same test that _DIRDEP_USE applies. +# We have do a double test with dirdep_list as it _may_ contain +# qualified dirs - if we got anything from a stage dir. +# qualdir_list we know are all qualified. +# It would be nice do peform this check for all of DIRDEPS, +# but we cannot assume that all of the tree is present, +# in fact we can only assume that RELDIR is. +DIRDEPS += \ + ${dirdep_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/$d/$m):?$d:${exists(${SRCTOP}/${d:R}/$m):?$d:}}@}@} \ + ${qualdir_list:M${RELDIR}/*:@d@${.MAKE.MAKEFILE_PREFERENCE:@m@${exists(${SRCTOP}/${d:R}/$m):?$d:}@}@} + +# what modifiers do we allow in GENDIRDEPS_FILTER +GENDIRDEPS_FILTER_MASK += @CMNS +DIRDEPS := ${DIRDEPS:${GENDIRDEPS_FILTER:UNno:M[${GENDIRDEPS_FILTER_MASK:O:u:ts}]*:ts:}:C,//+,/,g:O:u} + +.if ${DEBUG_GENDIRDEPS:Uno:@x@${RELDIR:M$x}@} != "" +.info ${RELDIR}: M2D_OBJROOTS=${M2D_OBJROOTS} +.info ${RELDIR}: M2D_EXCLUDES=${M2D_EXCLUDES} +.info ${RELDIR}: dir_list='${dir_list}' +.info ${RELDIR}: dpadd_dir_list='${dpadd_dir_list}' +.info ${RELDIR}: dirdep_list='${dirdep_list}' +.info ${RELDIR}: qualdir_list='${qualdir_list}' +.info ${RELDIR}: SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS}' +.info ${RELDIR}: GENDIRDEPS_FILTER='${GENDIRDEPS_FILTER}' +.info ${RELDIR}: FORCE_DPADD='${DPADD}' +.info ${RELDIR}: DIRDEPS='${DIRDEPS}' +.endif + +# SRC_DIRDEPS is for checkout logic +src_dirdep_list = \ + ${dir_list:M${SRCTOP}/*:S,${SRCTOP}/,,} + +SRC_DIRDEPS = \ + ${src_dirdep_list:N${RELDIR}:N${RELDIR}/*:C,(/h)/.*,,} + +SRC_DIRDEPS := ${SRC_DIRDEPS:${GENDIRDEPS_SRC_FILTER:UN/*:ts:}:C,//+,/,g:O:u} + +# if you want to capture SRC_DIRDEPS in .MAKE.DEPENDFILE put +# SRC_DIRDEPS_FILE = ${_DEPENDFILE} +# in local.gendirdeps.mk +.if ${SRC_DIRDEPS_FILE:Uno:tl} != "no" +ECHO_SRC_DIRDEPS = echo 'SRC_DIRDEPS = \'; echo '${SRC_DIRDEPS:@d@ $d \\${.newline}@}'; echo; + +.if ${SRC_DIRDEPS_FILE:T} == ${_DEPENDFILE:T} +_include_src_dirdeps = ${ECHO_SRC_DIRDEPS} +.else +all: ${SRC_DIRDEPS_FILE} +.if !target(${SRC_DIRDEPS_FILE}) +${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS} + @(${ECHO_SRC_DIRDEPS}) > $@ +.endif +.endif +.endif +_include_src_dirdeps ?= + +all: ${_DEPENDFILE} + +# if this is going to exist it would be there by now +.if !exists(.depend) +CAT_DEPEND = /dev/null +.endif +CAT_DEPEND ?= .depend + +.if !empty(_DIRDEPS) && ${DIRDEPS} != ${_DIRDEPS} +# we may have changed a filter +.PHONY: ${_DEPENDFILE} +.endif + +LOCAL_DEPENDS_GUARD ?= _{.MAKE.LEVEL} > 0 + +# 'cat .depend' should suffice, but if we are mixing build modes +# .depend may contain things we don't want. +# The sed command at the end of the stream, allows for the filters +# to output _{VAR} tokens which we will turn into proper ${VAR} references. +${_DEPENDFILE}: .NOMETA ${CAT_DEPEND:M.depend} ${META_FILES:O:u:@m@${exists($m):?$m:}@} ${_this} ${META2DEPS} + @(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \ + echo 'DIRDEPS = \'; \ + echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \ + ${_include_src_dirdeps} \ + echo '.include '; \ + echo; \ + echo '.if ${LOCAL_DEPENDS_GUARD}'; \ + echo '# local dependencies - needed for -jN in clean tree'; \ + [ -s ${CAT_DEPEND} ] && { grep : ${CAT_DEPEND} | grep -v '[/\\]'; }; \ + echo '.endif' ) | sed 's,_\([{(]\),$$\1,g' > $@.new${.MAKE.PID} + @${InstallNew}; InstallNew -s $@.new${.MAKE.PID} + +.endif # meta2deps failed +.elif !empty(SUBDIR) + +DIRDEPS := ${SUBDIR:S,^,${RELDIR}/,:O:u} + +all: ${_DEPENDFILE} + +${_DEPENDFILE}: .NOMETA ${MAKEFILE} ${_this} + @(${GENDIRDEPS_HEADER} echo '# Autogenerated - do NOT edit!'; echo; \ + echo 'DIRDEPS = \'; \ + echo '${DIRDEPS:@d@ $d \\${.newline}@}'; echo; \ + echo '.include '; \ + echo ) | sed 's,_\([{(]\),$$\1,g' > $@.new + @${InstallNew}; InstallNew $@.new + +.else + +# nothing to do +all ${_DEPENDFILE}: + +.endif +${_DEPENDFILE}: .PRECIOUS + +# don't waste time looking for ways to make .meta files +.SUFFIXES: Index: vendor/NetBSD/bmake/20201101/mk/host-target.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/host-target.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/host-target.mk (revision 367461) @@ -0,0 +1,49 @@ +# RCSid: +# $Id: host-target.mk,v 1.13 2020/08/05 23:32:08 sjg Exp $ + +# Host platform information; may be overridden +.if !defined(_HOST_OSNAME) +_HOST_OSNAME != uname -s +.export _HOST_OSNAME +.endif +.if !defined(_HOST_OSREL) +_HOST_OSREL != uname -r +.export _HOST_OSREL +.endif +.if !defined(_HOST_MACHINE) +_HOST_MACHINE != uname -m +.export _HOST_MACHINE +.endif +.if !defined(_HOST_ARCH) +# for NetBSD prefer $MACHINE (amd64 rather than x86_64) +.if ${_HOST_OSNAME:NDarwin:NNetBSD} == "" +_HOST_ARCH := ${_HOST_MACHINE} +.else +_HOST_ARCH != uname -p 2> /dev/null || uname -m +# uname -p may produce garbage on linux +.if ${_HOST_ARCH:[\#]} > 1 || ${_HOST_ARCH:Nunknown} == "" +_HOST_ARCH := ${_HOST_MACHINE} +.endif +.endif +.export _HOST_ARCH +.endif +.if !defined(HOST_MACHINE) +HOST_MACHINE := ${_HOST_MACHINE} +.export HOST_MACHINE +.endif + +HOST_OSMAJOR := ${_HOST_OSREL:C/[^0-9].*//} +HOST_OSTYPE := ${_HOST_OSNAME:S,/,,g}-${_HOST_OSREL:C/\([^\)]*\)//}-${_HOST_ARCH} +HOST_OS := ${_HOST_OSNAME} +host_os := ${_HOST_OSNAME:tl} +HOST_TARGET := ${host_os:S,/,,g}${HOST_OSMAJOR}-${_HOST_ARCH} +# sometimes we want HOST_TARGET32 +MACHINE32.amd64 = i386 +MACHINE32.x86_64 = i386 +_HOST_ARCH32 := ${MACHINE32.${_HOST_ARCH}:U${_HOST_ARCH:S,64$,,}} +HOST_TARGET32 := ${host_os:S,/,,g}${HOST_OSMAJOR}-${_HOST_ARCH32} + +# tr is insanely non-portable, accommodate the lowest common denominator +TR ?= tr +toLower = ${TR} 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' +toUpper = ${TR} 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' Index: vendor/NetBSD/bmake/20201101/mk/host.libnames.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/host.libnames.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/host.libnames.mk (revision 367461) @@ -0,0 +1,29 @@ +# $Id: host.libnames.mk,v 1.5 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2007-2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + + +DLIBEXT ?= .a +DSHLIBEXT ?= ${DLIBEXT} +HOST_LIBEXT ?= ${DSHLIBEXT} +HOST_LIBDIRS ?= /usr/lib /lib +HOST_LIBS ?= + +.for x in ${HOST_LIBS:O:u} +.for d in ${HOST_LIBDIRS} +.if exists($d/lib$x${HOST_LIBEXT}) +LIB${x:tu} ?= $d/lib$x${HOST_LIBEXT} +.endif +.endfor +.endfor Index: vendor/NetBSD/bmake/20201101/mk/inc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/inc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/inc.mk (revision 367461) @@ -0,0 +1,89 @@ +# $Id: inc.mk,v 1.8 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2008, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.include + +.if !empty(LIBOWN) +INC_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP} +.endif +INCMODE ?= 444 +INC_COPY ?= -C +INCSDIR ?= ${INCDIR} + +STAGE_INCSDIR?= ${STAGE_OBJTOP}${INCSDIR} + +# accommodate folk used to freebsd +INCGROUPS ?= ${INCSGROUPS:UINCS} +INCGROUPS := ${INCGROUPS:O:u} + +.if !target(buildincludes) +.for group in ${INCGROUPS} +buildincludes: ${${group}} +.endfor +.endif +buildincludes: +includes: buildincludes + +.if !target(incinstall) +.for group in ${INCGROUPS} +.if !empty(${group}) +.if ${group} != "INC" +${group}_INSTALL_OWN ?= ${INC_INSTALL_OWN} +${group}DIR ?= ${INCDIR} +.endif +# incase we are staging +STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR} + +.for header in ${${group}:O:u} +${group}_INSTALL_OWN.${header:T} ?= ${${group}_INSTALL_OWN} +${group}DIR.${header:T} ?= ${${group}DIR} +inc_mkdir_list += ${${group}DIR.${header:T}} + +.if defined(${group}NAME.${header:T}) +STAGE_AS_SETS += ${group} +STAGE_AS_${header} = ${${group}NAME.${header:T}} +stage_as.${group}: ${header} + +incinstall: incinstall.${group}.${header:T} +incinstall.${group}.${header:T}: ${header} inc_mkdirs + ${INSTALL} ${INC_COPY} ${${group}_INSTALL_OWN.${header:T}} -m ${INCMODE} ${.ALLSRC:Ninc_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${header:T}} + +.else +STAGE_SETS += ${group} +stage_files.${group}: ${header} +incinstall.${group}: ${header} +incinstall: incinstall.${group} +.endif + +.endfor # header + +incinstall.${group}: inc_mkdirs + ${INSTALL} ${INC_COPY} ${${group}_INSTALL_OWN} -m ${INCMODE} \ + ${.ALLSRC:Ninc_mkdirs:O:u} ${DESTDIR}${${group}DIR} + +.endif # !empty +.endfor # group + +inc_mkdirs: + @for d in ${inc_mkdir_list:O:u}; do \ + test -d ${DESTDIR}$$d || \ + ${INSTALL} -d ${INC_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \ + done + +.endif # !target(incinstall) + +beforeinstall: +realinstall: incinstall +.ORDER: beforeinstall incinstall Index: vendor/NetBSD/bmake/20201101/mk/init.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/init.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/init.mk (revision 367461) @@ -0,0 +1,93 @@ +# $Id: init.mk,v 1.21 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2002, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.if ${MAKE_VERSION:U0} > 20100408 +_this_mk_dir := ${.PARSEDIR:tA} +.else +_this_mk_dir := ${.PARSEDIR} +.endif + +.-include +.-include <${.CURDIR:H}/Makefile.inc> +.include +.include + +.MAIN: all + +# should have been set by sys.mk +CXX_SUFFIXES?= .cc .cpp .cxx .C + +.if !empty(WARNINGS_SET) || !empty(WARNINGS_SET_${MACHINE_ARCH}) +.include +.endif + +# these are applied in order, least specific to most +VAR_QUALIFIER_LIST += \ + ${TARGET_SPEC_VARS:UMACHINE:@v@${$v}@} \ + ${COMPILER_TYPE} \ + ${.TARGET:T:R} \ + ${.TARGET:T} \ + ${.IMPSRC:T} \ + ${VAR_QUALIFIER_XTRA_LIST} + +QUALIFIED_VAR_LIST += \ + CFLAGS \ + COPTS \ + CPPFLAGS \ + CPUFLAGS \ + LDFLAGS \ + +# a final :U avoids errors if someone uses := +.for V in ${QUALIFIED_VAR_LIST:O:u:@q@$q $q_LAST@} +.for Q in ${VAR_QUALIFIER_LIST:u} +$V += ${$V.$Q:U} ${$V.$Q.${COMPILER_TYPE}:U} +.endfor +.endfor + +CC_PG?= -pg +CXX_PG?= ${CC_PG} +CC_PIC?= -DPIC +CXX_PIC?= ${CC_PIC} +PROFFLAGS?= -DGPROF -DPROF + +# targets that are ok at level 0 +LEVEL0_TARGETS += clean* destory* +M_ListToSkip= O:u:S,^,N,:ts: + +.if ${.MAKE.LEVEL:U1} == 0 && ${MK_DIRDEPS_BUILD:Uno} == "yes" && ${.TARGETS:Uall:${LEVEL0_TARGETS:${M_ListToSkip}}} != "" +# this tells lib.mk and prog.mk to not actually build anything +_SKIP_BUILD = not building at level 0 +.endif + +.if !defined(.PARSEDIR) +# no-op is the best we can do if not bmake. +.WAIT: +.endif + +# define this once for consistency +.if empty(_SKIP_BUILD) +# beforebuild is a hook for things that must be done early +all: beforebuild .WAIT realbuild +.else +all: .PHONY +.warning ${_SKIP_BUILD} +.endif +beforebuild: +realbuild: + +.endif Index: vendor/NetBSD/bmake/20201101/mk/install-new.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/install-new.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/install-new.mk (revision 367461) @@ -0,0 +1,53 @@ +# $Id: install-new.mk,v 1.4 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !defined(InstallNew) + +# copy if src and target are different making a backup if desired +CmpCp= CmpCp() { \ + src=$$1 target=$$2 _bak=$$3; \ + if ! test -s $$target || ! cmp -s $$target $$src; then \ + trap "" 1 2 3 15; \ + if test -s $$target; then \ + if test "x$$_bak" != x; then \ + rm -f $$target$$_bak; \ + mv $$target $$target$$_bak; \ + else \ + rm -f $$target; \ + fi; \ + fi; \ + cp $$src $$target; \ + fi; } + +# If the .new file is different, we want it. +# Note: this function will work as is for *.new$RANDOM" +InstallNew= ${CmpCp}; InstallNew() { \ + _t=-e; _bak=; \ + while :; do \ + case "$$1" in \ + -?) _t=$$1; shift;; \ + --bak) _bak=$$2; shift 2;; \ + *) break;; \ + esac; \ + done; \ + for new in "$$@"; do \ + if test $$_t $$new; then \ + target=`expr $$new : '\(.*\).new'`; \ + CmpCp $$new $$target $$_bak; \ + fi; \ + rm -f $$new; \ + done; :; } + +.endif Index: vendor/NetBSD/bmake/20201101/mk/java.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/java.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/java.mk (revision 367461) @@ -0,0 +1,97 @@ +# +# RCSid: +# $Id: java.mk,v 1.15 2020/08/19 17:51:53 sjg Exp $ + +# @(#) Copyright (c) 1998-2001, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.include + +CLASSPATH?=. + +.if defined(PROG) +SRCS?= ${PROG:.class=.java} +.endif +.if !defined(SRCS) || empty(SRCS) +SRCS!=cd ${.CURDIR} && echo *.java +.endif +.SUFFIXES: .class .java + +CLEANFILES+= *.class + +JAVAC?= javac +JAVADOC?= javadoc + +.if !target(docs) +docs: + ${JAVADOC} ${JAVADOC_FLAGS} ${SRCS} +.endif + +.if defined(JAVADESTDIR) && !empty(JAVADESTDIR) +JAVASRCDIR?=${JAVADESTDIR:H}/src +__classdest:=${JAVADESTDIR}${.CURDIR:S,${JAVASRCDIR},,}/ +CLASSPATH:=${CLASSPATH}:${JAVADESTDIR} +JAVAC_FLAGS+= -d ${JAVADESTDIR} +.else +__classdest= +.endif + +JAVAC_FLAGS+= ${JAVAC_DBG} + +.if defined(MAKE_VERSION) && !defined(NO_CLASSES_COOKIE) +# java works best by compiling a bunch of classes at once. +# this lot does that but needs a recent netbsd make or +# or its portable cousin bmake. +.for __s in ${SRCS} +__c:= ${__classdest}${__s:.java=.class} +.if !target(${__c}) +# We need to do something to force __c's parent to be made. +${__c}: ${__s} + @rm -f ${.TARGET} +.endif +SRCS_${__c}=${__s} +__classes:= ${__classes} ${__c} +.endfor +__classes_cookie=${__classdest}.classes.done +CLEANFILES+= ${__classes} ${__classes_cookie} + +${__classes_cookie}: ${__classes} + CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE:@c@${SRCS_$c}@} + @touch ${.TARGET} + +all: ${__classes_cookie} + +.else +# this will work with other BSD make's +.for __s in ${SRCS} +__c:= ${__classdest}${__s:.java=.class} +${__c}: ${__s} + CLASSPATH=${CLASSPATH} ${JAVAC} ${JAVAC_FLAGS} ${.OODATE} +.endfor + +all: ${SRCS:%.java=${__classdest}%.class} + +.endif + +.if !target(cleanjava) +cleanjava: + rm -f [Ee]rrs mklog core *.core ${PROG} ${CLEANFILES} + +clean: cleanjava +cleandir: cleanjava +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/lib.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/lib.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/lib.mk (revision 367461) @@ -0,0 +1,609 @@ +# $Id: lib.mk,v 1.71 2020/08/19 17:51:53 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.include + +.if ${OBJECT_FMT} == "ELF" +NEED_SOLINKS?= yes +.endif + +SHLIB_VERSION_FILE?= ${.CURDIR}/shlib_version +.if !defined(SHLIB_MAJOR) && exists(${SHLIB_VERSION_FILE}) +SHLIB_MAJOR != . ${SHLIB_VERSION_FILE} ; echo $$major +SHLIB_MINOR != . ${SHLIB_VERSION_FILE} ; echo $$minor +SHLIB_TEENY != . ${SHLIB_VERSION_FILE} ; echo $$teeny +.endif + +.for x in major minor teeny +print-shlib-$x: +.if defined(SHLIB_${x:tu}) && ${MK_PIC} != "no" + @echo ${SHLIB_${x:tu}} +.else + @false +.endif +.endfor + +SHLIB_FULLVERSION ?= ${${SHLIB_MAJOR} ${SHLIB_MINOR} ${SHLIB_TEENY}:L:ts.} +SHLIB_FULLVERSION := ${SHLIB_FULLVERSION} + +# add additional suffixes not exported. +# .po is used for profiling object files. +# ${PICO} is used for PIC object files. +PICO?= .pico +.SUFFIXES: .out .a .ln ${PICO} .po .o .s .S .c .cc .C .m .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 .m + +CFLAGS+= ${COPTS} + +META_NOECHO?= echo + +# Originally derrived from NetBSD-1.6 + +# Set PICFLAGS to cc flags for producing position-independent code, +# if not already set. Includes -DPIC, if required. + +# Data-driven table using make variables to control how shared libraries +# are built for different platforms and object formats. +# OBJECT_FMT: currently either "ELF" or "a.out", from +# SHLIB_SOVERSION: version number to be compiled into a shared library +# via -soname. Usually ${SHLIB_MAJOR} on ELF. +# NetBSD/pmax used to use ${SHLIB_MAJOR}[.${SHLIB_MINOR} +# [.${SHLIB_TEENY}]] +# SHLIB_SHFLAGS: Flags to tell ${LD} to emit shared library. +# with ELF, also set shared-lib version for ld.so. +# SHLIB_LDSTARTFILE: support .o file, call C++ file-level constructors +# SHLIB_LDENDFILE: support .o file, call C++ file-level destructors +# FPICFLAGS: flags for ${FC} to compile .[fF] files to ${PICO} objects. +# CPPICFLAGS: flags for ${CPP} to preprocess .[sS] files for ${AS} +# CPICFLAGS: flags for ${CC} to compile .[cC] files to ${PICO} objects. +# CAPICFLAGS flags for {$CC} to compiling .[Ss] files +# (usually just ${CPPPICFLAGS} ${CPICFLAGS}) +# APICFLAGS: flags for ${AS} to assemble .[sS] to ${PICO} objects. + +.if ${TARGET_OSNAME} == "NetBSD" +.if ${MACHINE_ARCH} == "alpha" + # Alpha-specific shared library flags +FPICFLAGS ?= -fPIC +CPICFLAGS ?= -fPIC -DPIC +CPPPICFLAGS?= -DPIC +CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS} +APICFLAGS ?= +.elif ${MACHINE_ARCH} == "mipsel" || ${MACHINE_ARCH} == "mipseb" + # mips-specific shared library flags + +# On mips, all libs are compiled with ABIcalls, not just sharedlibs. +MKPICLIB= no + +# so turn shlib PIC flags on for ${AS}. +AINC+=-DABICALLS +AFLAGS+= -fPIC +AS+= -KPIC + +.elif ${MACHINE_ARCH} == "vax" && ${OBJECT_FMT} == "ELF" +# On the VAX, all object are PIC by default, not just sharedlibs. +MKPICLIB= no + +.elif (${MACHINE_ARCH} == "sparc" || ${MACHINE_ARCH} == "sparc64") && \ + ${OBJECT_FMT} == "ELF" +# If you use -fPIC you need to define BIGPIC to turn on 32-bit +# relocations in asm code +FPICFLAGS ?= -fPIC +CPICFLAGS ?= -fPIC -DPIC +CPPPICFLAGS?= -DPIC -DBIGPIC +CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS} +APICFLAGS ?= -KPIC + +.else + +# Platform-independent flags for NetBSD a.out shared libraries +SHLIB_SOVERSION=${SHLIB_FULLVERSION} +SHLIB_SHFLAGS= +FPICFLAGS ?= -fPIC +CPICFLAGS?= -fPIC -DPIC +CPPPICFLAGS?= -DPIC +CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS} +APICFLAGS?= -k + +.endif + +# Platform-independent linker flags for ELF shared libraries +.if ${OBJECT_FMT} == "ELF" +SHLIB_SOVERSION= ${SHLIB_MAJOR} +SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION} +SHLIB_LDSTARTFILE?= /usr/lib/crtbeginS.o +SHLIB_LDENDFILE?= /usr/lib/crtendS.o +.endif + +# for compatibility with the following +CC_PIC?= ${CPICFLAGS} +LD_shared=${SHLIB_SHFLAGS} + +.endif # NetBSD + +.if ${TARGET_OSNAME} == "FreeBSD" +.if ${OBJECT_FMT} == "ELF" +SHLIB_SOVERSION= ${SHLIB_MAJOR} +SHLIB_SHFLAGS= -soname lib${LIB}.so.${SHLIB_SOVERSION} +.else +SHLIB_SHFLAGS= -assert pure-text +.endif +SHLIB_LDSTARTFILE= +SHLIB_LDENDFILE= +CC_PIC?= -fpic +LD_shared=${SHLIB_SHFLAGS} + +.endif # FreeBSD + +MKPICLIB?= yes + +# sys.mk can override these +LD_X?=-X +LD_x?=-x +LD_r?=-r + +# Non BSD machines will be using bmake. +.if ${TARGET_OSNAME} == "SunOS" +LD_shared=-assert pure-text +.if ${OBJECT_FMT} == "ELF" || ${MACHINE} == "solaris" +# Solaris +LD_shared=-h lib${LIB}.so.${SHLIB_MAJOR} -G +.endif +.elif ${TARGET_OSNAME} == "HP-UX" +LD_shared=-b +LD_so=sl +DLLIB= +# HPsUX lorder does not grok anything but .o +LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,${PICO},'` +LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'` +.elif ${TARGET_OSNAME} == "OSF1" +LD_shared= -msym -shared -expect_unresolved '*' +LD_solib= -all lib${LIB}_pic.a +DLLIB= +# lorder does not grok anything but .o +LD_sobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,${PICO},'` +LD_pobjs=`${LORDER} ${OBJS} | ${TSORT} | sed 's,\.o,.po,'` +AR_cq= -cqs +.elif ${TARGET_OSNAME} == "FreeBSD" +LD_solib= lib${LIB}_pic.a +.elif ${TARGET_OSNAME} == "Linux" +SHLIB_LD = ${CC} +# this is ambiguous of course +LD_shared=-shared -Wl,"-soname lib${LIB}.so.${SHLIB_MAJOR}" +LD_solib= -Wl,--whole-archive lib${LIB}_pic.a -Wl,--no-whole-archive +.if ${COMPILER_TYPE} == "gcc" +# Linux uses GNU ld, which is a multi-pass linker +# so we don't need to use lorder or tsort +LD_objs = ${OBJS} +LD_pobjs = ${POBJS} +LD_sobjs = ${SOBJS} +.endif +.elif ${TARGET_OSNAME} == "Darwin" +SHLIB_LD = ${CC} +SHLIB_INSTALL_VERSION ?= ${SHLIB_MAJOR} +SHLIB_COMPATABILITY_VERSION ?= ${SHLIB_MAJOR}.${SHLIB_MINOR:U0} +SHLIB_COMPATABILITY ?= \ + -compatibility_version ${SHLIB_COMPATABILITY_VERSION} \ + -current_version ${SHLIB_FULLVERSION} +LD_shared = -dynamiclib \ + -flat_namespace -undefined suppress \ + -install_name ${LIBDIR}/lib${LIB}.${SHLIB_INSTALL_VERSION}.${LD_solink} \ + ${SHLIB_COMPATABILITY} +SHLIB_LINKS = +.for v in ${SHLIB_COMPATABILITY_VERSION} ${SHLIB_INSTALL_VERSION} +.if "$v" != "${SHLIB_FULLVERSION}" +SHLIB_LINKS += lib${LIB}.$v.${LD_solink} +.endif +.endfor +.if ${MK_LINKLIB} != "no" +SHLIB_LINKS += lib${LIB}.${LD_solink} +.endif + +LD_so = ${SHLIB_FULLVERSION}.dylib +LD_sobjs = ${SOBJS:O:u} +LD_solib = ${LD_sobjs} +SOLIB = ${LD_sobjs} +LD_solink = dylib +.if ${MACHINE_ARCH} == "i386" +PICFLAG ?= -fPIC +.else +PICFLAG ?= -fPIC -fno-common +.endif +RANLIB = : +.endif + +SHLIB_LD ?= ${LD} + +.if !empty(SHLIB_MAJOR) +.if ${NEED_SOLINKS} && empty(SHLIB_LINKS) +.if ${MK_LINKLIB} != "no" +SHLIB_LINKS = lib${LIB}.${LD_solink} +.endif +.if "${SHLIB_FULLVERSION}" != "${SHLIB_MAJOR}" +SHLIB_LINKS += lib${LIB}.${LD_solink}.${SHLIB_MAJOR} +.endif +.endif +.endif + +LIBTOOL?=libtool +LD_shared ?= -Bshareable -Bforcearchive +LD_so ?= so.${SHLIB_FULLVERSION} +LD_solink ?= so +.if empty(LORDER) +LD_objs ?= ${OBJS} +LD_pobjs ?= ${POBJS} +LD_sobjs ?= ${SOBJS} +.else +LD_objs ?= `${LORDER} ${OBJS} | ${TSORT}` +LD_sobjs ?= `${LORDER} ${SOBJS} | ${TSORT}` +LD_pobjs ?= `${LORDER} ${POBJS} | ${TSORT}` +.endif +LD_solib ?= ${LD_sobjs} +AR_cq ?= cq +.if exists(/netbsd) && exists(${DESTDIR}/usr/lib/libdl.so) +DLLIB ?= -ldl +.endif + +# some libs have lots of objects, and scanning all .o, .po and ${PICO} meta files +# is a waste of time, this tells meta.autodep.mk to just pick one +# (typically ${PICO}) +# yes, 42 is a random number. +.if ${MK_DIRDEPS_BUILD} == "yes" && ${SRCS:Uno:[\#]} > 42 +OPTIMIZE_OBJECT_META_FILES ?= yes +.endif + + +.if ${MK_LIBTOOL} == "yes" +# because libtool is so fascist about naming the object files, +# we cannot (yet) build profiled libs +MK_PROFILE=no +_LIBS=lib${LIB}.a +.if exists(${.CURDIR}/shlib_version) +SHLIB_AGE != . ${.CURDIR}/shlib_version ; echo $$age +.endif +.else +# for the normal .a we do not want to strip symbols +.c.o: + ${COMPILE.c} ${.IMPSRC} + +# for the normal .a we do not want to strip symbols +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} + +.S.o .s.o: + ${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} + +.if (${LD_X} == "") +.c.po: + ${COMPILE.c} ${CC_PG} ${PROFFLAGS} ${.IMPSRC} -o ${.TARGET} + +${CXX_SUFFIXES:%=%.po}: + ${COMPILE.cc} -pg ${.IMPSRC} -o ${.TARGET} + +.S${PICO} .s${PICO}: + ${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET} +.else +.c.po: + ${COMPILE.c} ${CC_PG} ${PROFFLAGS} ${.IMPSRC} -o ${.TARGET}.o + @${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o + +${CXX_SUFFIXES:%=%.po}: + ${COMPILE.cc} ${CXX_PG} ${.IMPSRC} -o ${.TARGET}.o + ${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o + +.S${PICO} .s${PICO}: + ${COMPILE.S} ${PICFLAG} ${CC_PIC} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o + ${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o +.endif + +.if (${LD_x} == "") +.c${PICO}: + ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET} + +${CXX_SUFFIXES:%=%${PICO}}: + ${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET} + +.S.po .s.po: + ${COMPILE.S} ${PROFFLAGS} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET} +.else + +.c${PICO}: + ${COMPILE.c} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o + ${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o + +${CXX_SUFFIXES:%=%${PICO}}: + ${COMPILE.cc} ${PICFLAG} ${CC_PIC} ${.IMPSRC} -o ${.TARGET}.o + ${LD} ${LD_x} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o + +.S.po .s.po: + ${COMPILE.S} ${PROFFLAGS} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC} -o ${.TARGET}.o + ${LD} ${LD_X} ${LD_r} ${.TARGET}.o -o ${.TARGET} + @rm -f ${.TARGET}.o + +.endif +.endif + +.c.ln: + ${LINT} ${LINTFLAGS} ${CFLAGS:M-[IDU]*} -i ${.IMPSRC} + +.if ${MK_LIBTOOL} != "yes" + +.if !defined(PICFLAG) +PICFLAG=-fpic +.endif + +_LIBS= + +.if ${MK_ARCHIVE} != "no" +_LIBS += lib${LIB}.a +.endif + +.if ${MK_PROFILE} != "no" +_LIBS+=lib${LIB}_p.a +POBJS+=${OBJS:.o=.po} +.endif + +.if ${MK_PIC} != "no" +.if ${MK_PICLIB} == "no" +SOLIB ?= lib${LIB}.a +.else +SOLIB=lib${LIB}_pic.a +_LIBS+=${SOLIB} +.endif +.if !empty(SHLIB_FULLVERSION) +_LIBS+=lib${LIB}.${LD_so} +.endif +.endif + +.if ${MK_LINT} != "no" +_LIBS+=llib-l${LIB}.ln +.endif + +# here is where you can define what LIB* are +.-include +.if ${MK_DPADD_MK} == "yes" +# lots of cool magic, but might not suit everyone. +.include +.endif + +.if empty(LIB) +_LIBS= +.elif ${MK_LDORDER_MK} != "no" +# Record any libs that we need to be linked with +_LIBS+= ${libLDORDER_INC} + +.include +.endif + +.if !defined(_SKIP_BUILD) +realbuild: ${_LIBS} +.endif + +all: _SUBDIRUSE + +.for s in ${SRCS:N*.h:M*/*} +${.o ${PICO} .po .lo:L:@o@${s:T:R}$o@}: $s +.endfor + +OBJS+= ${SRCS:T:N*.h:R:S/$/.o/g} +.NOPATH: ${OBJS} + +.if ${MK_LIBTOOL} == "yes" +.if ${MK_PIC} == "no" +LT_STATIC=-static +.else +LT_STATIC= +.endif +SHLIB_AGE?=0 + +# .lo's are created as a side effect +.s.o .S.o .c.o: + ${LIBTOOL} --mode=compile ${CC} ${LT_STATIC} ${CFLAGS} ${CPPFLAGS} ${IMPFLAGS} -c ${.IMPSRC} + +# can't really do profiled libs with libtool - its too fascist about +# naming the output... +lib${LIB}.a: ${OBJS} + @rm -f ${.TARGET} + ${LIBTOOL} --mode=link ${CC} ${LT_STATIC} -o ${.TARGET:.a=.la} ${OBJS:.o=.lo} -rpath ${SHLIBDIR}:/usr/lib -version-info ${SHLIB_MAJOR}:${SHLIB_MINOR}:${SHLIB_AGE} + @ln .libs/${.TARGET} . + +lib${LIB}.${LD_so}: lib${LIB}.a + @[ -s ${.TARGET}.${SHLIB_AGE} ] || { ln -s .libs/lib${LIB}.${LD_so}* . 2>/dev/null; : } + @[ -s ${.TARGET} ] || ln -s ${.TARGET}.${SHLIB_AGE} ${.TARGET} + +.else # MK_LIBTOOL=yes + +lib${LIB}.a: ${OBJS} + @${META_NOECHO} building standard ${LIB} library + @rm -f ${.TARGET} + @${AR} ${AR_cq} ${.TARGET} ${LD_objs} + ${RANLIB} ${.TARGET} + +POBJS+= ${OBJS:.o=.po} +.NOPATH: ${POBJS} +lib${LIB}_p.a: ${POBJS} + @${META_NOECHO} building profiled ${LIB} library + @rm -f ${.TARGET} + @${AR} ${AR_cq} ${.TARGET} ${LD_pobjs} + ${RANLIB} ${.TARGET} + +SOBJS+= ${OBJS:.o=${PICO}} +.NOPATH: ${SOBJS} +lib${LIB}_pic.a: ${SOBJS} + @${META_NOECHO} building shared object ${LIB} library + @rm -f ${.TARGET} + @${AR} ${AR_cq} ${.TARGET} ${LD_sobjs} + ${RANLIB} ${.TARGET} + +#SHLIB_LDADD?= ${LDADD} + +# bound to be non-portable... +# this is known to work for NetBSD 1.6 and FreeBSD 4.2 +lib${LIB}.${LD_so}: ${SOLIB} ${DPADD} + @${META_NOECHO} building shared ${LIB} library \(version ${SHLIB_FULLVERSION}\) + @rm -f ${.TARGET} +.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD" +.if ${OBJECT_FMT} == "ELF" + ${SHLIB_LD} -x -shared ${SHLIB_SHFLAGS} -o ${.TARGET} \ + ${SHLIB_LDSTARTFILE} \ + --whole-archive ${SOLIB} --no-whole-archive ${SHLIB_LDADD} \ + ${SHLIB_LDENDFILE} +.else + ${SHLIB_LD} ${LD_x} ${LD_shared} \ + -o ${.TARGET} ${SOLIB} ${SHLIB_LDADD} +.endif +.else + ${SHLIB_LD} -o ${.TARGET} ${LD_shared} ${LD_solib} ${DLLIB} ${SHLIB_LDADD} +.endif +.endif +.if !empty(SHLIB_LINKS) + rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s ${.TARGET} $x;@} +.endif + +LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln} +.NOPATH: ${LOBJS} +LLIBS?= -lc +llib-l${LIB}.ln: ${LOBJS} + @${META_NOECHO} building llib-l${LIB}.ln + @rm -f llib-l${LIB}.ln + @${LINT} -C${LIB} ${LOBJS} ${LLIBS} + +.if !target(clean) +cleanlib: .PHONY + rm -f a.out [Ee]rrs mklog core *.core ${CLEANFILES} + rm -f lib${LIB}.a ${OBJS} + rm -f lib${LIB}_p.a ${POBJS} + rm -f lib${LIB}_pic.a lib${LIB}.so.*.* ${SOBJS} + rm -f llib-l${LIB}.ln ${LOBJS} +.if !empty(SHLIB_LINKS) + rm -f ${SHLIB_LINKS} +.endif + +clean: _SUBDIRUSE cleanlib +cleandir: _SUBDIRUSE cleanlib +.else +cleandir: _SUBDIRUSE clean +.endif + +.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep) +afterdepend: .depend + @(TMP=/tmp/_depend$$$$; \ + sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.po \1${PICO} \1.ln:/' \ + < .depend > $$TMP; \ + mv $$TMP .depend) +.endif + +.if !target(install) +.if !target(beforeinstall) +beforeinstall: +.endif + +.if !empty(LIBOWN) +LIB_INSTALL_OWN ?= -o ${LIBOWN} -g ${LIBGRP} +.endif + +.include + +.if !target(libinstall) && !empty(LIB) +realinstall: libinstall +libinstall: + [ -d ${DESTDIR}/${LIBDIR} ] || \ + ${INSTALL} -d ${LIB_INSTALL_OWN} -m 775 ${DESTDIR}${LIBDIR} +.if ${MK_ARCHIVE} != "no" + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 lib${LIB}.a \ + ${DESTDIR}${LIBDIR} + ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}.a + chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}.a +.endif +.if ${MK_PROFILE} != "no" + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \ + lib${LIB}_p.a ${DESTDIR}${LIBDIR} + ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a + chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_p.a +.endif +.if ${MK_LDORDER_MK} != "no" + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \ + lib${LIB}.ldorder.inc ${DESTDIR}${LIBDIR} +.endif +.if ${MK_PIC} != "no" +.if ${MK_PICLIB} != "no" + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m 644 \ + lib${LIB}_pic.a ${DESTDIR}${LIBDIR} + ${RANLIB} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a + chmod ${LIBMODE} ${DESTDIR}${LIBDIR}/lib${LIB}_pic.a +.endif +.if !empty(SHLIB_MAJOR) + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \ + lib${LIB}.${LD_so} ${DESTDIR}${LIBDIR} +.if !empty(SHLIB_LINKS) + (cd ${DESTDIR}${LIBDIR} && { rm -f ${SHLIB_LINKS}; ${SHLIB_LINKS:O:u:@x@ln -s lib${LIB}.${LD_so} $x;@} }) +.endif +.endif +.endif +.if ${MK_LINT} != "no" && ${MK_LINKLIB} != "no" && !empty(LOBJS) + ${INSTALL} ${COPY} ${LIB_INSTALL_OWN} -m ${LIBMODE} \ + llib-l${LIB}.ln ${DESTDIR}${LINTLIBDIR} +.endif +.if defined(LINKS) && !empty(LINKS) + @set ${LINKS}; ${_LINKS_SCRIPT} +.endif +.endif + +.if ${MK_MAN} != "no" +install: maninstall _SUBDIRUSE +maninstall: afterinstall +.endif +afterinstall: realinstall +libinstall: beforeinstall +realinstall: beforeinstall +.endif + +.if defined(FILES) || defined(FILESGROUPS) +.include +.endif + +.if ${MK_MAN} != "no" +.include +.endif + +.if ${MK_NLS} != "no" +.include +.endif + +.include +.include +.include +.include +.endif + +# during building we usually need/want to install libs somewhere central +# note that we do NOT ch{own,grp} as that would likely fail at this point. +# otherwise it is the same as realinstall +# Note that we don't need this when using dpadd.mk +.libinstall: ${_LIBS} + test -d ${DESTDIR}${LIBDIR} || ${INSTALL} -d -m775 ${DESTDIR}${LIBDIR} +.for _lib in ${_LIBS:M*.a} + ${INSTALL} ${COPY} -m 644 ${_lib} ${DESTDIR}${LIBDIR} + ${RANLIB} ${DESTDIR}${LIBDIR}/${_lib} +.endfor +.for _lib in ${_LIBS:M*.${LD_solink}*:O:u} + ${INSTALL} ${COPY} -m ${LIBMODE} ${_lib} ${DESTDIR}${LIBDIR} +.if !empty(SHLIB_LINKS) + (cd ${DESTDIR}${LIBDIR} && { ${SHLIB_LINKS:O:u:@x@ln -sf ${_lib} $x;@}; }) +.endif +.endfor + @touch ${.TARGET} + +.if !empty(LIB) +STAGE_LIBDIR?= ${STAGE_OBJTOP}${LIBDIR} +stage_libs: ${_LIBS} +.endif + +.include +.endif Index: vendor/NetBSD/bmake/20201101/mk/libnames.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/libnames.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/libnames.mk (revision 367461) @@ -0,0 +1,22 @@ +# $Id: libnames.mk,v 1.9 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2007-2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +DLIBEXT ?= .a +DSHLIBEXT ?= .so + +.-include +.-include +.-include +.-include Index: vendor/NetBSD/bmake/20201101/mk/libs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/libs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/libs.mk (revision 367461) @@ -0,0 +1,99 @@ +# $Id: libs.mk,v 1.6 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2006, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.MAIN: all + +.if defined(LIBS) + +# In meta mode, we can capture dependenices for _one_ of the progs. +# if makefile doesn't nominate one, we use the first. +.ifndef UPDATE_DEPENDFILE_LIB +UPDATE_DEPENDFILE_LIB = ${LIBS:[1]} +.export UPDATE_DEPENDFILE_LIB +.endif + +.ifndef LIB +# They may have asked us to build just one +.for t in ${LIBS:R:T:S,^lib,,} +.if make(lib$t) +LIB?= $t +lib$t: all +.endif +.endfor +.endif + +.if defined(LIB) +# just one of many +LIB_VARS += \ + LIBDIR \ + CFLAGS \ + COPTS \ + CPPFLAGS \ + CXXFLAGS \ + DPADD \ + DPLIBS \ + LDADD \ + LDFLAGS \ + MAN \ + SRCS + +.for v in ${LIB_VARS:O:u} +.if defined(${v}.${LIB}) || defined(${v}_${LIB}) +$v += ${${v}_${LIB}:U${${v}.${LIB}}} +.endif +.endfor + +# for meta mode, there can be only one! +.if ${LIB} == ${UPDATE_DEPENDFILE_LIB:Uno} +UPDATE_DEPENDFILE ?= yes +.endif +UPDATE_DEPENDFILE ?= NO + +# ensure that we don't clobber each other's dependencies +DEPENDFILE?= .depend.${LIB} +# lib.mk will do the rest +.else +all: ${LIBS:S,^lib,,:@t@lib$t.a@} .MAKE + +# We cannot capture dependencies for meta mode here +UPDATE_DEPENDFILE = NO +# nor can we safely run in parallel. +.NOTPARALLEL: +.endif +.endif + +# handle being called [bsd.]libs.mk +.include <${.PARSEFILE:S,libs,lib,}> + +.ifndef LIB +# tell libs.mk we might want to install things +LIBS_TARGETS+= cleandepend cleandir cleanobj depend install + +.for b in ${LIBS:R:T:S,^lib,,} +lib$b.a: ${SRCS} ${DPADD} ${SRCS_lib$b} ${DPADD_lib$b} + (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$b -DWITHOUT_META_STATS) + +.for t in ${LIBS_TARGETS:O:u} +$b.$t: .PHONY .MAKE + (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} LIB=$b ${@:E} -DWITHOUT_META_STATS) +.endfor +.endfor + +.if !defined(WITHOUT_META_STATS) && ${.MAKE.LEVEL} > 0 +.END: _reldir_finish +.ERROR: _reldir_failed +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/links.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/links.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/links.mk (revision 367461) @@ -0,0 +1,80 @@ +# $Id: links.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2005, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# some platforms need something special +LN?= ln +ECHO?= echo + +LINKS?= +SYMLINKS?= + +__SYMLINK_SCRIPT= \ + ${ECHO} "$$t -> $$l"; \ + case `'ls' -l $$t 2> /dev/null` in \ + *"> $$l") ;; \ + *) \ + mkdir -p `dirname $$t`; \ + rm -f $$t; \ + ${LN} -s $$l $$t;; \ + esac + + +__LINK_SCRIPT= \ + ${ECHO} "$$t -> $$l"; \ + mkdir -p `dirname $$t`; \ + rm -f $$t; \ + ${LN} $$l $$t + +_SYMLINKS_SCRIPT= \ + while test $$\# -ge 2; do \ + l=$$1; shift; \ + t=${DESTDIR}$$1; shift; \ + ${__SYMLINK_SCRIPT}; \ + done; :; + +_LINKS_SCRIPT= \ + while test $$\# -ge 2; do \ + l=${DESTDIR}$$1; shift; \ + t=${DESTDIR}$$1; shift; \ + ${__LINK_SCRIPT}; \ + done; :; + +_SYMLINKS_USE: .USE + @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_SYMLINKS_SCRIPT} + +_LINKS_USE: .USE + @set ${$@_LINKS:U${LINKS}}; ${_LINKS_SCRIPT} + + +# sometimes we want to ensure DESTDIR is ignored +_BUILD_SYMLINKS_SCRIPT= \ + while test $$\# -ge 2; do \ + l=$$1; shift; \ + t=$$1; shift; \ + ${__SYMLINK_SCRIPT}; \ + done; :; + +_BUILD_LINKS_SCRIPT= \ + while test $$\# -ge 2; do \ + l=$$1; shift; \ + t=$$1; shift; \ + ${__LINK_SCRIPT}; \ + done; :; + +_BUILD_SYMLINKS_USE: .USE + @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_BUILD_SYMLINKS_SCRIPT} + +_BUILD_LINKS_USE: .USE + @set ${$@_LINKS:U${LINKS}}; ${_BUILD_LINKS_SCRIPT} Index: vendor/NetBSD/bmake/20201101/mk/manifest.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/manifest.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/manifest.mk (revision 367461) @@ -0,0 +1,66 @@ +# $Id: manifest.mk,v 1.3 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2014, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# generate mtree style manifest supported by makefs in FreeBSD + +# input looks like +# MANIFEST= my.mtree +# for each MANIFEST we have a list of dirs +# ${MANIFEST}.DIRS += bin sbin usr/bin ... +# for each dir we have a ${MANIFEST}.SRCS.$dir +# that provides the absolute path to the contents +# ${MANIFEST}.SRCS.bin += ${OBJTOP}/bin/sh/sh +# ${MANIFEST}.SYMLINKS is a list of src target pairs +# for each file/dir there are a number of attributes +# UID GID MODE FLAGS +# which can be set per dir, per file or we use defaults +# eg. +# MODE.sbin = 550 +# MODE.usr/sbin = 550 +# MODE.dirs = 555 +# means that sbin and usr/sbin get 550 all other dirs get 555 +# MODE.usr/bin/passwd = 4555 +# MODE.usr/bin.files = 555 +# MODE.usr/sbin.files = 500 +# means passwd gets 4555 other files in usr/bin get 555 and +# files in usr/sbin get 500 +# STORE defaults to basename of src and target directory +# but we can use +# ${MANIFEST}.SRCS.sbin += ${OBJTOP}/bin/sh-static/sh-static +# STORE.sbin/sh-static = sbin/sh +# +# the above is a little overkill but means we can easily adapt to +# different formats + +UID.dirs ?= 0 +GID.dirs ?= 0 +MODE.dirs ?= 775 +FLAGS.dirs ?= + +UID.files ?= 0 +GID.files ?= 0 +MODE.files ?= 555 + +# a is attribute name d is dirname +M_DIR_ATTR = L:@a@$${$$a.$$d:U$${$$a.dirs}}@ +# as above and s is set to the name we store f as +M_FILE_ATTR = L:@a@$${$$a.$$s:U$${$$a.$$d.files:U$${$$a.files}}}@ + +# this produces the body of the manifest +# there should typically be a header prefixed +_GEN_MTREE_MANIFEST_USE: .USE + @(${${.TARGET}.DIRS:O:u:@d@echo '$d type=dir uid=${UID:${M_DIR_ATTR}} gid=${GID:${M_DIR_ATTR}} mode=${MODE:${M_DIR_ATTR}} ${FLAGS:${M_DIR_ATTR}}';@} \ + ${${.TARGET}.DIRS:O:u:@d@${${.TARGET}.SRCS.$d:O:u:@f@echo '${s::=${STORE.$d/${f:T}:U$d/${f:T}}}$s contents="$f" type=file uid=${UID:${M_FILE_ATTR}} gid=${GID:${M_FILE_ATTR}} mode=${MODE:${M_FILE_ATTR}} ${FLAGS:${M_FILE_ATTR}}';@}@} \ + set ${${.TARGET}.SYMLINKS}; while test $$# -ge 2; do echo "$$2 type=link link=$$1"; shift 2; done) > ${.TARGET} Property changes on: vendor/NetBSD/bmake/20201101/mk/manifest.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/meta.autodep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta.autodep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta.autodep.mk (revision 367461) @@ -0,0 +1,316 @@ +# $Id: meta.autodep.mk,v 1.52 2020/07/18 05:57:57 sjg Exp $ + +# +# @(#) Copyright (c) 2010, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +_this ?= ${.PARSEFILE} +.if !target(__${_this}__) +__${_this}__: .NOTMAIN + +.-include + +PICO?= .pico + +.if defined(SRCS) +# it would be nice to be able to query .SUFFIXES +OBJ_EXTENSIONS+= .o .po .lo ${PICO} + +# explicit dependencies help short-circuit .SUFFIX searches +SRCS_DEP_FILTER+= N*.[hly] +.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}} +.for e in ${OBJ_EXTENSIONS:O:u} +.if !target(${s:T:R}$e) +${s:T:R}$e: $s +.endif +.endfor +.endfor +.endif + +.if make(gendirdeps) +# you are supposed to know what you are doing! +UPDATE_DEPENDFILE = yes +.elif !empty(.TARGETS) && !make(all) +# do not update the *depend* files +# unless we are building the entire directory or the default target. +# NO means don't update .depend - or Makefile.depend* +# no means update .depend but not Makefile.depend* +UPDATE_DEPENDFILE = NO +.elif ${.MAKEFLAGS:M-k} != "" +# it is a bad idea to update anything +UPDATE_DEPENDFILE = NO +.endif + +_CURDIR ?= ${.CURDIR} +_OBJDIR ?= ${.OBJDIR} +_OBJTOP ?= ${OBJTOP} +_OBJROOT ?= ${OBJROOT:U${_OBJTOP}} +_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T} + +.if ${.MAKE.LEVEL} > 0 +# do not allow auto update if we ever built this dir without filemon +NO_FILEMON_COOKIE = .nofilemon +CLEANFILES += ${NO_FILEMON_COOKIE} +.if ${.MAKE.MODE:Uno:Mnofilemon} != "" +UPDATE_DEPENDFILE = NO +all: ${NO_FILEMON_COOKIE} +${NO_FILEMON_COOKIE}: .NOMETA + @echo UPDATE_DEPENDFILE=NO > ${.TARGET} +.elif exists(${NO_FILEMON_COOKIE}) +UPDATE_DEPENDFILE = NO +.warning ${RELDIR} built with nofilemon; UPDATE_DEPENDFILE=NO +.endif +.endif + +.if ${.MAKE.LEVEL} == 0 +UPDATE_DEPENDFILE = NO +.endif +.if !exists(${_DEPENDFILE}) +_bootstrap_dirdeps = yes +.endif +_bootstrap_dirdeps ?= no +UPDATE_DEPENDFILE ?= yes + +.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != "" +.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE} +.endif + +.if !empty(XMAKE_META_FILE) +.if exists(${.OBJDIR}/${XMAKE_META_FILE}) +# we cannot get accurate dependencies from an update build +UPDATE_DEPENDFILE = NO +.else +META_XTRAS += ${XMAKE_META_FILE} +.endif +.endif + +.if ${_bootstrap_dirdeps} == "yes" || exists(${_DEPENDFILE}) +# if it isn't supposed to be touched by us the Makefile should have +# UPDATE_DEPENDFILE = no +WANT_UPDATE_DEPENDFILE ?= yes +.endif + +.if ${WANT_UPDATE_DEPENDFILE:Uno:tl} != "no" +.if ${.MAKE.MODE:Uno:Mmeta*} == "" || ${.MAKE.MODE:Uno:M*read*} != "" +UPDATE_DEPENDFILE = no +.endif + +.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != "" +.info ${_DEPENDFILE:S,${SRCTOP}/,,} update=${UPDATE_DEPENDFILE} +.endif + +.if ${UPDATE_DEPENDFILE:tl} == "yes" +# sometimes we want .meta files generated to aid debugging/error detection +# but do not want to consider them for dependencies +# for example the result of running configure +# just make sure this is not empty +META_FILE_FILTER ?= N.meta +# never consider these +META_FILE_FILTER += Ndirdeps.cache* + +.if !empty(DPADD) +# if we have any non-libs in DPADD, +# they probably need to be paid attention to +.if !empty(DPLIBS) +FORCE_DPADD = ${DPADD:${DPLIBS:${M_ListToSkip}}:${DPADD_LAST:${M_ListToSkip}}} +.else +_nonlibs := ${DPADD:T:Nlib*:N*include} +.if !empty(_nonlibs) +FORCE_DPADD += ${_nonlibs:@x@${DPADD:M*/$x}@} +.endif +.endif +.endif + +.if !make(gendirdeps) +.END: gendirdeps +.endif + +# if we don't have OBJS, then .depend isn't useful +.if !target(.depend) && (!empty(OBJS) || ${.ALLTARGETS:M*.o} != "") +# some makefiles and/or targets contain +# circular dependencies if you dig too deep +# (as meta mode is apt to do) +# so we provide a means of suppressing them. +# the input to the loop below is target: dependency +# with just one dependency per line. +# Also some targets are not really local, or use random names. +# Use local.autodep.mk to provide local additions! +SUPPRESS_DEPEND += \ + ${SB:S,/,_,g}* \ + *:y.tab.c \ + *.c:*.c \ + *.h:*.h + +.NOPATH: .depend +# we use ${.MAKE.META.CREATED} to trigger an update but +# we process using ${.MAKE.META.FILES} +# the double $$ defers initial evaluation +# if necessary, we fake .po dependencies, just so the result +# in Makefile.depend* is stable +# The current objdir may be referred to in various ways +OBJDIR_REFS += ${.OBJDIR} ${.OBJDIR:tA} ${_OBJDIR} ${RELOBJTOP}/${RELDIR} +_depend = .depend +# it would be nice to be able to get .SUFFIXES as ${.SUFFIXES} +# we actually only care about the .SUFFIXES of files that might be +# generated by tools like yacc. +DEPEND_SUFFIXES += .c .h .cpp .hpp .cxx .hxx .cc .hh +.depend: .NOMETA $${.MAKE.META.CREATED} ${_this} + @echo "Updating $@: ${.OODATE:T:[1..8]}" + @egrep -i '^R .*\.(${DEPEND_SUFFIXES:tl:O:u:S,^.,,:ts|})$$' /dev/null ${.MAKE.META.FILES:T:O:u:${META_FILE_FILTER:ts:}:M*o.meta} | \ + sed -e 's, \./, ,${OBJDIR_REFS:O:u:@d@;s, $d/, ,@};/\//d' \ + -e 's,^\([^/][^/]*\).meta...[0-9]* ,\1: ,' | \ + sort -u | \ + while read t d; do \ + case "$$d:" in $$t) continue;; esac; \ + case "$$t$$d" in ${SUPPRESS_DEPEND:U.:O:u:ts|}) continue;; esac; \ + echo $$t $$d; \ + done > $@.${.MAKE.PID} + @case "${.MAKE.META.FILES:T:M*.po.*}" in \ + *.po.*) mv $@.${.MAKE.PID} $@;; \ + *) { cat $@.${.MAKE.PID}; \ + sed 's,\${PICO}:,.o:,;s,\.o:,.po:,' $@.${.MAKE.PID}; } | sort -u > $@; \ + rm -f $@.${.MAKE.PID};; \ + esac +.else +# make sure this exists +.depend: +# do _not_ assume that .depend is in any fit state for us to use +CAT_DEPEND = /dev/null +.if ${.MAKE.LEVEL} > 0 +.export CAT_DEPEND +.endif +_depend = +.endif + +.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != "" +.info ${_DEPENDFILE:S,${SRCTOP}/,,} _depend=${_depend} +.endif + +.if ${UPDATE_DEPENDFILE} == "yes" +gendirdeps: ${_DEPENDFILE} +.endif + +.if !target(${_DEPENDFILE}) +.if ${_bootstrap_dirdeps} == "yes" +# We are boot-strapping a new directory +# Use DPADD to seed DIRDEPS +.if !empty(DPADD) +# anything which matches ${_OBJROOT}* but not ${_OBJTOP}* +# needs to be qualified in DIRDEPS +# The pseudo machine "host" is used for HOST_TARGET +DIRDEPS += \ + ${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \ + ${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:N${STAGE_ROOT:U${_OBJTOP}}/*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u} + +.endif +.endif + +_gendirdeps_mutex = +.if defined(NEED_GENDIRDEPS_MUTEX) +# If a src dir gets built with multiple object dirs, +# we need a mutex. Obviously, this is best avoided. +# Note if .MAKE.DEPENDFILE is common for all ${MACHINE} +# you either need to mutex, or ensure only one machine builds at a time! +# lockf is an example of a suitable tool +LOCKF ?= /usr/bin/lockf +.if exists(${LOCKF}) +GENDIRDEPS_MUTEXER ?= ${LOCKF} -k +.endif +.if empty(GENDIRDEPS_MUTEXER) +.error NEED_GENDIRDEPS_MUTEX defined, but GENDIRDEPS_MUTEXER not set +.else +_gendirdeps_mutex = ${GENDIRDEPS_MUTEXER} ${GENDIRDEPS_MUTEX:U${_CURDIR}/Makefile} +.endif +.endif + +# If we have META_XTRAS we most likely did not create them +# but we need to behave as if we did. +# Avoid adding glob patterns to .MAKE.META.CREATED though. +.MAKE.META.CREATED += ${META_XTRAS:N*\**:O:u} + +.if make(gendirdeps) +META_FILES = *.meta +.elif ${OPTIMIZE_OBJECT_META_FILES:Uno:tl} == "no" +META_FILES = ${.MAKE.META.FILES:T:N.depend*:O:u} +.else +# if we have 1000's of .o.meta, ${PICO}.meta etc we need only look at one set +# it is left as an exercise for the reader to work out what this does +META_FILES = ${.MAKE.META.FILES:T:N.depend*:N*o.meta:O:u} \ + ${.MAKE.META.FILES:T:M*.${.MAKE.META.FILES:M*o.meta:R:E:O:u:[1]}.meta:O:u} +.endif + +.if ${DEBUG_AUTODEP:Uno:@m@${RELDIR:M$m}@} != "" +.info ${_DEPENDFILE:S,${SRCTOP}/,,}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} xtras=${META_XTRAS} +.endif + +.if ${.MAKE.LEVEL} > 0 +.if ${UPDATE_DEPENDFILE} == "yes" +.-include <${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.options> +.endif +.if !empty(GENDIRDEPS_FILTER) +.export GENDIRDEPS_FILTER +.endif +# export to avoid blowing command line limit +META_FILES := ${META_XTRAS:U:O:u} ${META_FILES:U:T:O:u:${META_FILE_FILTER:ts:}} +.export META_FILES +.endif + +# we might have .../ in MAKESYSPATH +_makesyspath:= ${_PARSEDIR} +${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.META.CREATED} + @echo Checking $@: ${.OODATE:T:[1..8]} + @(cd . && ${GENDIRDEPS_ENV} \ + SKIP_GENDIRDEPS='${SKIP_GENDIRDEPS:O:u}' \ + DPADD='${FORCE_DPADD:O:u}' ${_gendirdeps_mutex} \ + MAKESYSPATH=${_makesyspath} \ + ${.MAKE} -f gendirdeps.mk RELDIR=${RELDIR} _DEPENDFILE=${_DEPENDFILE}) + @test -s $@ && touch $@; : +.endif + +.endif +.endif + +.if ${_bootstrap_dirdeps} == "yes" +DIRDEPS+= ${RELDIR}.${TARGET_SPEC:U${MACHINE}} +# make sure this is included at least once +.include +.else +${_DEPENDFILE}: .PRECIOUS +.endif + +CLEANFILES += *.meta filemon.* *.db + +# these make it easy to gather some stats +now_utc = ${%s:L:gmtime} +start_utc := ${now_utc} + +meta_stats= meta=${empty(.MAKE.META.FILES):?0:${.MAKE.META.FILES:[#]}} \ + created=${empty(.MAKE.META.CREATED):?0:${.MAKE.META.CREATED:[#]}} + +#.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}" + +#.ERROR: _reldir_failed +_reldir_failed: .NOMETA + @echo "${TIME_STAMP} Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}" + +.if !defined(WITHOUT_META_STATS) && ${.MAKE.LEVEL} > 0 +.END: _reldir_finish +.ERROR: _reldir_failed +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/meta.stage.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta.stage.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta.stage.mk (revision 367461) @@ -0,0 +1,366 @@ +# $Id: meta.stage.mk,v 1.60 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2011-2017, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.ifndef NO_STAGING + +.if !target(__${.PARSEFILE}__) +# the guard target is defined later + +.-include + +.if ${.MAKE.DEPENDFILE_PREFERENCE:U${.MAKE.DEPENDFILE}:M*.${MACHINE}} != "" +# this is generally safer anyway +_dirdep ?= ${RELDIR}.${TARGET_SPEC:U${MACHINE}} +.else +_dirdep ?= ${RELDIR} +.endif + +CLEANFILES+= .dirdep + +# this allows us to trace dependencies back to their src dir +.dirdep: .NOPATH + @echo '${_dirdep}' > $@ + +.if defined(NO_POSIX_SHELL) || ${type printf:L:sh:Mbuiltin} == "" +_stage_file_basename = `basename $$f` +_stage_target_dirname = `dirname $$t` +.else +_stage_file_basename = $${f\#\#*/} +_stage_target_dirname = $${t%/*} +.endif + +_OBJROOT ?= ${OBJROOT:U${OBJTOP:H}} +.if ${_OBJROOT:M*/} != "" +_objroot ?= ${_OBJROOT:tA}/ +.else +_objroot ?= ${_OBJROOT:tA} +.endif + +# make sure this is global +_STAGED_DIRS ?= +.export _STAGED_DIRS +# add each dir we stage to to _STAGED_DIRS +# and make sure we have absolute paths so that bmake +# will match against .MAKE.META.BAILIWICK +STAGE_DIR_FILTER = tA:@d@$${_STAGED_DIRS::+=$$d}$$d@ +# convert _STAGED_DIRS into suitable filters +GENDIRDEPS_FILTER += Nnot-empty-is-important \ + ${_STAGED_DIRS:O:u:M${OBJTOP}*:S,${OBJTOP}/,N,} \ + ${_STAGED_DIRS:O:u:M${_objroot}*:N${OBJTOP}*:S,${_objroot},,:C,^([^/]+)/(.*),N\2.\1,:S,${HOST_TARGET},.host,} + +LN_CP_SCRIPT = LnCp() { \ + rm -f $$2 2> /dev/null; \ + { [ -z "$$mode" ] && ${LN:Uln} $$1 $$2 2> /dev/null; } || \ + cp -p $$1 $$2; } + +# a staging conflict should cause an error +# a warning is handy when bootstapping different options. +STAGE_CONFLICT?= ERROR +.if ${STAGE_CONFLICT:tl} == "error" +STAGE_CONFLICT_ACTION= exit 1 +.else +STAGE_CONFLICT_ACTION= +.endif + +# it is an error for more than one src dir to try and stage +# the same file +STAGE_DIRDEP_SCRIPT = ${LN_CP_SCRIPT}; StageDirdep() { \ + t=$$1; \ + if [ -s $$t.dirdep ]; then \ + cmp -s .dirdep $$t.dirdep && return; \ + x=`cat $$t.dirdep`; \ + case "${RELDIR}:${_dirdep}" in $${x%.*}:$${x}*) ;; \ + *) echo "${STAGE_CONFLICT}: $$t installed by $$x not ${_dirdep}" >&2; \ + ${STAGE_CONFLICT_ACTION} ;; esac; \ + fi; \ + LnCp .dirdep $$t.dirdep || exit 1; } + +# common logic for staging files +# this all relies on RELDIR being set to a subdir of SRCTOP +# we use ln(1) if we can, else cp(1) +STAGE_FILE_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageFiles() { \ + case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ + dest=$$1; shift; \ + mkdir -p $$dest; \ + [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ + for f in "$$@"; do \ + case "$$f" in */*) t=$$dest/${_stage_file_basename};; *) t=$$dest/$$f;; esac; \ + StageDirdep $$t; \ + LnCp $$f $$t || exit 1; \ + [ -z "$$mode" ] || chmod $$mode $$t; \ + done; :; } + +STAGE_LINKS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageLinks() { \ + case "$$1" in "") return;; --) shift;; -*) ldest= lnf=$$1; shift;; /*) ldest=$$1/;; esac; \ + dest=$$1; shift; \ + mkdir -p $$dest; \ + [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ + while test $$\# -ge 2; do \ + l=$$ldest$$1; shift; \ + t=$$dest/$$1; \ + case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \ + shift; \ + StageDirdep $$t; \ + rm -f $$t 2>/dev/null; \ + ln $$lnf $$l $$t || exit 1; \ + done; :; } + +STAGE_AS_SCRIPT = ${STAGE_DIRDEP_SCRIPT}; StageAs() { \ + case "$$1" in "") return;; -m) mode=$$2; shift 2;; *) mode=;; esac; \ + dest=$$1; shift; \ + mkdir -p $$dest; \ + [ -s .dirdep ] || echo '${_dirdep}' > .dirdep; \ + while test $$\# -ge 2; do \ + s=$$1; shift; \ + t=$$dest/$$1; \ + case "$$1" in */*) mkdir -p ${_stage_target_dirname};; esac; \ + shift; \ + StageDirdep $$t; \ + LnCp $$s $$t || exit 1; \ + [ -z "$$mode" ] || chmod $$mode $$t; \ + done; :; } + +# this is simple, a list of the "staged" files depends on this, +_STAGE_BASENAME_USE: .USE .dirdep ${.TARGET:T} + @${STAGE_FILE_SCRIPT}; StageFiles ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} + +_STAGE_AS_BASENAME_USE: .USE .dirdep ${.TARGET:T} + @${STAGE_AS_SCRIPT}; StageAs ${.TARGET:H:${STAGE_DIR_FILTER}} ${.TARGET:T} ${STAGE_AS_${.TARGET:T}:U${.TARGET:T}} + + +.endif # first time + + +.if !empty(STAGE_INCSDIR) +.if !empty(STAGE_INCS) +stage_incs: ${STAGE_INCS:N*\**} +.endif +.if target(stage_incs) || !empty(.ALLTARGETS:Mstage_includes) +STAGE_TARGETS += stage_incs +STAGE_INCS ?= ${.ALLSRC:N.dirdep:Nstage_*} +stage_includes: stage_incs +stage_incs: .dirdep + @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_INCSDIR:${STAGE_DIR_FILTER}} ${STAGE_INCS} + @touch $@ + +.endif +.endif + +.if !empty(STAGE_LIBDIR) +.if !empty(STAGE_LIBS) +stage_libs: ${STAGE_LIBS:N*\**} +.endif +.if target(stage_libs) +STAGE_TARGETS += stage_libs +STAGE_LIBS ?= ${.ALLSRC:N.dirdep:Nstage_*} +stage_libs: .dirdep + @${STAGE_FILE_SCRIPT}; StageFiles ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${STAGE_LIBS} +.if !defined(NO_SHLIB_LINKS) +.if !empty(SHLIB_LINKS) + @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} \ + ${SHLIB_LINKS:@t@${STAGE_LIBS:T:M$t.*} $t@} +.elif !empty(SHLIB_LINK) && !empty(SHLIB_NAME) + @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_LIBDIR:${STAGE_DIR_FILTER}} ${SHLIB_NAME} ${SHLIB_LINK} +.endif +.endif + @touch $@ +.endif +.endif + +.if !empty(STAGE_DIR) +STAGE_SETS += _default +STAGE_DIR._default = ${STAGE_DIR} +STAGE_LINKS_DIR._default = ${STAGE_LINKS_DIR:U${STAGE_OBJTOP}} +STAGE_SYMLINKS_DIR._default = ${STAGE_SYMLINKS_DIR:U${STAGE_OBJTOP}} +STAGE_FILES._default = ${STAGE_FILES} +STAGE_LINKS._default = ${STAGE_LINKS} +STAGE_SYMLINKS._default = ${STAGE_SYMLINKS} +.endif + +.if !empty(STAGE_SETS) +CLEANFILES += ${STAGE_SETS:@s@stage*$s@} + +# some makefiles need to populate multiple directories +.for s in ${STAGE_SETS:O:u} +.if !empty(STAGE_FILES.$s) +stage_files.$s: ${STAGE_FILES.$s:N*\**} +.endif +.if target(stage_files.$s) || target(stage_files${s:S,^,.,:N._default}) +STAGE_TARGETS += stage_files +STAGE_FILES.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} +.if !target(.stage_files.$s) +.stage_files.$s: +.if $s != "_default" +stage_files: stage_files.$s +stage_files.$s: .dirdep +.else +STAGE_FILES ?= ${.ALLSRC:N.dirdep:Nstage_*} +stage_files: .dirdep +.endif + @${STAGE_FILE_SCRIPT}; StageFiles ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_FILES.$s:O} + @touch $@ +.endif +.endif + +.if !empty(STAGE_LINKS.$s) +stage_links.$s: +.endif +.if target(stage_links.$s) || target(stage_links${s:S,^,.,:N._default}) +STAGE_LINKS_DIR.$s ?= ${STAGE_OBJTOP} +STAGE_TARGETS += stage_links +.if !target(.stage_links.$s) +.stage_links.$s: +.if $s != "_default" +stage_links: stage_links.$s +stage_links.$s: .dirdep +.else +stage_links: .dirdep +.endif + @${STAGE_LINKS_SCRIPT}; StageLinks ${STAGE_LINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_LINKS.$s} + @touch $@ +.endif +.endif + +.if !empty(STAGE_SYMLINKS.$s) +stage_symlinks.$s: +.endif +.if target(stage_symlinks.$s) || target(stage_symlinks${s:S,^,.,:N._default}) +STAGE_SYMLINKS_DIR.$s ?= ${STAGE_OBJTOP} +STAGE_TARGETS += stage_symlinks +.if !target(.stage_symlinks.$s) +.stage_symlinks.$s: +.if $s != "_default" +stage_symlinks: stage_symlinks.$s +stage_symlinks.$s: .dirdep +.else +stage_symlinks: .dirdep +.endif + @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_SYMLINKS_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_SYMLINKS.$s} + @touch $@ +.endif +.endif + +.endfor +.endif + +.if !empty(STAGE_AS_SETS) +CLEANFILES += ${STAGE_AS_SETS:@s@stage*$s@} + +# sometimes things need to be renamed as they are staged +# each ${file} will be staged as ${STAGE_AS_${file:T}} +# one could achieve the same with SYMLINKS +# stage_as_and_symlink makes the original name a symlink to the new name +# it is the same as using stage_as and stage_symlinks but ensures +# both operations happen together +.for s in ${STAGE_AS_SETS:O:u} +.if !empty(STAGE_AS.$s) +stage_as.$s: ${STAGE_AS.$s:N*\**} +.endif +.if target(stage_as.$s) +STAGE_TARGETS += stage_as +STAGE_AS.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} +.if !target(.stage_as.$s) +.stage_as.$s: +stage_as: stage_as.$s +stage_as.$s: .dirdep + @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS.$s:O:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@} + @touch $@ +.endif +.endif + +.if !empty(STAGE_AS_AND_SYMLINK.$s) +stage_as_and_symlink.$s: ${STAGE_AS_AND_SYMLINK.$s:N*\**} +.endif +.if target(stage_as_and_symlink.$s) +STAGE_TARGETS += stage_as_and_symlink +STAGE_AS_AND_SYMLINK.$s ?= ${.ALLSRC:N.dirdep:Nstage_*} +.if !target(.stage_as_and_symlink.$s) +.stage_as_and_symlink.$s: +stage_as_and_symlink: stage_as_and_symlink.$s +stage_as_and_symlink.$s: .dirdep + @${STAGE_AS_SCRIPT}; StageAs ${FLAGS.$@} ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@$f ${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}}@} + @${STAGE_LINKS_SCRIPT}; StageLinks -s ${STAGE_FILES_DIR.$s:U${STAGE_DIR.$s}:${STAGE_DIR_FILTER}} ${STAGE_AS_AND_SYMLINK.$s:O:@f@${STAGE_AS_${f:tA}:U${STAGE_AS_${f:T}:U${f:T}}} $f@} + @touch $@ +.endif +.endif + +.endfor +.endif + +CLEANFILES += ${STAGE_TARGETS} stage_incs stage_includes + +# this lot also only makes sense the first time... +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# stage_*links usually needs to follow any others. +# for non-jobs mode the order here matters +staging: ${STAGE_TARGETS:N*_links} ${STAGE_TARGETS:M*_links} + +.if ${.MAKE.JOBS:U0} > 0 && ${STAGE_TARGETS:U:M*_links} != "" +# the above isn't sufficient +.for t in ${STAGE_TARGETS:N*links:O:u} +.ORDER: $t stage_links +.endfor +.endif + +# generally we want staging to wait until everything else is done +STAGING_WAIT ?= .WAIT + +.if ${.MAKE.LEVEL} > 0 +all: ${STAGING_WAIT} staging +.endif + +.if exists(${.PARSEDIR}/stage-install.sh) && !defined(STAGE_INSTALL) +# this will run install(1) and then followup with .dirdep files. +STAGE_INSTALL := sh ${.PARSEDIR:tA}/stage-install.sh INSTALL="${INSTALL}" OBJDIR=${.OBJDIR:tA} +.endif + +# if ${INSTALL} gets run during 'all' assume it is for staging? +.if ${.TARGETS:Nall} == "" && defined(STAGE_INSTALL) +INSTALL := ${STAGE_INSTALL} +.if target(beforeinstall) +beforeinstall: .dirdep +.endif +.endif +.NOPATH: ${STAGE_FILES} + +.if !empty(STAGE_TARGETS) +# for backwards compat make sure they exist +${STAGE_TARGETS}: + +.NOPATH: ${CLEANFILES} + +MK_STALE_STAGED?= no +.if ${MK_STALE_STAGED} == "yes" +all: stale_staged +# get a list of paths that we have just staged +# get a list of paths that we have previously staged to those same dirs +# anything in the 2nd list but not the first is stale - remove it. +stale_staged: staging .NOMETA + @egrep '^[WL] .*${STAGE_OBJTOP}' /dev/null ${.MAKE.META.FILES:M*stage_*} | \ + sed "/\.dirdep/d;s,.* '*\(${STAGE_OBJTOP}/[^ '][^ ']*\).*,\1," | \ + sort > ${.TARGET}.staged1 + @grep -l '${_dirdep}' /dev/null ${_STAGED_DIRS:M${STAGE_OBJTOP}*:O:u:@d@$d/*.dirdep@} | \ + sed 's,\.dirdep,,' | sort > ${.TARGET}.staged2 + @comm -13 ${.TARGET}.staged1 ${.TARGET}.staged2 > ${.TARGET}.stale + @test ! -s ${.TARGET}.stale || { \ + echo "Removing stale staged files..."; \ + sed 's,.*,& &.dirdep,' ${.TARGET}.stale | xargs rm -f; } + +.endif +.endif +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/meta.subdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta.subdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta.subdir.mk (revision 367461) @@ -0,0 +1,79 @@ +# $Id: meta.subdir.mk,v 1.12 2020/08/19 17:51:53 sjg Exp $ + +# +# @(#) Copyright (c) 2010, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !defined(NO_SUBDIR) && !empty(SUBDIR) +.if make(destroy*) || make(clean*) +.MAKE.MODE = compat +.if !commands(destroy) +.-include +.endif +.elif ${.MAKE.LEVEL} == 0 + +.MAIN: all + +.if !exists(${.CURDIR}/${.MAKE.DEPENDFILE:T}) || make(gendirdeps) +# start with this +DIRDEPS = ${SUBDIR:N.WAIT:O:u:@d@${RELDIR}/$d@} + +.if make(gendirdeps) +.include +.else +# this is the cunning bit +# actually it is probably a bit risky +# since we may pickup subdirs which are not relevant +# the alternative is a walk through the tree though +# which is difficult without a sub-make. + +.if defined(BOOTSTRAP_DEPENDFILES) +_find_name = ${.MAKE.MAKEFILE_PREFERENCE:@m@-o -name $m@:S,^-o,,1} +DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@} +.elif ${.MAKE.DEPENDFILE:E} == ${MACHINE} && defined(ALL_MACHINES) +# we want to find Makefile.depend.* ie for all machines +# and turn the dirs into dir. +_find_name = -name '${.MAKE.DEPENDFILE:T:R}*' +DIRDEPS = ${_subdeps:O:u:${NIgnoreFiles}:@d@${RELDIR}/${d:H}.${d:E}@:S,.${MACHINE}$,,:S,.depend$,,} +.else +# much simpler +_find_name = -name ${.MAKE.DEPENDFILE:T} +.if ${.MAKE.DEPENDFILE:E} == ${MACHINE} +_find_name += -o -name ${.MAKE.DEPENDFILE:T:R} +.endif +DIRDEPS = ${_subdeps:H:O:u:@d@${RELDIR}/$d@} +.endif + +_subdeps != cd ${.CURDIR} && \ + find ${SUBDIR:N.WAIT} -type f \( ${_find_name} \) -print -o \ + -name .svn -prune 2> /dev/null; echo + +.if empty(_subdeps) +DIRDEPS = +.else +# clean up if needed +DIRDEPS := ${DIRDEPS:S,^./,,:S,/./,/,g:${SUBDIRDEPS_FILTER:Uu}} +.endif +# we just dealt with it, if we leave it defined, +# dirdeps.mk will compute some interesting combinations. +.undef ALL_MACHINES + +DEP_RELDIR = ${RELDIR} +.include +.endif +.endif +.else +all: .PHONY +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/meta.sys.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/meta.sys.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/meta.sys.mk (revision 367461) @@ -0,0 +1,167 @@ +# $Id: meta.sys.mk,v 1.38 2020/08/19 17:51:53 sjg Exp $ + +# +# @(#) Copyright (c) 2010-2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# include this if you want to enable meta mode +# for maximum benefit, requires filemon(4) driver. + +.if ${MAKE_VERSION:U0} > 20100901 +.if !target(.ERROR) + +.-include + +# absolute path to what we are reading. +_PARSEDIR = ${.PARSEDIR:tA} + +.if !defined(SYS_MK_DIR) +SYS_MK_DIR := ${_PARSEDIR} +.endif + +META_MODE += meta verbose +.MAKE.MODE ?= ${META_MODE} + +.if ${.MAKE.LEVEL} == 0 +_make_mode := ${.MAKE.MODE} ${META_MODE} +.if ${_make_mode:M*read*} != "" || ${_make_mode:M*nofilemon*} != "" +# tell everyone we are not updating Makefile.depend* +UPDATE_DEPENDFILE = NO +.export UPDATE_DEPENDFILE +.endif +.if ${UPDATE_DEPENDFILE:Uyes:tl} == "no" && !exists(/dev/filemon) +# we should not get upset +META_MODE += nofilemon +.export META_MODE +.endif +.endif + +.if !defined(NO_SILENT) +.if ${MAKE_VERSION} > 20110818 +# only be silent when we have a .meta file +META_MODE += silent=yes +.else +.SILENT: +.endif +.endif + +# we use the pseudo machine "host" for the build host. +# this should be taken care of before we get here +.if ${OBJTOP:Ua} == ${HOST_OBJTOP:Ub} +MACHINE = host +.endif + +.if !defined(MACHINE0) +# it can be handy to know which MACHINE kicked off the build +# for example, if using Makefild.depend for multiple machines, +# allowing only MACHINE0 to update can keep things simple. +MACHINE0 := ${MACHINE} +.export MACHINE0 +.endif + +.if !defined(META2DEPS) +.if defined(PYTHON) && exists(${PYTHON}) +# we prefer the python version of this - it is much faster +META2DEPS ?= ${.PARSEDIR}/meta2deps.py +.else +META2DEPS ?= ${.PARSEDIR}/meta2deps.sh +.endif +META2DEPS := ${META2DEPS} +.export META2DEPS +.endif + +MAKE_PRINT_VAR_ON_ERROR += \ + .ERROR_TARGET \ + .ERROR_META_FILE \ + .MAKE.LEVEL \ + MAKEFILE \ + .MAKE.MODE + +.if !defined(SB) && defined(SRCTOP) +SB = ${SRCTOP:H} +.endif +ERROR_LOGDIR ?= ${SB}/error +meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log + +# we are not interested in make telling us a failure happened elsewhere +.ERROR: _metaError +_metaError: .NOMETA .NOTMAIN + -@[ "${.ERROR_META_FILE}" ] && { \ + grep -q 'failure has been detected in another branch' ${.ERROR_META_FILE} && exit 0; \ + mkdir -p ${meta_error_log:H}; \ + cp ${.ERROR_META_FILE} ${meta_error_log}; \ + echo "ERROR: log ${meta_error_log}" >&2; }; : + +.endif + +# Are we, after all, in meta mode? +.if ${.MAKE.MODE:Uno:Mmeta*} != "" +MKDEP_MK = meta.autodep.mk + +.if ${.MAKE.MAKEFILES:M*sys.dependfile.mk} == "" +# this does all the smarts of setting .MAKE.DEPENDFILE +.-include +# check if we got anything sane +.if ${.MAKE.DEPENDFILE} == ".depend" +.undef .MAKE.DEPENDFILE +.endif +.MAKE.DEPENDFILE ?= Makefile.depend +.endif + +# we can afford to use cookies to prevent some targets +# re-running needlessly +META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}} +META_NOPHONY= +META_NOECHO= : + +# some targets involve old pre-built targets +# ignore mtime of shell +# and mtime of makefiles does not matter in meta mode +.MAKE.META.IGNORE_PATHS += \ + ${MAKEFILE} \ + ${MAKE_SHELL} \ + ${SHELL} \ + ${SYS_MK_DIR} \ + + +.if ${UPDATE_DEPENDFILE:Uyes:tl} != "no" +.if ${.MAKEFLAGS:Uno:M-k} != "" +# make this more obvious +.warning Setting UPDATE_DEPENDFILE=NO due to -k +UPDATE_DEPENDFILE= NO +.export UPDATE_DEPENDFILE +.elif !exists(/dev/filemon) +.error ${.newline}ERROR: The filemon module (/dev/filemon) is not loaded. +.endif +.endif + +.if ${.MAKE.LEVEL} == 0 +# make sure dirdeps target exists and do it first +all: dirdeps .WAIT +dirdeps: +.NOPATH: dirdeps + +.if defined(ALL_MACHINES) +# the first .MAIN: is what counts +# by default dirdeps is all we want at level0 +.MAIN: dirdeps +.endif + +.endif +.else +META_COOKIE_TOUCH= +# some targets need to be .PHONY in non-meta mode +META_NOPHONY= .PHONY +META_NOECHO= echo +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/mk-files.txt =================================================================== --- vendor/NetBSD/bmake/20201101/mk/mk-files.txt (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/mk-files.txt (revision 367461) @@ -0,0 +1,500 @@ +mk-files +******** + +The term ``mk-files`` refers to a collection of ``*.mk`` files. + +You need bmake_ or a *recent* NetBSD_ make. +If in doubt use bmake_. + +Introduction +============ + +Many years ago, when building large software projects, I used GNU make +(or my own patched version of it), and had developed a set of macros +to simplify developing complex build trees. + +Since the early 90's my main development machines, run BSD +(NetBSD_ to be precise, and more recently FreeBSD), and the BSD source +tree is good example of a large software project. +It quickly became clear that ``/usr/share/mk/*.mk`` were a great +model, but at the time were quite tightly linked to building the BSD tree. + +Much as I liked using NetBSD, my customers were more likely to be +using SunOS, HP-UX etc, so I started on bmake_ and a portable collection +of mk-files (mk.tar.gz_). NetBSD provided much of the original structure. + +Since then I've added a lot of features to NetBSD's make and hence to +bmake which is kept closely in sync. The mk-files however have +diverged quite a bit, though ideas are still picked up from NetBSD +and FreeBSD. + +Basics +------ + +The BSD build model is very simple. A directory produces one +component, which is generally either a library or a program. +Library makefiles include ``lib.mk`` and programs include ``prog.mk`` +and they *do the right thing*. + +A simple library makefile might look like:: + + LIB = sig + + SRCS = \ + sigaction.c \ + sigcompat.c \ + sighdl.c + + .include + +a simple program makefile:: + + PROG = cat + + SRCS = cat.c + + .include + +in such cases even the ``SRCS`` line is unnecessary as ``prog.mk`` +will default it to ``${PROG}.c``. + +It is the sensible use of defaults and the plethora of macro modifiers +provided by bmake_ that allow simple makefiles such as the above to +*just work* on many different systems. + + +mk-files +======== + +This section provides a brief description of some of the ``*.mk`` +files. + +sys.mk +------ + +When bmake starts, it looks for ``sys.mk`` and reads it before doing +anything else. Thus, this is the place to setup the environment for +everyone else. + +In this distribution, ``sys.mk`` avoids doing anything platform dependent. +It is quite short, and includes a number of other files (which may or +may not exists) + +sys.env.mk + If it exists, is expected to do things like conditioning the + environment. Since it will only be included by the initial + instance of bmake, it should ``.export`` anything that + sub-makes might need. + +examples/sys.clean-env.mk + An example of how to clean the environment. + See the file for all the details:: + + .if ${MAKE_VERSION} >= 20100606 && ${.MAKE.LEVEL} == 0 + # we save any env var that starts with these + MAKE_SAVE_ENV_PREFIX += SB MK MAKE MACHINE NEED_ CCACHE DISTCC USE_ SSH + MAKE_SAVE_ENV_VARS += \ + PATH HOME USER LOGNAME \ + SRCTOP OBJTOP OBJROOT \ + ${_env_vars} + + _env_vars != env | egrep '^(${MAKE_SAVE_ENV_PREFIX:ts|})' | sed 's,=.*,,'; echo + _export_list = + .for v in ${MAKE_SAVE_ENV_VARS:O:u} + .if !empty($v) + _export_list += $v + $v := ${$v} + .endif + .endfor + # now clobber the environment + .unexport-env + + # list of vars that we handle specially below + _tricky_env_vars = MAKEOBJDIR + # export our selection - sans tricky ones + .export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}} + + # this next bit may need tweaking + .if defined(MAKEOBJDIR) + srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}} + objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}} + # we'll take care of MACHINE below + objtop := ${OBJTOP:U${objroot}${MACHINE}} + .if !empty(objtop) + # we would normally want something like (/bin/sh): + # MAKEOBJDIR="\${.CURDIR:S,${SRCTOP},${OBJROOT}\${MACHINE},}" + # the $$ below is how we achieve the same result here. + # since everything saved from the environment above + # has run through := we need to compensate for ${MACHINE} + MAKEOBJDIR = $${.CURDIR:S,${srctop},${objtop:S,${MACHINE},\${MACHINE},},} + + # export these as-is, and do not track... + .export-env ${_tricky_env_vars} + # now evaluate for ourselves + .for v in ${_tricky_env_vars} + $v := ${$v} + .endfor + + .endif + .endif + .endif + + +host-target.mk + Is used to set macros like ``HOST_TARGET``, ``HOST_OS`` and + ``host_os`` which are used to find the next step. + +sys/\*.mk + Platform specific additions, such as ``Darwin.mk`` or ``SunOS.mk`` + set things like ``HOST_LIBEXT = .dylib`` for Darwin or + ``SHLIB_FULLVERSION = ${SHLIB_MAJOR}`` for SunOS 5. + If there is no OS specific file, ``sys/Generic.mk`` is used. + +local.sys.mk + Any ``local.*.mk`` file is not part of the distribution. + This provides a hook for sites to do extra setup without + having to edit the distributed files. + + +The above arrangement makes it easy for the mk files to be part of a +src tree on an NFS volume and to allow building on multiple platforms. + +lib.mk +------ + +This file is used to build a number of different libraries from the +same SRCS. + +lib${LIB}.a + An archive lib of ``.o`` files, this is the default + +lib${LIB}_p.a + A profiled lib of ``.po`` files. + Still an archive lib, but all the objects are built with + profiling in mind - hence the different extension. + It is skipped if ``MKPROFILE`` is "no". + +lib${LIB}_pic.a + An archive of ``.so`` objects compiled for relocation. + On NetBSD this is the input to ``lib${LIB}.${LD_so}``, it is + skipped if ``MKPICLIB`` is "no". + +lib${LIB}.${LD_so} + A shared library. The value of ``LD_so`` is very platform + specific. For example:: + + # SunOS 5 and most other ELF systems + libsslfd.so.1 + + # Darwin + libsslfd.1.dylib + + This library will only be built if ``SHLIB_MAJOR`` has + a value, and ``MKPIC`` is not set to "no". + +There is a lot of platform specific tweaking in ``lib.mk``, largely the +result of the original distributions trying to avoid interfering with +the system's ``sys.mk``. + +libnames.mk +----------- + +This is included by both ``prog.mk`` and ``lib.mk`` and tries to +include ``*.libnames.mk`` of which: + +local.libnames.mk + does not exist unless you create it. It is a handy way for you + to customize without touching the distributed files. + For example, on a test machine I needed to build openssl but + not install it, so put the following in ``local.libnames.mk``:: + + .if ${host_os} == "sunos" + LIBCRYPTO = ${OBJTOP}/openssl/lib/crypto/libcrypto${DLIBEXT} + LIBSSL = ${OBJTOP}/openssl/lib/ssl/libssl${DLIBEXT} + INCLUDES_libcrypto = -I${OBJ_libcrypto} + .endif + + The makefile created an openssl dir in ``${OBJ_libcrypto}`` to + gather all the headers. dpadd.mk_ did the rest. + +host.libnames.mk + contains logic to find any libs named in ``HOST_LIBS`` in + ``HOST_LIBDIRS``. + +Each file above gets an opportunity to define things like:: + + LIBSSLFD ?= ${OBJTOP}/ssl/lib/sslfd/libsslfd${DLIBEXT} + INCLUDES_libsslfd = -I${SRC_libsslfd}/h -I${OBJ_libslfd} + +these are used by dpadd.mk_ and will be explained below. + +dpadd.mk +-------- + +This file looks like line noise, and is best considered read-only. +However it provides some very useful functionality, which simplifies the build. + +Makefiles can use the LIB* macros defined via libnames.mk_ or anywhere +else in various ways:: + + # indicate that we need to include headers from LIBCRYPTO + # this would result in ${INCLUDES_libcrypto} being added to CFLAGS. + SRC_LIBS += ${LIBCRYPTO} + + # indicate that libsslfd must be built already. + # it also has the same effect as SRC_LIBS + DPADD += ${LIBSSLFD} + + # indicate that not only must libsslfd be built, + # but that we need to link with it. + # this is almost exactly equivalent to + # DPADD += ${LIBSSLFD} + # LDADD += -L${LIBSSLFD:H} -lsslfd + # and mostly serves to ensure that DPADD and LDADD are in sync. + DPLIBS += ${LIBSSLFD} + +Any library (referenced by its full path) in any of the above, is +added to ``DPMAGIC_LIBS`` with the following results, for each lib *foo*. + +SRC_libfoo + Is set to indicate where the src for libfoo is. + By default it is derived from ``LIBFOO`` by replacing + ``${OBJTOP}`` with ``${SRCTOP}``. + +OBJ_libfoo + Not very exciting, is just the dir where libfoo lives. + +INCLUDES_libfoo + What to add to ``CFLAGS`` to find the public headers. + The default varies. If ``${SRC_libfoo}/h`` exists, it is assumed + to be the home of all public headers and thus the default is + ``-I${SRC_libfoo}/h`` + + Otherwise we make no assumptions and the default is + ``-I${SRC_libfoo} -I${OBJ_libfoo}`` + +LDADD_libfoo + This only applies to libs reference via ``DPLIBS``. + The default is ``-lfoo``, ``LDADD_*`` provides a hook to + instantiate other linker flags at the appropriate point + without losing the benfits of ``DPLIBS``. + +prog.mk +------- + +Compiles the specified SRCS and links them and the nominated libraries +into a program. Prog makefiles usually need to list the libraries +that need to be linked. We prefer use of ``DPLIBS`` but the more +traditional ``DPADD`` and ``LDADD`` work just as well. +That is:: + + DPLIBS += ${LIBCRYPTO} + +is equivalent to:: + + DPADD += ${LIBCRYPTO} + LDADD += -lcrypto + +obj.mk +------ + +One of the cool aspects of BSD make, is its support for separating +object files from the src tree. This is also the source of much +confusion to some. + +Traditionally one had to do a separate ``make obj`` pass through the +tree. If ``MKOBJDIRS`` is "auto", we include auto.obj.mk_. + +auto.obj.mk +----------- + +This leverages the ``.OBJDIR`` target introduced some years ago to +NetBSD make, to automatically create the desired object dir. + +subdir.mk +--------- + +This is the traditional means of walking the tree. A makefile sets +``SUBDIR`` to the list of sub-dirs to visit. + +If ``SUBDIR_MUST_EXIST`` is set, missing directories cause an error, +otherwise a warning is issued. If you don't even want the warning, +set ``MISSING_DIR=continue``. + +Traditionally, ``subdir.mk`` prints clues as it visits each subdir:: + + ===> ssl + ===> ssl/lib + ===> ssl/lib/sslfd + +you can suppress that - or enhance it by setting ``ECHO_DIR``:: + + # suppress subdir noise + ECHO_DIR=: + # print time stamps + ECHO_DIR=echo @ `date "+%s [%Y-%m-%d %T] "` + +links.mk +-------- + +Provides rules for processing lists of ``LINKS`` and ``SYMLINKS``. +Each is expected to be a list of ``link`` and ``target`` pairs +(``link`` -> ``target``). + +The logic is generally in a ``_*_SCRIPT`` which is referenced in a +``_*_USE`` (``.USE``) target. + +The ``_BUILD_*`` forms are identical, but do not use ``${DESTDIR}`` +and so are useful for creating symlinks during the build phase. +For example:: + + SYMLINKS += ${.CURDIR}/${MACHINE_ARCH}/include machine + header_links: _BUILD_SYMLINKS_USE + + md.o: header_links + +would create a symlink called ``machine`` in ``${.OBJDIR}`` pointing to +``${.CURDIR}/${MACHINE_ARCH}/include`` before compiling ``md.o`` + + +autoconf.mk +----------- + +Deals with running (or generating) GNU autoconf ``configure`` scripts. + +dep.mk +------ + +Deals with collecting dependencies. Another useful feature of BSD +make is the separation of this sort of information into a ``.depend`` +file. ``MKDEP`` needs to point to a suitable tool (like mkdeps.sh_) + +If ``USE_AUTODEP_MK`` is "yes" includes autodep.mk_ + +autodep.mk +---------- + +Leverages the ``-MD`` feature of recent GCC to collect dependency +information as a side effect of compilation. With this GCC puts +dependency info into a ``.d`` file. + +Unfortunately GCC bases the name of the ``.d`` file on the name of the +input rather than the output file, which causes problems when the same +source is compiled different ways. The latest GCC supports ``-MF`` to +name the ``.d`` file and ``-MT`` to control the name to put as the +dependent. + +Recent bmake allows dependencies for the ``.END`` target (run at the +end if everything was successful), and ``autodep.mk`` uses this to +post process the ``.d`` files into ``.depend``. + +auto.dep.mk +----------- + +A much simpler implementation than autodep.mk_ it uses +``-MF ${.TARGET:T}.d`` +to avoid possible conflicts during parallel builds. +This precludes the use of suffix rules to drive ``make depend``, so +dep.mk_ handles that if specifically requested. + +options.mk +---------- + +Inspired by FreeBSD's ``bsd.own.mk`` more flexible. +FreeBSD now have similar functionality in ``bsd.mkopt.mk``. + +It allows users to express their intent with respect to options +``MK_*`` by setting ``WITH_*`` or ``WITHOUT_*``. + +Note: ``WITHOUT_*`` wins if both are set, and makefiles can set +``NO_*`` to say they cannot handle that option, or even ``MK_*`` if +they really need to. + + +own.mk +------ + +Normally included by ``init.mk`` (included by ``lib.mk`` and +``prog.mk`` etc), sets macros for default ownership etc. + +It includes ``${MAKECONF}`` if it is defined and exists. + +ldorder.mk +---------- + +Leverages ``bmake`` to compute optimal link order for libraries. +This works nicely and makes refactoring a breeze - so long as you +have not (or few) cicular dependencies between libraries. + +man.mk +------ + +Deals with man pages. + +warnings.mk +----------- + +This provides a means of fine grained control over warnings on a per +``${MACHINE}`` or even file basis. + +A makefile sets ``WARNINGS_SET`` to name a list of warnings +and individual ``W_*`` macros can be used to tweak them. +For example:: + + WARNINGS_SET = HIGH + W_unused_sparc = -Wno-unused + +would add all the warnings in ``${HIGH_WARNINGS}`` to CFLAGS, but +on sparc, ``-Wno-unused`` would replace ``-Wunused``. + +You should never need to edit ``warnings.mk``, it will include +``warnings-sets.mk`` if it exists and you use that to make any local +customizations. + +rst2htm.mk +---------- + +Logic to simplify generating HTML (and PDF) documents from ReStructuredText. + +cython.mk +--------- + +Logic to build Python C interface modules using Cython_ + +.. _Cython: http://www.cython.org/ + +Meta mode +========= + +The 20110505 and later versions of ``mk-files`` include a number of +makefiles contributed by Juniper Networks, Inc. +These allow the latest version of bmake_ to run in `meta mode`_ +see `dirdeps.mk`_ + +.. _`dirdeps.mk`: /help/sjg/dirdeps.htm +.. _`meta mode`: bmake-meta-mode.htm + +Install +======= + +You can use the content of mk.tar.gz_ without installing at all. + +The script ``install-mk`` takes care of copying ``*.mk`` into a +destination directory, and unless told not to, create ``bsd.*.mk`` links +for ``lib.mk`` etc. + +If you just want to create the ``bsd.*.mk`` links in the directory +where you unpacked the tar file, you can:: + + ./mk/install-mk ./mk + +------ + +.. _bmake: bmake.htm +.. _NetBSD: http://www.netbsd.org/ +.. _mkdeps.sh: http://www.crufty.net/ftp/pub/sjg/mkdeps.sh +.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz + +:Author: sjg@crufty.net +:Revision: $Id: mk-files.txt,v 1.20 2020/08/19 17:51:53 sjg Exp $ +:Copyright: Crufty.NET Property changes on: vendor/NetBSD/bmake/20201101/mk/mk-files.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/mkopt.sh =================================================================== --- vendor/NetBSD/bmake/20201101/mk/mkopt.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/mkopt.sh (revision 367461) @@ -0,0 +1,104 @@ +#!/bin/sh + +# $Id: mkopt.sh,v 1.13 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2014, 2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# handle WITH[OUT]_* options in a manner compatible with +# options.mk and bsd.mkopt.mk in recent FreeBSD + +# no need to be included more than once +_MKOPT_SH=: +_MKOPT_PREFIX=${_MKOPT_PREFIX:-MK_} + +# +# _mk_opt default OPT +# +# Set MK_$OPT +# +# The semantics are simple, if MK_$OPT has no value +# WITHOUT_$OPT results in MK_$OPT=no +# otherwise WITH_$OPT results in MK_$OPT=yes. +# Note WITHOUT_$OPT overrides WITH_$OPT. +# +# For backwards compatability reasons we treat WITH_$OPT=no +# the same as WITHOUT_$OPT. +# +_mk_opt() { + _d=$1 + _mo=${_MKOPT_PREFIX}$2 _wo=WITHOUT_$2 _wi=WITH_$2 + eval "_mov=\$$_mo _wov=\$$_wo _wiv=\$$_wi" + + case "$_wiv" in + [Nn][Oo]) _wov=no;; + esac + _v=${_mov:-${_wov:+no}} + _v=${_v:-${_wiv:+yes}} + _v=${_v:-$_d} + _opt_list="$_opt_list $_mo" + case "$_v" in + yes|no) ;; # sane + 0|[NnFf]*) _v=no;; # they mean no + 1|[YyTt]*) _v=yes;; # they mean yes + *) _v=$_d;; # ignore bogus value + esac + eval "$_mo=$_v" +} + +# +# _mk_opts default opt ... [default [opt] ...] +# +# see _mk_opts_defaults for example +# +_mk_opts() { + _d=no + for _o in "$@" + do + case "$_o" in + */*) # option is dirname default comes from basename + eval "_d=\$${_MKOPT_PREFIX}${_o#*/}" + _o=${_o%/*} + ;; + yes|no) _d=$_o; continue;; + esac + _mk_opt $_d $_o + done +} + +# handle either options.mk style OPTIONS_DEFAULT_* +# or FreeBSD's new bsd.mkopt.mk style __DEFAULT_*_OPTIONS +_mk_opts_defaults() { + _mk_opts no $OPTIONS_DEFAULT_NO $__DEFAULT_NO_OPTIONS \ + yes $OPTIONS_DEFAULT_YES $__DEFAULT_YES_OPTIONS \ + $OPTIONS_DEFAULT_DEPENDENT $__DEFAULT_DEPENDENT_OPTIONS +} + +case "/$0" in +*/mkopt*) + _list=no + while : + do + case "$1" in + *=*) eval "$1"; shift;; + --no|no) _list="$_list no"; shift;; + --yes|yes) _list="$_list yes"; shift;; + -DWITH*) eval "${1#-D}=1"; shift;; + [A-Z]*) _list="$_list $1"; shift;; + *) break;; + esac + done + _mk_opts $_list + ;; +esac + Property changes on: vendor/NetBSD/bmake/20201101/mk/mkopt.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/obj.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/obj.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/obj.mk (revision 367461) @@ -0,0 +1,113 @@ +# $Id: obj.mk,v 1.16 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 1999-2010, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !target(__${.PARSEFILE:S,bsd.,,}__) +__${.PARSEFILE:S,bsd.,,}__: + +.include + +ECHO_TRACE ?= echo + +.if ${MK_OBJDIRS} == "no" +obj: +objlink: +objwarn: +.else + +# this has to match how make behaves +.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR) +.if defined(MAKEOBJDIRPREFIX) +__objdir:= ${MAKEOBJDIRPREFIX}${.CURDIR} +.else +__objdir:= ${MAKEOBJDIR} +.endif +.else +__objdir= ${__objlink} +.endif + +.if defined(OBJMACHINE) +__objlink= obj.${MACHINE} +.else +__objlink= obj +.endif + +.if ${MK_AUTO_OBJ} == "yes" +.-include "auto.obj.mk" +.endif + +.NOPATH: ${__objdir} +.PHONY: obj + +obj: _SUBDIRUSE + @if test ! -d ${__objdir}/.; then \ + mkdir -p ${__objdir}; \ + if test ! -d ${__objdir}; then \ + mkdir ${__objdir}; exit 1; \ + fi; \ + ${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \ + fi + +.if !target(_SUBDIRUSE) +# this just allows us to be included by ourselves +_SUBDIRUSE: +.endif + +# so we can interact with freebsd makefiles +.if !target(objwarn) +objwarn: +.if ${.OBJDIR} == ${.CURDIR} + @echo "Warning Object directory is ${.CURDIR}" +.elif ${.OBJDIR} != ${__objdir} + @echo "Warning Object directory is ${.OBJDIR} vs. ${__objdir}" +.endif +.endif + +.if !target(objlink) +objlink: +.if ${__objdir:T} != ${__objlink} + @if test -d ${__objdir}/.; then \ + ${RM} -f ${.CURDIR}/${__objlink}; \ + ${LN} -s ${__objdir} ${.CURDIR}/${__objlink}; \ + echo "${__objlink} -> ${__objdir}"; \ + else \ + echo "No ${__objdir} to link to - do a 'make obj'"; \ + fi +.endif +.endif +.endif + +_CURDIR?= ${.CURDIR} +_OBJDIR?= ${.OBJDIR} + +.if !target(print-objdir) +print-objdir: + @echo ${_OBJDIR} +.endif + +.if !target(whereobj) +whereobj: + @echo ${_OBJDIR} +.endif + +.if !target(destroy) +.if ${.CURDIR} != ${.OBJDIR} +destroy: + (cd ${_CURDIR} && rm -rf ${_OBJDIR}) +.else +destroy: clean +.endif +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/options.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/options.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/options.mk (revision 367461) @@ -0,0 +1,82 @@ +# $Id: options.mk,v 1.13 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2012, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# Inspired by FreeBSD bsd.own.mk, but intentionally simpler and more flexible. + +# Options are normally listed in either OPTIONS_DEFAULT_{YES,NO} +# We convert these to ${OPTION}/{yes,no} in OPTIONS_DEFAULT_VALUES. +# We add the OPTIONS_DEFAULT_NO first so they take precedence. +# This allows override of an OPTIONS_DEFAULT_YES by adding it to +# OPTIONS_DEFAULT_NO or adding ${OPTION}/no to OPTIONS_DEFAULT_VALUES. +# An OPTIONS_DEFAULT_NO option can only be overridden by putting +# ${OPTION}/yes in OPTIONS_DEFAULT_VALUES. +# A makefile may set NO_* (or NO*) to indicate it cannot do something. +# User sets WITH_* and WITHOUT_* to indicate what they want. +# We set ${OPTION_PREFIX:UMK_}* which is then all we need care about. +OPTIONS_DEFAULT_VALUES += \ + ${OPTIONS_DEFAULT_NO:O:u:S,$,/no,} \ + ${OPTIONS_DEFAULT_YES:O:u:S,$,/yes,} + +OPTION_PREFIX ?= MK_ + +# NO_* takes precedence +# If both WITH_* and WITHOUT_* are defined, WITHOUT_ wins unless +# DOMINANT_* is set to "yes" +# Otherwise WITH_* and WITHOUT_* override the default. +.for o in ${OPTIONS_DEFAULT_VALUES:M*/*} +.if defined(NO_${o:H}) || defined(NO${o:H}) +# we cannot do it +${OPTION_PREFIX}${o:H} ?= no +.elif defined(WITH_${o:H}) && defined(WITHOUT_${o:H}) +# normally WITHOUT_ wins +DOMINANT_${o:H} ?= no +${OPTION_PREFIX}${o:H} ?= ${DOMINANT_${o:H}} +.elif ${o:T:tl} == "no" +.if defined(WITH_${o:H}) +${OPTION_PREFIX}${o:H} ?= yes +.else +${OPTION_PREFIX}${o:H} ?= no +.endif +.else +.if defined(WITHOUT_${o:H}) +${OPTION_PREFIX}${o:H} ?= no +.else +${OPTION_PREFIX}${o:H} ?= yes +.endif +.endif +.endfor + +# OPTIONS_DEFAULT_DEPENDENT += FOO_UTILS/FOO +# If neither WITH[OUT]_FOO_UTILS is set, (see rules above) +# use the value of ${OPTION_PREFIX}FOO +.for o in ${OPTIONS_DEFAULT_DEPENDENT:M*/*:O:u} +.if defined(NO_${o:H}) || defined(NO${o:H}) +# we cannot do it +${OPTION_PREFIX}${o:H} ?= no +.elif defined(WITH_${o:H}) && defined(WITHOUT_${o:H}) +# normally WITHOUT_ wins +DOMINANT_${o:H} ?= no +${OPTION_PREFIX}${o:H} ?= ${DOMINANT_${o:H}} +.elif defined(WITH_${o:H}) +${OPTION_PREFIX}${o:H} ?= yes +.elif defined(WITHOUT_${o:H}) +${OPTION_PREFIX}${o:H} ?= no +.else +${OPTION_PREFIX}${o:H} ?= ${${OPTION_PREFIX}${o:T}} +.endif +.endfor +.undef OPTIONS_DEFAULT_VALUES +.undef OPTIONS_DEFAULT_NO +.undef OPTIONS_DEFAULT_YES Index: vendor/NetBSD/bmake/20201101/mk/own.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/own.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/own.mk (revision 367461) @@ -0,0 +1,271 @@ +# $Id: own.mk,v 1.41 2020/08/19 17:51:53 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.if !target(__init.mk__) +.include "init.mk" +.endif + +.if !defined(NOMAKECONF) && !defined(NO_MAKECONF) +MAKECONF?= /etc/mk.conf +.-include "${MAKECONF}" +.endif + +.include + +TARGET_OSNAME?= ${_HOST_OSNAME} +TARGET_OSREL?= ${_HOST_OSREL} +TARGET_OSTYPE?= ${HOST_OSTYPE} +TARGET_HOST?= ${HOST_TARGET} + +# these may or may not exist +.-include <${TARGET_HOST}.mk> +.-include + +RM?= rm +LN?= ln +INSTALL?= install + +prefix?= /usr +.if exists(${prefix}/lib) +libprefix?= ${prefix} +.else +libprefix?= /usr +.endif + +# FreeBSD at least does not set this +MACHINE_ARCH?= ${MACHINE} +# we need to make sure these are defined too in case sys.mk fails to. +COMPILE.s?= ${CC} ${AFLAGS} -c +LINK.s?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp +LINK.S?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.c?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} +CXXFLAGS?= ${CFLAGS} +COMPILE.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.f?= ${FC} ${FFLAGS} -c +LINK.f?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} +LEX.l?= ${LEX} ${LFLAGS} +COMPILE.p?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} +YACC.y?= ${YACC} ${YFLAGS} + +# for suffix rules +IMPFLAGS?= ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} ${CPPFLAGS.${.IMPSRC:T}} +.for s in .c .cc +COMPILE.$s += ${IMPFLAGS} +LINK.$s += ${IMPFLAGS} +.endfor + +PRINT.VAR.MAKE = MAKESYSPATH=${MAKESYSPATH:U${.PARSEDIR}} ${.MAKE} +.if empty(.MAKEFLAGS:M-V*) +.if defined(MAKEOBJDIRPREFIX) || defined(MAKEOBJDIR) +PRINTOBJDIR= ${PRINT.VAR.MAKE} -r -V .OBJDIR -f /dev/null xxx +.else +PRINTOBJDIR= ${PRINT.VAR.MAKE} -V .OBJDIR +.endif +.else +PRINTOBJDIR= echo # prevent infinite recursion +.endif + +# we really like to have SRCTOP and OBJTOP defined... +.if !defined(SRCTOP) || !defined(OBJTOP) +.-include +.endif + +.if !defined(SRCTOP) || !defined(OBJTOP) +# dpadd.mk is rather pointless without these +OPTIONS_DEFAULT_NO+= DPADD_MK +.endif + +# process options +OPTIONS_DEFAULT_NO+= \ + INSTALL_AS_USER \ + GPROF \ + PROG_LDORDER_MK \ + LIBTOOL \ + LINT \ + +OPTIONS_DEFAULT_YES+= \ + ARCHIVE \ + AUTODEP \ + CRYPTO \ + DOC \ + DPADD_MK \ + GDB \ + KERBEROS \ + LINKLIB \ + MAN \ + NLS \ + OBJ \ + PIC \ + SHARE \ + SKEY \ + YP \ + +OPTIONS_DEFAULT_DEPENDENT+= \ + CATPAGES/MAN \ + LDORDER_MK/PROG_LDORDER_MK \ + OBJDIRS/OBJ \ + PICINSTALL/LINKLIB \ + PICLIB/PIC \ + PROFILE/LINKLIB \ + STAGING_PROG/STAGING \ + +.include + +.if ${MK_INSTALL_AS_USER} == "yes" +# We ignore this if user is root. +_uid!= id -u +.if ${_uid} != 0 +.if !defined(USERGRP) +USERGRP!= id -g +.export USERGRP +.endif +.for x in BIN CONF DOC INC INFO FILES KMOD LIB MAN NLS PROG SHARE +$xOWN= ${USER} +$xGRP= ${USERGRP} +$x_INSTALL_OWN= +.endfor +.endif +.endif + +# override this in sys.mk +ROOT_GROUP?= wheel +BINGRP?= ${ROOT_GROUP} +BINOWN?= root +BINMODE?= 555 +NONBINMODE?= 444 +DIRMODE?= 755 + +INCLUDEDIR?= ${prefix}/include +INCDIR?= ${INCLUDEDIR} + +# Define MANZ to have the man pages compressed (gzip) +#MANZ= 1 + +MANTARGET?= cat +MANDIR?= ${prefix}/share/man/${MANTARGET} +MANGRP?= ${BINGRP} +MANOWN?= ${BINOWN} +MANMODE?= ${NONBINMODE} + +INCLUDEDIR?= ${libprefix}/include +LIBDIR?= ${libprefix}/lib +SHLIBDIR?= ${libprefix}/lib +.if ${USE_SHLIBDIR:Uno} == "yes" +_LIBSODIR?= ${SHLIBDIR} +.else +_LIBSODIR?= ${LIBDIR} +.endif +# this is where ld.*so lives +SHLINKDIR?= /usr/libexec +LINTLIBDIR?= ${libprefix}/libdata/lint +LIBGRP?= ${BINGRP} +LIBOWN?= ${BINOWN} +LIBMODE?= ${NONBINMODE} + +DOCDIR?= ${prefix}/share/doc +DOCGRP?= ${BINGRP} +DOCOWN?= ${BINOWN} +DOCMODE?= ${NONBINMODE} + +NLSDIR?= ${prefix}/share/nls +NLSGRP?= ${BINGRP} +NLSOWN?= ${BINOWN} +NLSMODE?= ${NONBINMODE} + +KMODDIR?= ${prefix}/lkm +KMODGRP?= ${BINGRP} +KMODOWN?= ${BINOWN} +KMODMODE?= ${NONBINMODE} + +SHAREGRP?= ${BINGRP} +SHAREOWN?= ${BINOWN} +SHAREMODE?= ${NONBINMODE} + +COPY?= -c +STRIP_FLAG?= -s + +.if ${TARGET_OSNAME} == "NetBSD" +.if exists(/usr/libexec/ld.elf_so) +OBJECT_FMT=ELF +.endif +OBJECT_FMT?=a.out +.endif +# sys.mk should set something appropriate if need be. +OBJECT_FMT?=ELF + +.if (${_HOST_OSNAME} == "FreeBSD") +CFLAGS+= ${CPPFLAGS} +.endif + +# allow for per target flags +# apply the :T:R first, so the more specific :T can override if needed +CPPFLAGS += ${CPPFLAGS_${.TARGET:T:R}} ${CPPFLAGS_${.TARGET:T}} +CFLAGS += ${CFLAGS_${.TARGET:T:R}} ${CFLAGS_${.TARGET:T}} + +# Define SYS_INCLUDE to indicate whether you want symbolic links to the system +# source (``symlinks''), or a separate copy (``copies''); (latter useful +# in environments where it's not possible to keep /sys publicly readable) +#SYS_INCLUDE= symlinks + +# don't try to generate PIC versions of libraries on machines +# which don't support PIC. +.if (${MACHINE_ARCH} == "vax") || \ + ((${MACHINE_ARCH} == "mips") && defined(STATIC_TOOLCHAIN)) || \ + ((${MACHINE_ARCH} == "alpha") && defined(ECOFF_TOOLCHAIN)) +MK_PIC=no +.endif + +# No lint, for now. +NOLINT= + + +.if ${MK_LINKLIB} == "no" +MK_PICINSTALL= no +MK_PROFILE= no +.endif + +.if ${MK_MAN} == "no" +MK_CATPAGES= no +.endif + +.if ${MK_OBJ} == "no" +MK_OBJDIRS= no +MK_AUTO_OBJ= no +.endif + +.if ${MK_SHARE} == "no" +MK_CATPAGES= no +MK_DOC= no +MK_INFO= no +MK_MAN= no +MK_NLS= no +.endif + +# :U incase not using our sys.mk +.if ${MK_META_MODE:Uno} == "yes" +# should all be set by sys.mk if not default +TARGET_SPEC_VARS ?= MACHINE +.if ${TARGET_SPEC_VARS:[#]} > 1 +TARGET_SPEC_VARS_REV := ${TARGET_SPEC_VARS:[-1..1]} +.else +TARGET_SPEC_VARS_REV = ${TARGET_SPEC_VARS} +.endif +.if ${MK_STAGING} == "yes" +STAGE_ROOT?= ${OBJROOT}/stage +STAGE_OBJTOP?= ${STAGE_ROOT}/${TARGET_SPEC_VARS_REV:ts/} +.endif +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/prlist.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/prlist.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/prlist.mk (revision 367461) @@ -0,0 +1,36 @@ +# $Id: prlist.mk,v 1.4 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2006, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# this needs to be included after all the lists it will process +# are defined - which is why it is a separate file. +# Usage looks like: +# MAKEFLAGS= ${.MAKE} -f ${MAKEFILE} prlist.SOMETHING_HUGE | xargs whatever +# +.if make(prlist.*) +.for t in ${.TARGETS:Mprlist.*:E} +.if empty($t) +prlist.$t: +.else +prlist.$t: ${$t:O:u:S,^,prlist-,} +${$t:O:u:S,^,prlist-,}: .PHONY + @echo "${.TARGET:S,prlist-,,}" +.endif +.endfor +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/prog.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/prog.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/prog.mk (revision 367461) @@ -0,0 +1,251 @@ +# $Id: prog.mk,v 1.36 2020/08/19 17:51:53 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.include + +# FreeBSD at least expects MAN8 etc. +.if defined(MAN) && !empty(MAN) +_sect:=${MAN:E} +MAN${_sect}=${MAN} +.endif + +.SUFFIXES: .out .o .c .cc .C .y .l .s .8 .7 .6 .5 .4 .3 .2 .1 .0 + +CFLAGS+= ${COPTS} + +.if ${TARGET_OSNAME} == "NetBSD" +.if ${MACHINE_ARCH} == "sparc64" +CFLAGS+= -mcmodel=medlow +.endif + +# ELF platforms depend on crtbegin.o and crtend.o +.if ${OBJECT_FMT} == "ELF" +.ifndef LIBCRTBEGIN +LIBCRTBEGIN= ${DESTDIR}/usr/lib/crtbegin.o +.MADE: ${LIBCRTBEGIN} +.endif +.ifndef LIBCRTEND +LIBCRTEND= ${DESTDIR}/usr/lib/crtend.o +.MADE: ${LIBCRTEND} +.endif +_SHLINKER= ${SHLINKDIR}/ld.elf_so +.else +LIBCRTBEGIN?= +LIBCRTEND?= +_SHLINKER= ${SHLINKDIR}/ld.so +.endif + +.ifndef LIBCRT0 +LIBCRT0= ${DESTDIR}/usr/lib/crt0.o +.MADE: ${LIBCRT0} +.endif +.endif # NetBSD + +# here is where you can define what LIB* are +.-include +.if ${MK_DPADD_MK} == "yes" +# lots of cool magic, but might not suit everyone. +.include +.endif + +.if ${MK_GPROF} == "yes" +CFLAGS+= ${CC_PG} ${PROFFLAGS} +LDADD+= ${CC_PG} +.if ${MK_DPADD_MK} == "no" +LDADD_LIBC_P?= -lc_p +LDADD_LAST+= ${LDADD_LIBC_P} +.endif +.endif + +.if defined(SHAREDSTRINGS) +CLEANFILES+=strings +.c.o: + ${CC} -E ${CFLAGS} ${.IMPSRC} | xstr -c - + @${CC} ${CFLAGS} -c x.c -o ${.TARGET} + @rm -f x.c + +${CXX_SUFFIXES:%=%.o}: + ${CXX} -E ${CXXFLAGS} ${.IMPSRC} | xstr -c - + @mv -f x.c x.cc + @${CXX} ${CXXFLAGS} -c x.cc -o ${.TARGET} + @rm -f x.cc +.endif + + +.if defined(PROG) +BINDIR ?= ${prefix}/bin + +SRCS?= ${PROG}.c +.for s in ${SRCS:N*.h:N*.sh:M*/*} +${.o .po .lo:L:@o@${s:T:R}$o@}: $s +.endfor +.if !empty(SRCS:N*.h:N*.sh) +OBJS+= ${SRCS:T:N*.h:N*.sh:R:S/$/.o/g} +LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln} +.endif + +.if defined(OBJS) && !empty(OBJS) +.NOPATH: ${OBJS} ${PROG} ${SRCS:M*.[ly]:C/\..$/.c/} ${YHEADER:D${SRCS:M*.y:.y=.h}} + +# this is known to work for NetBSD 1.6 and FreeBSD 4.2 +.if ${TARGET_OSNAME} == "NetBSD" || ${TARGET_OSNAME} == "FreeBSD" +_PROGLDOPTS= +.if ${SHLINKDIR} != "/usr/libexec" # XXX: change or remove if ld.so moves +_PROGLDOPTS+= -Wl,-dynamic-linker=${_SHLINKER} +.endif +.if defined(LIBDIR) && ${SHLIBDIR} != ${LIBDIR} +_PROGLDOPTS+= -Wl,-rpath-link,${DESTDIR}${SHLIBDIR}:${DESTDIR}/usr/lib \ + -L${DESTDIR}${SHLIBDIR} +.endif +_PROGLDOPTS+= -Wl,-rpath,${SHLIBDIR}:/usr/lib + +.if defined(PROG_CXX) +_CCLINK= ${CXX} +_SUPCXX= -lstdc++ -lm +.endif +.endif # NetBSD + +_CCLINK?= ${CC} + +.if ${MK_PROG_LDORDER_MK} != "no" +${PROG}: ldorder + +.include +.endif + +.if defined(DESTDIR) && exists(${LIBCRT0}) && ${LIBCRT0} != "/dev/null" + +${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD} + ${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} -nostdlib ${_PROGLDOPTS} -L${DESTDIR}/usr/lib ${LIBCRT0} ${LIBCRTBEGIN} ${OBJS} ${LDADD_LDORDER} ${LDADD} -L${DESTDIR}/usr/lib ${_SUPCXX} -lgcc -lc -lgcc ${LIBCRTEND} + +.else + +${PROG}: ${LIBCRT0} ${OBJS} ${LIBC} ${DPADD} + ${_CCLINK} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} ${_PROGLDOPTS} ${OBJS} ${LDADD_LDORDER} ${LDADD} + +.endif # defined(DESTDIR) +.endif # defined(OBJS) && !empty(OBJS) + +.if !defined(MAN) +MAN= ${PROG}.1 +.endif # !defined(MAN) +.endif # defined(PROG) + +.if !defined(_SKIP_BUILD) +realbuild: ${PROG} +.endif + +all: _SUBDIRUSE + +.if !target(clean) +cleanprog: + rm -f a.out [Ee]rrs mklog core *.core \ + ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES} + +clean: _SUBDIRUSE cleanprog +cleandir: _SUBDIRUSE cleanprog +.else +cleandir: _SUBDIRUSE clean +.endif + +.if defined(SRCS) && (!defined(MKDEP) || ${MKDEP} != autodep) +afterdepend: .depend + @(TMP=/tmp/_depend$$$$; \ + sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.ln:/' \ + < .depend > $$TMP; \ + mv $$TMP .depend) +.endif + +.if !target(install) +.if !target(beforeinstall) +beforeinstall: +.endif +.if !target(afterinstall) +afterinstall: +.endif + +.if !empty(BINOWN) +PROG_INSTALL_OWN ?= -o ${BINOWN} -g ${BINGRP} +.endif + +.if !target(realinstall) +realinstall: proginstall +.endif +.if !target(proginstall) +proginstall: +.if defined(PROG) + [ -d ${DESTDIR}${BINDIR} ] || \ + ${INSTALL} -d ${PROG_INSTALL_OWN} -m 775 ${DESTDIR}${BINDIR} + ${INSTALL} ${COPY} ${STRIP_FLAG} ${PROG_INSTALL_OWN} -m ${BINMODE} \ + ${PROG} ${DESTDIR}${BINDIR}/${PROG_NAME} +.endif +.if defined(HIDEGAME) + (cd ${DESTDIR}/usr/games; rm -f ${PROG}; ln -s dm ${PROG}) +.endif +.endif + +.include + +install: maninstall install_links _SUBDIRUSE + +install_links: +.if !empty(SYMLINKS) + @set ${SYMLINKS}; ${_SYMLINKS_SCRIPT} +.endif +.if !empty(LINKS) + @set ${LINKS}; ${_LINKS_SCRIPT} +.endif + +maninstall: afterinstall +afterinstall: realinstall +install_links: realinstall +proginstall: beforeinstall +realinstall: beforeinstall +.endif + +.if !target(lint) +lint: ${LOBJS} +.if defined(LOBJS) && !empty(LOBJS) + @${LINT} ${LINTFLAGS} ${LDFLAGS:M-L*} ${LOBJS} ${LDADD} +.endif +.endif + +.NOPATH: ${PROG} +.if defined(OBJS) && !empty(OBJS) +.NOPATH: ${OBJS} +.endif + +.if defined(FILES) || defined(FILESGROUPS) +.include +.endif + +.if ${MK_MAN} != "no" +.include +.endif + +.if ${MK_NLS} != "no" +.include +.endif + +.include +.include +.include + +.if !empty(PROG) && ${MK_STAGING_PROG} == "yes" +STAGE_BINDIR ?= ${STAGE_OBJTOP}${BINDIR} +STAGE_DIR.prog ?= ${STAGE_BINDIR} +.if ${PROG_NAME:U${PROG}} != ${PROG} +STAGE_AS_SETS += prog +STAGE_AS_${PROG} = ${PROG_NAME} +stage_as.prog: ${PROG} +.else +STAGE_SETS += prog +stage_files.prog: ${PROG} +.endif +.endif + +.include + +.endif Index: vendor/NetBSD/bmake/20201101/mk/progs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/progs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/progs.mk (revision 367461) @@ -0,0 +1,107 @@ +# $Id: progs.mk,v 1.16 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2006, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.MAIN: all + +.if defined(PROGS) + +# In meta mode, we can capture dependenices for _one_ of the progs. +# if makefile doesn't nominate one, we use the first. +.ifndef UPDATE_DEPENDFILE_PROG +UPDATE_DEPENDFILE_PROG = ${PROGS:[1]} +.export UPDATE_DEPENDFILE_PROG +.endif + +.ifndef PROG +# They may have asked us to build just one +.for t in ${PROGS} +.if make($t) +PROG ?= $t +.endif +.endfor +.endif + +.if defined(PROG) +# just one of many +PROG_VARS += \ + BINDIR \ + CFLAGS \ + COPTS \ + CPPFLAGS \ + CXXFLAGS \ + DPADD \ + DPLIBS \ + LDADD \ + LDFLAGS \ + MAN \ + SRCS + +.for v in ${PROG_VARS:O:u} +.if defined(${v}.${PROG}) || defined(${v}_${PROG}) +$v += ${${v}_${PROG}:U${${v}.${PROG}}} +.endif +.endfor + +# for meta mode, there can be only one! +.if ${PROG} == ${UPDATE_DEPENDFILE_PROG:Uno} +UPDATE_DEPENDFILE ?= yes +.endif +UPDATE_DEPENDFILE ?= NO + +# ensure that we don't clobber each other's dependencies +DEPENDFILE?= .depend.${PROG} +# prog.mk will do the rest +.else +all: ${PROGS} + +# We cannot capture dependencies for meta mode here +UPDATE_DEPENDFILE = NO +# nor can we safely run in parallel. +.NOTPARALLEL: +.endif +.endif + +# handle being called [bsd.]progs.mk +.include <${.PARSEFILE:S,progs,prog,}> + +.ifndef PROG +# tell progs.mk we might want to install things +PROGS_TARGETS+= cleandepend cleandir cleanobj depend install + +.for p in ${PROGS} +.if defined(PROGS_CXX) && !empty(PROGS_CXX:M$p) +# bsd.prog.mk may need to know this +x.$p= PROG_CXX=$p +.endif + +$p ${p}_p: .PHONY .MAKE + (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} PROG=$p ${x.$p} -DWITHOUT_META_STATS) + +.for t in ${PROGS_TARGETS:O:u} +$p.$t: .PHONY .MAKE + (cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} PROG=$p ${x.$p} ${@:E} -DWITHOUT_META_STATS) +.endfor +.endfor + +.for t in ${PROGS_TARGETS:O:u} +$t: ${PROGS:%=%.$t} +.endfor + +.if !defined(WITHOUT_META_STATS) && ${.MAKE.LEVEL} > 0 +.END: _reldir_finish +.ERROR: _reldir_failed +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/rst2htm.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/rst2htm.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/rst2htm.mk (revision 367461) @@ -0,0 +1,53 @@ +# $Id: rst2htm.mk,v 1.11 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# convert reStructuredText to HTML, using rst2html.py from +# docutils - http://docutils.sourceforge.net/ + +.if empty(TXTSRCS) +TXTSRCS != 'ls' -1t ${.CURDIR}/*.txt ${.CURDIR}/*.rst 2>/dev/null; echo +.endif +RSTSRCS ?= ${TXTSRCS} +HTMFILES ?= ${RSTSRCS:R:T:O:u:%=%.htm} +RST2HTML ?= rst2html.py +RST2PDF ?= rst2pdf +RST2S5 ?= rst2s5.py +# the following will run RST2S5 if the target name contains the word 'slides' +# otherwise it uses RST2HTML +RST2HTM = ${"${.TARGET:T:M*slides*}":?${RST2S5}:${RST2HTML}} +RST2HTM_SLIDES_FLAGS ?= ${RST2S5_FLAGS} +RST2HTM_DOC_FLAGS ?= ${RST2HTML_FLAGS} +RST2HTM_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2HTM_SLIDES_FLAGS}:${RST2HTM_DOC_FLAGS}} + +RST2PDF_FLAGS ?= ${"${.TARGET:T:M*slides*}":?${RST2PDF_SLIDES_FLAGS}:${RST2PDF_DOC_FLAGS}} + +RST_SUFFIXES ?= .rst .txt + +CLEANFILES += ${HTMFILES} + +html: ${HTMFILES} + +.SUFFIXES: ${RST_SUFFIXES} .htm .pdf + +${RST_SUFFIXES:@s@$s.htm@}: + ${RST2HTM} ${RST2HTM_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET} + +${RST_SUFFIXES:@s@$s.pdf@}: + ${RST2PDF} ${RST2PDF_FLAGS} ${FLAGS.${.TARGET}} ${.IMPSRC} ${.TARGET} + +.for s in ${RSTSRCS:O:u} +${s:R:T}.htm: $s +${s:R:T}.pdf: $s +.endfor Index: vendor/NetBSD/bmake/20201101/mk/scripts.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/scripts.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/scripts.mk (revision 367461) @@ -0,0 +1,91 @@ +# $Id: scripts.mk,v 1.4 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2006, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.include + +SCRIPTSGROUPS ?= SCRIPTS +SCRIPTSGROUPS := ${SCRIPTSGROUPS:O:u} + +SCRIPTSDIR?= ${BINDIR} +SCRIPTSOWN?= ${BINOWN} +SCRIPTSGRP?= ${BINGRP} +SCRIPTSMODE?= ${BINMODE} + +SCRIPTS_INSTALL_OWN?= -o ${SCRIPTSOWN} -g ${SCRIPTSGRP} +SCRIPTS_COPY ?= -C + +# how we get script name from src +SCRIPTSNAME_MOD?=T:R + +.if !target(buildfiles) +.for group in ${SCRIPTSGROUPS} +buildfiles: ${${group}} +.endfor +.endif +buildfiles: +realbuild: buildfiles + +.for group in ${SCRIPTSGROUPS} +.if !empty(${group}) && defined(${group}DIR) +.if ${group} != "SCRIPTS" +${group}_INSTALL_OWN ?= ${SCRIPTS_INSTALL_OWN} +.endif +# incase we are staging +STAGE_DIR.${group} ?= ${STAGE_OBJTOP}${${group}DIR} + +.for script in ${${group}:O:u} +${group}_INSTALL_OWN.${script:T} ?= ${${group}_INSTALL_OWN} +${group}DIR.${script:T} ?= ${${group}DIR_${script:T}:U${${group}DIR}} +script_mkdir_list += ${${group}DIR.${script:T}} + +${group}NAME.${script} ?= ${${group}NAME_${script:T}:U${script:${SCRIPTSNAME_MOD}}} +.if ${${group}NAME.${script}:T} != ${script:T} +STAGE_AS_SETS += ${group} +STAGE_AS_${script} = ${${group}NAME.${script:T}} +stage_as.${group}: ${script} + +installscripts: installscripts.${group}.${script:T} +installscripts.${group}.${script:T}: ${script} script_mkdirs + ${INSTALL} ${SCRIPTS_COPY} ${${group}_INSTALL_OWN.${script:T}} \ + -m ${SCRIPTSMODE} ${.ALLSRC:Nscript_mkdirs} ${DESTDIR}${${group}DIR}/${${group}NAME.${script:T}} + +.else +STAGE_SETS += ${group} +stage_files.${group}: ${script} +installscripts.${group}: ${script} +installscripts: installscripts.${group} +.endif + +.endfor # script + +installscripts.${group}: script_mkdirs + ${INSTALL} ${SCRIPTS_COPY} ${${group}_INSTALL_OWN} -m ${SCRIPTSMODE} \ + ${.ALLSRC:Nscript_mkdirs:O:u} ${DESTDIR}${${group}DIR} + +.endif # !empty +.endfor # group + +script_mkdirs: + @for d in ${script_mkdir_list:O:u}; do \ + test -d ${DESTDIR}$$d || \ + ${INSTALL} -d ${SCRIPTS_INSTALL_OWN} -m 775 ${DESTDIR}$$d; \ + done + + +beforeinstall: +installscripts: +realinstall: installscripts +.ORDER: beforeinstall installscripts + Index: vendor/NetBSD/bmake/20201101/mk/srctop.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/srctop.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/srctop.mk (revision 367461) @@ -0,0 +1,66 @@ +# $Id: srctop.mk,v 1.4 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2012, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if !defined(SRCTOP) +# if using mk(1) SB will be set. +.ifdef SB +.if ${.CURDIR:S,${SB},,} != ${.CURDIR} +# we are actually within SB +.ifdef SB_SRC +SRCTOP:= ${SB_SRC} +.elif exists(${SB}/src) +SRCTOP:= ${SB}/src +.else +SRCTOP:= ${SB} +.endif +.endif +.endif + +.if !defined(SRCTOP) +.for rd in share/mk build/mk mk +.if ${_this_mk_dir:M*${rd}} != "" +.if ${.CURDIR:S,${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}},,} != ${.CURDIR} +SRCTOP:= ${_this_mk_dir:${rd:C,[^/]+,H,g:S,/, ,g:ts:}} +.endif +.endif +.endfor +.endif + +.if !defined(SRCTOP) +_SRCTOP_TEST_?= [ -f ../.sandbox-env -o -d share/mk ] +# Linux at least has a bug where attempting to check an automounter +# directory will hang. So avoid looking above /a/b +SRCTOP!= cd ${.CURDIR}; while :; do \ + here=`pwd`; \ + ${_SRCTOP_TEST_} && { echo $$here; break; }; \ + case $$here in /*/*/*) cd ..;; *) echo ""; break;; esac; \ + done +.endif +.if defined(SRCTOP) && exists(${SRCTOP}/.) +.export SRCTOP +.endif +.endif + +.if !defined(OBJTOP) && !empty(SRCTOP) +.if defined(MAKEOBJDIRPREFIX) && exists(${MAKEOBJDIRPREFIX}${SRCTOP}) +OBJTOP= ${MAKEOBJDIRPREFIX}${SRCTOP} +.elif (exists(${SRCTOP}/Makefile) || exists(${SRCTOP}/makefile)) +OBJTOP!= cd ${SRCTOP} && ${PRINTOBJDIR} +.endif +.if empty(OBJTOP) +OBJTOP= ${SRCTOP} +.endif +.export OBJTOP +.endif Index: vendor/NetBSD/bmake/20201101/mk/stage-install.sh =================================================================== --- vendor/NetBSD/bmake/20201101/mk/stage-install.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/stage-install.sh (revision 367461) @@ -0,0 +1,135 @@ +#!/bin/sh + +# NAME: +# stage-install.sh - wrapper around install +# +# SYNOPSIS: +# stage-install.sh [variable="value"] "args" "dest" +# +# DESCRIPTION: +# This script is a wrapper around the normal install(1). +# Its role is to add '.dirdep' files to the destination. +# The variables we might use are: +# +# INSTALL +# Path to actual install(1), default is +# $REAL_INSTALL +# +# OBJDIR +# Path to the dir where '.dirdep' was generated, +# default is '.' +# +# _DIRDEP +# Path to actual '.dirdep' file, default is +# $OBJDIR/.dirdep +# +# The "args" and "dest" are passed as is to install(1), and if a +# '.dirdep' file exists it will be linked or copied to each +# "file".dirdep placed in "dest" or "dest".dirdep if it happed +# to be a file rather than a directory. +# +# Before we run install(1), we check if "dest" needs to be a +# directory (more than one file in "args") and create it +# if necessary. +# +# SEE ALSO: +# meta.stage.mk +# + +# RCSid: +# $Id: stage-install.sh,v 1.9 2020/08/28 01:04:13 sjg Exp $ +# +# @(#) Copyright (c) 2013-2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +INSTALL=${REAL_INSTALL:-install} +OBJDIR=. + +while : +do + case "$1" in + *=*) eval "$1"; shift;; + *) break;; + esac +done + +# get last entry from "$@" without side effects +last_entry() { + while [ $# -gt 8 ] + do + shift 8 + done + eval last=\$$# + echo $last +} + +# mkdir $dest if needed (more than one file) +mkdir_if_needed() { + ( + lf= + while [ $# -gt 8 ] + do + shift 4 + done + for f in "$@" + do + [ -f $f ] || continue + [ $f = $dest ] && continue + if [ -n "$lf" ]; then + # dest must be a directory + mkdir -p $dest + break + fi + lf=$f + done + ) +} + +args="$@" +dest=`last_entry "$@"` +case " $args " in +*" -d "*) ;; +*) [ -e $dest ] || mkdir_if_needed "$@";; +esac + +# if .dirdep doesn't exist, just run install and be done +_DIRDEP=${_DIRDEP:-$OBJDIR/.dirdep} +[ -s $_DIRDEP ] && EXEC= || EXEC=exec +$EXEC $INSTALL "$@" || exit 1 + +# from meta.stage.mk +LnCp() { + rm -f $2 2> /dev/null + ln $1 $2 2> /dev/null || cp -p $1 $2 +} + +StageDirdep() { + t=$1 + if [ -s $t.dirdep ]; then + cmp -s $_DIRDEP $t.dirdep && return + echo "ERROR: $t installed by `cat $t.dirdep` not `cat $_DIRDEP`" >&2 + exit 1 + fi + LnCp $_DIRDEP $t.dirdep || exit 1 +} + +if [ -f $dest ]; then + # a file, there can be only one .dirdep needed + StageDirdep $dest +elif [ -d $dest ]; then + for f in $args + do + test -f $f || continue + StageDirdep $dest/${f##*/} + done +fi Property changes on: vendor/NetBSD/bmake/20201101/mk/stage-install.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/sys/AIX.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/AIX.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/AIX.mk (revision 367461) @@ -0,0 +1,184 @@ +# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $ +# @(#)sys.mk 5.11 (Berkeley) 3/13/91 + +OS ?= AIX +unix ?= We run ${OS}. +ROOT_GROUP ?= system + +# This needs a lot of work yet... + +NOPIC ?=no # no shared libs? + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +.LIBS: .a + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AFLAGS= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +.if exists(/usr/local/bin/gcc) +CC ?= gcc +DBG ?= -O -g +STATIC ?= -static +.else +CC ?= cc +DBG ?= -g +STATIC ?= +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= g++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif + +MK_DEP ?= mkdeps.sh -N +FC ?= f77 +FFLAGS ?= -O +RFLAGS= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +LEX ?= lex +LFLAGS= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS= + +LINT ?= lint +LINTFLAGS ?= -chapbx + +PC ?= pc +PFLAGS= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +YACC ?= yacc +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} -o ${.TARGET} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/Darwin.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/Darwin.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/Darwin.mk (revision 367461) @@ -0,0 +1,222 @@ +# $NetBSD: Darwin.sys.mk,v 1.3 2003/02/16 09:44:41 grant Exp $ +# @(#)sys.mk 8.2 (Berkeley) 3/21/94 + +OS ?= Darwin +unix ?= We run ${OS}. + +.SUFFIXES: .out .a .ln .o .s .S .c .m ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 .dylib + +.LIBS: .a .dylib + +SHLIBEXT ?= .dylib +HOST_LIBEXT ?= .dylib +DSHLIBEXT ?= .dylib + +AR ?= ar +ARFLAGS ?= rl +RANLIB = + +AS ?= as +AFLAGS ?= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +PIPE ?= -pipe + +.if exists(/usr/bin/clang) +CC ?= cc ${PIPE} +CXX ?= c++ +.elif exists(/usr/bin/gcc) +CC ?= gcc ${PIPE} +.else +CC ?= cc ${PIPE} +.endif +DBG ?= -O2 +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +.if exists(/usr/bin/g++) +CXX ?= g++ +.else +CXX ?= c++ +.endif +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +OBJC ?= ${CC} +OBJCFLAGS ?= ${CFLAGS} +COMPILE.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +NOLINT ?= 1 +CPPFLAGS ?= + +MK_DEP ?= mkdep + +FC ?= f77 +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= install + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +SHLIB_TEENY ?= 0 +SHLIB_MINOR ?= 0 + +MKPICLIB ?= no +LIBEXT ?= .dylib + +LINT ?= lint +LINTFLAGS ?= -chapbx + +LORDER ?= lorder + +NM ?= nm + +PC ?= pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +TSORT ?= tsort -q + +YACC ?= bison -y +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Objective-C +.m: + ${LINK.m} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.m.o: + ${COMPILE.m} ${.IMPSRC} +.m.a: + ${COMPILE.m} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} -o ${.TARGET} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/Generic.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/Generic.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/Generic.mk (revision 367461) @@ -0,0 +1,204 @@ +# $Id: Generic.mk,v 1.17 2020/08/19 17:51:53 sjg Exp $ +# + +# some reasonable defaults +.SUFFIXES: .out .a .ln .o .s .S .c ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 + +.LIBS: .a + +tools ?= \ + ar \ + lorder \ + ranlib \ + tsort + +.for t in ${tools} +${t:tu} := ${t:${M_whence}} +.endfor + +# need to make sure this is set +MACHINE_ARCH.${MACHINE} ?= ${MACHINE} +.if empty(MACHINE_ARCH) +MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}} +.endif + +.if !empty(TSORT) +TSORT += -q +.endif + +ARFLAGS ?= rl + +AS ?= as +AFLAGS ?= +.if ${MACHINE_ARCH} == "sparc64" +AFLAGS+= -Wa,-Av9a +.endif +COMPILE.s ?= ${CC} ${AFLAGS} -c +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CC ?= cc +DBG ?= -O2 +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= c++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +OBJC ?= ${CC} +OBJCFLAGS ?= ${CFLAGS} +COMPILE.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +CPPFLAGS ?= + +FC ?= f77 +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= install + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +LINT ?= lint +LINTFLAGS ?= -chapbxzF + +NM ?= nm + +PC ?= pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +YACC ?= yacc +YFLAGS ?= +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.c.ln: + ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC} + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} + Index: vendor/NetBSD/bmake/20201101/mk/sys/HP-UX.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/HP-UX.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/HP-UX.mk (revision 367461) @@ -0,0 +1,226 @@ +# $Id: HP-UX.mk,v 1.15 2020/08/19 17:51:53 sjg Exp $ +# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $ +# @(#)sys.mk 5.11 (Berkeley) 3/13/91 + +OS ?= HP-UX +ROOT_GROUP ?= root +unix ?= We run ${OS}. + +# HP-UX's cc does not provide any clues as to wether this is 9.x or 10.x +# nor does sys/param.h, so we'll use the existence of /hp-ux +.if exists("/hp-ux") +OSMAJOR ?=9 +.endif +OSMAJOR ?=10 +__HPUX_VERSION ?=${OSMAJOR} + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +LIBMODE ?= 755 +LIBCRT0 ?= /lib/crt0.o + +.LIBS: .a + +# +b is needed to stop the binaries from insisting on having +# the build tree available :-) +# +s tells the dynamic loader to use SHLIB_PATH if set +LD_bpath ?=-Wl,+b/lib:/usr/lib:/usr/local/lib +LD_spath ?=-Wl,+s +LDADD+= ${LD_bpath} ${LD_spath} + +.if exists(/usr/lib/end.o) +LDADD+= /usr/lib/end.o +.endif + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= : + +AFLAGS= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +.if exists(/usr/local/bin/gcc) +PIPE ?= -pipe +CC ?= gcc ${PIPE} +AS ?= gas +DBG ?= -O -g +STATIC ?= -static +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif +.else +# HP's bundled compiler knows not -g or -O +AS ?= as +CC ?= cc +.if exists(/opt/ansic/bin/cc) +CCMODE ?=-Ae +ESlit +PICFLAG ?= +z +LD_x= +DBG ?=-g -O +.endif +DBG ?= +STATIC ?= -Wl,-a,archive +.endif +.if (${__HPUX_VERSION} == "10") +CCSOURCE_FLAGS ?= -D_HPUX_SOURCE +.else +CCSOURCE_FLAGS ?= -D_HPUX_SOURCE -D_INCLUDE_POSIX_SOURCE -D_INCLUDE_XOPEN_SOURCE -D_INCLUDE_XOPEN_SOURCE_EXTENDED +.endif +CFLAGS ?= ${DBG} +CFLAGS+ ?= ${CCMODE} -D__hpux__ -D__HPUX_VERSION=${__HPUX_VERSION} ${CCSOURCE_FLAGS} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= g++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp + +MK_DEP ?= mkdeps.sh -N +FC ?= f77 +FFLAGS ?= -O +RFLAGS= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +LEX ?= lex +LFLAGS= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS= + +LINT ?= lint +LINTFLAGS ?= -chapbx + +PC ?= pc +PFLAGS= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +# HP's sh sucks +ENV= +MAKE_SHELL ?= /bin/ksh + +.if exists(/usr/local/bin/bison) +YACC ?= bison -y +.else +YACC ?= yacc +.endif +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} -o ${.TARGET} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/IRIX.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/IRIX.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/IRIX.mk (revision 367461) @@ -0,0 +1,195 @@ +# $NetBSD: IRIX.sys.mk,v 1.2 2002/12/24 23:03:27 jschauma Exp $ +# @(#)sys.mk 8.2 (Berkeley) 3/21/94 + +.if ${.PARSEFILE} == "sys.mk" +.ifndef ROOT_GROUP +OS!= uname -s +ROOT_GROUP!= sed -n /:0:/s/:.*//p /etc/group +.MAKEOVERRIDES+= OS ROOT_GROUP +.endif +unix ?= We run ${OS}. +.endif + +.SUFFIXES: .out .a .ln .o .s .S .c ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 + +.LIBS: .a + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AFLAGS ?= +COMPILE.s ?= ${CC} ${AFLAGS} -c +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CC ?= cc +NOGCCERROR ?= # defined +DBG ?= -O2 +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= CC +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +OBJC ?= ${CC} +OBJCFLAGS ?= ${CFLAGS} +COMPILE.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= CC +CPPFLAGS ?= + +FC ?= f77 +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= ${PREFIX}/bin/install-sh + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +LINT ?= lint +LINTFLAGS ?= -chapbxzF + +LORDER ?= lorder + +NM ?= nm + +PC ?= pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +TSORT ?= tsort -q + +YACC ?= yacc +YFLAGS ?= +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.c.ln: + ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC} + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/Linux.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/Linux.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/Linux.mk (revision 367461) @@ -0,0 +1,187 @@ +# $Id: Linux.mk,v 1.13 2020/08/19 17:51:53 sjg Exp $ +# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $ +# @(#)sys.mk 5.11 (Berkeley) 3/13/91 + +OS ?= Linux +unix ?= We run ${OS}. + +ROOT_GROUP ?= root + +# would be better to work out where it is... +LIBCRT0 ?= /dev/null + +NEED_SOLINKS ?=yes + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +.LIBS: .a + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AFLAGS= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +.if exists(/usr/local/bin/gcc) +CC ?= gcc -pipe +DBG ?= -O -g +STATIC ?= -static +.else +CC ?= cc -pipe +DBG ?= -g +STATIC ?= -Bstatic +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= g++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif + +MK_DEP ?= mkdeps.sh -N +FC ?= f77 +FFLAGS ?= -O +RFLAGS= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +LEX ?= lex +LFLAGS= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS= + +LINT ?= lint +LINTFLAGS ?= -chapbx + +PC ?= pc +PFLAGS= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +YACC ?= yacc +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} -o ${.TARGET} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/NetBSD.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/NetBSD.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/NetBSD.mk (revision 367461) @@ -0,0 +1,230 @@ +# $NetBSD: sys.mk,v 1.66.2.1 2002/06/05 03:31:01 lukem Exp $ +# @(#)sys.mk 8.2 (Berkeley) 3/21/94 + +OS ?= NetBSD +unix ?= We run ${OS}. + +.if !defined(MAKE_VERSION) +# we are running native make +# which defined MAKE_VERSION between 20010609 and 20090324 +# so we can make a rough guess +.if defined(.MAKE.LEVEL) +MAKE_VERSION ?= 20090908 +.elif defined(.MAKE.MAKEFILES) +# introduced 20071008 +MAKE_VERSION ?= 20090324 +.else +# this just before when MAKE_VERSION was introduced +MAKE_VERSION ?= 20010606 +.endif +.endif + +.SUFFIXES: .out .a .ln .o .s .S .c ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 + +.LIBS: .a + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AFLAGS ?= +COMPILE.s ?= ${CC} ${AFLAGS} -c +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CC ?= cc + +# need to make sure this is set +MACHINE_ARCH.${MACHINE} ?= ${MACHINE} +.if empty(MACHINE_ARCH) +MACHINE_ARCH ?= ${MACHINE_ARCH.${MACHINE}} +.endif + +# +# CPU model, derived from MACHINE_ARCH +# +MACHINE_CPU ?= ${MACHINE_ARCH:C/mipse[bl]/mips/:C/mips64e[bl]/mips/:C/sh3e[bl]/sh3/:S/m68000/m68k/:S/armeb/arm/} + +.if ${MACHINE_CPU} == "alpha" || \ + ${MACHINE_CPU} == "arm" || \ + ${MACHINE_CPU} == "i386" || \ + ${MACHINE_CPU} == "m68k" || \ + ${MACHINE_CPU} == "mips" || \ + ${MACHINE_CPU} == "powerpc" || \ + ${MACHINE_CPU} == "sparc" || \ + ${MACHINE_CPU} == "vax" +DBG ?= -O2 +.elif ${MACHINE_ARCH} == "x86_64" +DBG ?= +.elif ${MACHINE_ARCH} == "sparc64" +DBG ?= -O -ffixed-g4 #Hack for embedany memory model compatibility +.else +DBG ?= -O +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= c++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +OBJC ?= ${CC} +OBJCFLAGS ?= ${CFLAGS} +COMPILE.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +CPPFLAGS ?= + +FC ?= f77 +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= install + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +LINT ?= lint +LINTFLAGS ?= -chapbxzF + +LORDER ?= lorder + +NM ?= nm + +PC ?= pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +TSORT ?= tsort -q + +YACC ?= yacc +YFLAGS ?= +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.c.ln: + ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC} + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/OSF1.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/OSF1.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/OSF1.mk (revision 367461) @@ -0,0 +1,198 @@ +# $Id: OSF1.mk,v 1.12 2020/08/19 17:51:53 sjg Exp $ +# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $ +# @(#)sys.mk 5.11 (Berkeley) 3/13/91 + +OS ?= OSF1 +unix ?= We run ${OS}. +ROOT_GROUP ?= system + +# can't fine one anywhere, so just stop the dependency +LIBCRT0 ?= /dev/null + +PATH ?=/usr/sbin:/usr/bin:/usr/ucb:/opt/gnu/bin:/usr/ccs/bin + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +.LIBS: .a + +# no -X +LD_X= +LD_x ?= -x +LD_r ?= -r +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AS_STDIN ?= - +AFLAGS= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +.if exists(/opt/gnu/bin/gcc) || exists(/usr/local/bin/gcc) +CC ?= gcc +.else +CC ?= cc -std +.endif +.if (${CC:T} == "gcc") +DBG ?= -O -g +STATIC ?= -static +DBG ?= -g +STATIC ?= -non_shared +.endif + +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= g++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= /usr/ccs/lib/cpp +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif + +MK_DEP ?= mkdeps.sh -N +FC ?= f77 +FFLAGS ?= -O +RFLAGS= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +LEX ?= lex +LFLAGS= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS= + +LINT ?= lint +LINTFLAGS ?= -chapbx + +PC ?= pc +PFLAGS= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +.if exists(/usr/local/bin/bison) || exists(/opt/gnu/bin/bison) +YACC ?= bison -y +.else +YACC ?= yacc +.endif +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/OpenBSD.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/OpenBSD.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/OpenBSD.mk (revision 367461) @@ -0,0 +1,205 @@ +# $NetBSD: OpenBSD.sys.mk,v 1.1 2002/11/17 09:18:00 cjep Exp $ +# @(#)sys.mk 8.2 (Berkeley) 3/21/94 + +OS ?= OpenBSD +unix ?= We run ${OS}. + +.SUFFIXES: .out .a .ln .o .s .S .c ${CXX_SUFFIXES} .F .f .r .y .l .cl .p .h +.SUFFIXES: .sh .m4 + +.LIBS: .a + +# need to make sure this is set +MACHINE_ARCH.${MACHINE} ?= ${MACHINE} +.if empty(MACHINE_ARCH) +MACHINE_ARCH ?= ${MACHINE_ARCH.${MACHINE}} +.endif + +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= ranlib + +AS ?= as +AFLAGS ?= +.if ${MACHINE_ARCH} == "sparc64" +AFLAGS+= -Wa,-Av9a +.endif +COMPILE.s ?= ${CC} ${AFLAGS} -c +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c -traditional-cpp +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CC ?= cc +.if ${MACHINE_ARCH} == "alpha" || \ + ${MACHINE_ARCH} == "i386" || \ + ${MACHINE_ARCH} == "m68k" || \ + ${MACHINE_ARCH} == "sparc" || \ + ${MACHINE_ARCH} == "vax" +DBG ?= -O2 +.else +DBG ?= -O +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= c++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +OBJC ?= ${CC} +OBJCFLAGS ?= ${CFLAGS} +COMPILE.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c +LINK.m ?= ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= cpp +CPPFLAGS ?= + +FC ?= f77 +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= install + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +LINT ?= lint +LINTFLAGS ?= -chapbxzF + +LORDER ?= lorder + +NM ?= nm + +PC ?= pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +TSORT ?= tsort -q + +YACC ?= yacc +YFLAGS ?= +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.c.ln: + ${LINT} ${LINTFLAGS} ${CPPFLAGS:M-[IDU]*} -i ${.IMPSRC} + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/SunOS.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/SunOS.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/SunOS.mk (revision 367461) @@ -0,0 +1,219 @@ +# $Id: SunOS.mk,v 1.12 2020/08/19 17:51:53 sjg Exp $ + +.if ${.PARSEFILE} == "sys.mk" +.include + +OS ?= SunOS.${HOST_OSMAJOR} +unix ?= We run ${OS}. +.endif + +.if ${HOST_OSMAJOR} > 4 +ROOT_GROUP ?= root + +SHLIB_FULLVERSION ?= ${SHLIB_MAJOR} + +# suppress the dependency +LIBCRT0 ?= /dev/null + +.ifndef CC +# the PATH below may find an ancient gcc +CC := ${gcc:L:${M_whence}} +.export CC +.endif + +# the stuff in /usr/xpg4/bin is usually more sane. +PATH ?=/usr/xpg4/bin:/usr/sbin:/usr/bin:/usr/ucb:/usr/sfw/bin:/opt/gnu/bin:/usr/ccs/bin:/usr/local/bin +.export PATH + +DSHLIBEXT ?= .so +HOST_LIBDIRS ?= /usr/lib /lib /usr/sfw/lib + +# no -X +LD_X= +LD_x= +RANLIB ?= : +CPP ?= /usr/ccs/lib/cpp +.else +ROOT_GROUP ?= wheel +RANLIB ?= ranlib +CPP ?= cpp +.endif + +# the rest is common + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +.LIBS: .a + +AR ?= ar +ARFLAGS ?= rl + +AS ?= as +AS_STDIN ?= - +AFLAGS= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} +.if exists(/opt/gnu/bin/gcc) || exists(/usr/local/bin/gcc) +CC ?= gcc -pipe +DBG ?= -O -g +STATIC ?= -static +.else +CC ?= cc +DBG ?= -g +STATIC ?= -Bstatic +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CXX ?= g++ +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif + +MK_DEP ?= mkdeps.sh -N +FC ?= f77 +FFLAGS ?= -O +RFLAGS= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +LEX ?= lex +LFLAGS= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS= + +LINT ?= lint +LINTFLAGS ?= -chapbx + +PC ?= pc +PFLAGS= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +.if exists(/usr/local/bin/bison) || exists(/opt/gnu/bin/bison) +YACC ?= bison -y +.else +YACC ?= yacc +.endif +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys/UnixWare.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys/UnixWare.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys/UnixWare.mk (revision 367461) @@ -0,0 +1,241 @@ +# $Id: UnixWare.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $ +# based on "Id: SunOS.5.sys.mk,v 1.6 2003/09/30 16:42:23 sjg Exp " +# $NetBSD: sys.mk,v 1.19.2.1 1994/07/26 19:58:31 cgd Exp $ +# @(#)sys.mk 5.11 (Berkeley) 3/13/91 + +OS ?= UnixWare +unix ?= We run ${OS}. +ROOT_GROUP ?= root + +# can't fine one anywhere, so just stop the dependency +LIBCRT0 ?= /dev/null + +PATH ?=/usr/sbin:/usr/bin:/usr/ccs/bin:/usr/ccs/lib:/usr/ucb:/usr/local/bin + +.SUFFIXES: .out .a .ln .o .c ${CXX_SUFFIXES} .F .f .r .y .l .s .S .cl .p .h .sh .m4 + +.LIBS: .a + +# no -X +LD_X= +LD_x= +AR ?= ar +ARFLAGS ?= rl +RANLIB ?= : + +AS ?= as +AS_STDIN ?= - +AFLAGS ?= +COMPILE.s ?= ${AS} ${AFLAGS} +LINK.s ?= ${CC} ${AFLAGS} ${LDFLAGS} +COMPILE.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} -c +LINK.S ?= ${CC} ${AFLAGS} ${CPPFLAGS} ${LDFLAGS} + +# at least gcc 2.95 on UnixWare has no internal macro to identify the system +.if exists(/usr/local/bin/gcc) +CC ?= gcc -pipe -DUNIXWARE +DBG ?= -O -g +STATIC ?= -static +.else +CC ?= cc +DBG ?= -g +STATIC ?= -Bstatic # XXX: don't know about UDK compilers +.endif +CFLAGS ?= ${DBG} +COMPILE.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} -c +LINK.c ?= ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} + +.if exists(/usr/local/bin/g++) +CXX ?= g++ -DUNIXWARE +.else +CXX ?= c++ # XXX: don't know about UDK compilers +.endif +CXXFLAGS ?= ${CFLAGS} +COMPILE.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c +LINK.cc ?= ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} + +CPP ?= /usr/ccs/lib/cpp +.if defined(DESTDIR) +CPPFLAGS+= -nostdinc -idirafter ${DESTDIR}/usr/include +.endif + +MK_DEP ?= mkdeps.sh -N +.if exists(/usr/local/bin/g77) +FC ?= g77 +.else +FC ?= f77 # XXX: don't know about UDK compilers +.endif +FFLAGS ?= -O +RFLAGS ?= +COMPILE.f ?= ${FC} ${FFLAGS} -c +LINK.f ?= ${FC} ${FFLAGS} ${LDFLAGS} +COMPILE.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} -c +LINK.F ?= ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS} +COMPILE.r ?= ${FC} ${FFLAGS} ${RFLAGS} -c +LINK.r ?= ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS} + +INSTALL ?= /usr/ucb/install # BSD install + +LEX ?= lex +LFLAGS ?= +LEX.l ?= ${LEX} ${LFLAGS} + +LD ?= ld +LDFLAGS ?= + +LIBC ?= ${DESTDIR}/usr/ccs/lib/libc.a +LIBCOMPAT ?= +LIBCRYPT ?= ${DESTDIR}/usr/lib/libcrypt.a +LIBCURSES ?= ${DESTDIR}/usr/ccs/lib/libcurses.a +LIBDBM ?= +LIBDES ?= +LIBEDIT ?= +LIBGCC ?= +LIBKDB ?= +LIBKRB ?= +LIBKVM ?= +LIBL ?= ${DESTDIR}/usr/ccs/lib/libl.a +LIBM ?= ${DESTDIR}/usr/ccs/lib/libm.a +LIBMP ?= +LIBPC ?= +LIBPCAP ?= +LIBPLOT ?= +LIBRESOLV ?= +LIBRPCSVC ?= ${DESTDIR}/usr/lib/librpcsvc.a +LIBSKEY ?= ${DESTDIR}/usr/lib/libskey.a +LIBTERMCAP ?= ${DESTDIR}/usr/ccs/lib/libtermcap.a +LIBUTIL ?= +LIBWRAP ?= +LIBY ?= ${DESTDIR}/usr/ccs/lib/liby.a +LIBZ ?= + +LINT ?= lint +LINTFLAGS ?= -pF + +LORDER ?= lorder + +NM ?= nm + +PC ?= pc # XXX: UDK probably does not have pc +PFLAGS ?= +COMPILE.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} -c +LINK.p ?= ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS} + +SIZE ?= size + +TSORT ?= tsort + +.if exists(/usr/local/bin/bison) +YACC ?= bison -y +.else +YACC ?= yacc +.endif +YFLAGS ?= -d +YACC.y ?= ${YACC} ${YFLAGS} + +# C +.c: + ${LINK.c} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.c.o: + ${COMPILE.c} ${.IMPSRC} +.c.a: + ${COMPILE.c} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# C++ +${CXX_SUFFIXES}: + ${LINK.cc} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +${CXX_SUFFIXES:%=%.o}: + ${COMPILE.cc} ${.IMPSRC} +${CXX_SUFFIXES:%=%.a}: + ${COMPILE.cc} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Fortran/Ratfor +.f: + ${LINK.f} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.f.o: + ${COMPILE.f} ${.IMPSRC} +.f.a: + ${COMPILE.f} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.F: + ${LINK.F} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.F.o: + ${COMPILE.F} ${.IMPSRC} +.F.a: + ${COMPILE.F} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +.r: + ${LINK.r} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.r.o: + ${COMPILE.r} ${.IMPSRC} +.r.a: + ${COMPILE.r} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Pascal +.p: + ${LINK.p} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.p.o: + ${COMPILE.p} ${.IMPSRC} +.p.a: + ${COMPILE.p} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Assembly +.s: + ${LINK.s} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.s.o: + ${COMPILE.s} ${.IMPSRC} +.s.a: + ${COMPILE.s} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o +.S: + ${LINK.S} -o ${.TARGET} ${.IMPSRC} ${LDLIBS} +.S.o: + ${COMPILE.S} ${.IMPSRC} +.S.a: + ${COMPILE.S} ${.IMPSRC} + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +# Lex +.l: + ${LEX.l} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} lex.yy.c ${LDLIBS} -ll + rm -f lex.yy.c +.l.c: + ${LEX.l} ${.IMPSRC} + mv lex.yy.c ${.TARGET} +.l.o: + ${LEX.l} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} lex.yy.c + rm -f lex.yy.c + +# Yacc +.y: + ${YACC.y} ${.IMPSRC} + ${LINK.c} -o ${.TARGET} y.tab.c ${LDLIBS} + rm -f y.tab.c +.y.c: + ${YACC.y} ${.IMPSRC} + mv y.tab.c ${.TARGET} +.y.o: + ${YACC.y} ${.IMPSRC} + ${COMPILE.c} -o ${.TARGET} y.tab.c + rm -f y.tab.c + +# Shell +.sh: + rm -f ${.TARGET} + cp ${.IMPSRC} ${.TARGET} Index: vendor/NetBSD/bmake/20201101/mk/sys.clean-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys.clean-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys.clean-env.mk (revision 367461) @@ -0,0 +1,130 @@ +# $Id: sys.clean-env.mk,v 1.23 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# This makefile would normally be included by sys.env.mk + +# The variables used by this makefile include: +# +# MAKE_ENV_SAVE_VAR_LIST +# The actuall list of variables from the environment that will be +# preserved. +# MAKE_ENV_SAVE_PREFIX_LIST +# A list of prefixes to match against the environment - the results +# are added to MAKE_ENV_SAVE_VAR_LIST after being filtered by... +# MAKE_ENV_SAVE_EXCLUDE_LIST +# A list of words or patterns which is turned into a list of :N +# modifiers. + +.if ${.MAKE.LEVEL} == 0 && ${MAKE_VERSION} >= 20100606 +# We save any env var that starts with the words in MAKE_ENV_SAVE_PREFIX_LIST. +# This gets expanded to an egrep expression like '^(A|B|C...)' +# and added to MAKE_ENV_SAVE_VAR_LIST below. +# If any of these end up being too greedy, MAKE_ENV_SAVE_EXCLUDE_LIST +# can be used to filter. +MAKE_ENV_SAVE_PREFIX_LIST += \ + CCACHE \ + CVS \ + DEBUG \ + DISTCC \ + HOST \ + MACHINE \ + MAKE \ + MK \ + NEED_ \ + SB_ \ + SSH \ + SVN \ + USE_ \ + WITH_ \ + WITHOUT_ \ + + +# This could be a list of vars or patterns to explicitly exclude. +MAKE_ENV_SAVE_EXCLUDE_LIST ?= _ + +# This is the actual list that we will save +# HOME is probably something worth clobbering eg. +# HOME=/var/empty +MAKE_ENV_SAVE_VAR_LIST += \ + HOME \ + LOGNAME \ + OBJROOT \ + OBJTOP \ + PATH \ + SB \ + SRCTOP \ + USER \ + ${_env_vars:${MAKE_ENV_SAVE_EXCLUDE_LIST:${M_ListToSkip}}} + +_env_vars != env | egrep '^(${MAKE_ENV_SAVE_PREFIX_LIST:ts|})' | sed 's,=.*,,'; echo + +_export_list = +.for v in ${MAKE_ENV_SAVE_VAR_LIST:O:u} +.if defined($v) +_export_list += $v +# Save current value +$v := ${$v} +.endif +.endfor + +# Now, clobber the environment +.unexport-env + +# This is a list of vars that we handle specially below +_tricky_env_vars = MAKEOBJDIR OBJTOP +# Export our selection - sans tricky ones +.export ${_export_list:${_tricky_env_vars:${M_ListToSkip}}} + +# This next bit may need tweaking +# if you don't happen to like the way I set it. +.if defined(MAKEOBJDIR) +# We are going to set this to the equivalent of the shell's +# MAKEOBJDIR='${.CURDIR:S,${SRCTOP},${OBJTOP},}' +_srctop := ${SRCTOP:U${SB_SRC:U${SB}/src}} +_objroot := ${OBJROOT:U${SB_OBJROOT:U${SB}/${SB_OBJPREFIX}}} +.if ${MAKE_VERSION} < 20160218 +_objtop := ${OBJTOP:U${_objroot}${MACHINE}} +# Take care of ${MACHINE} +.if ${MACHINE:Nhost*} == "" || ${OBJTOP} == ${HOST_OBJTOP:Uno} +OBJTOP = ${_objtop:S,${HOST_TARGET}$,\${MACHINE},} +.else +OBJTOP = ${_objtop:S,${MACHINE}$,\${MACHINE},} +.endif +# Export like this +MAKEOBJDIR = $${.CURDIR:S,${_srctop},$${OBJTOP},} +#.info ${MAKE_SAVE_ENV_VARS _srctop _objroot _objtop OBJTOP MAKEOBJDIR:L:@v@${.newline}$v=${$v}@} + +# Export these as-is, and do not track... +# otherwise the environment will be ruined when we evaluate them below. +.export-env ${_tricky_env_vars} + +# Now evaluate for ourselves +.for v in ${_tricky_env_vars} +$v := ${$v} +.endfor +.else +# we cannot use the '$$' trick, anymore +# but we can export a literal (unexpanded) value +SRCTOP := ${_srctop} +OBJROOT := ${_objroot} +OBJTOP = ${OBJROOT}${MACHINE} +MAKEOBJDIR = ${.CURDIR:S,${SRCTOP},${OBJTOP},} +.export-literal SRCTOP OBJROOT ${_tricky_env_vars} +.endif +#.info ${_tricky_env_vars:@v@${.newline}$v=${$v}@} +#showenv: +# @env | egrep 'OBJ|SRC' +.endif # MAKEOBJDIR +.endif # level 0 Index: vendor/NetBSD/bmake/20201101/mk/sys.debug.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys.debug.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys.debug.mk (revision 367461) @@ -0,0 +1,33 @@ +# $Id: sys.debug.mk,v 1.2 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# Sometimes we want to turn on debugging in just one or two places +# if .CURDIR is matched by any entry in DEBUG_MAKE_SYS_DIRS we +# will apply DEBUG_MAKE_FLAGS now. +# if an entry in DEBUG_MAKE_DIRS matches, we at the end of sys.mk +# eg. DEBUG_MAKE_FLAGS=-dv DEBUG_MAKE_SYS_DIRS="*lib/sjg" +# use DEBUG_MAKE_FLAGS0 to apply only to .MAKE.LEVEL 0 +# +.if ${.MAKE.LEVEL:U1} == 0 +# we use indirection, to simplify the tests below, and incase +# DEBUG_* were given on our command line. +_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS0} +_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS0:U${DEBUG_MAKE_SYS_DIRS}} +_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS0:U${DEBUG_MAKE_DIRS}} +.else +_DEBUG_MAKE_FLAGS = ${DEBUG_MAKE_FLAGS} +_DEBUG_MAKE_SYS_DIRS = ${DEBUG_MAKE_SYS_DIRS} +_DEBUG_MAKE_DIRS = ${DEBUG_MAKE_DIRS} +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/sys.debug.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/sys.dependfile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys.dependfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys.dependfile.mk (revision 367461) @@ -0,0 +1,59 @@ +# $Id: sys.dependfile.mk,v 1.9 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2012, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# This only makes sense in meta mode. +# This allows a mixture of auto generated as well as manually edited +# dependency files, which can be differentiated by their names. +# As per dirdeps.mk we only require: +# 1. a common prefix +# 2. that machine specific files end in .${MACHINE} +# +# The .MAKE.DEPENDFILE_PREFERENCE below is an example. + +# All depend file names should start with this +.MAKE.DEPENDFILE_PREFIX ?= Makefile.depend + +.if !empty(.MAKE.DEPENDFILE) && \ + ${.MAKE.DEPENDFILE:M${.MAKE.DEPENDFILE_PREFIX}*} == "" +# let us do our thing below... +.undef .MAKE.DEPENDFILE +.endif + +# The order of preference: we will use the first one of these we find. +# It usually makes sense to order from most specific to least. +.MAKE.DEPENDFILE_PREFERENCE ?= \ + ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX}.${MACHINE} \ + ${.CURDIR}/${.MAKE.DEPENDFILE_PREFIX} + +# Normally the 1st entry is our default choice +# Another useful default is ${.MAKE.DEPENDFILE_PREFIX} +.MAKE.DEPENDFILE_DEFAULT ?= ${.MAKE.DEPENDFILE_PREFERENCE:[1]} + +_e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@} +.if !empty(_e) +.MAKE.DEPENDFILE := ${_e:[1]} +.elif ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}} != "" && ${.MAKE.DEPENDFILE_DEFAULT:E} != ${MACHINE} +# MACHINE specific depend files are supported, but *not* default. +# If any already exist, we should follow suit. +_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE} +# make sure we restore MACHINE +_m := ${MACHINE} +_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@} +MACHINE := ${_m} +.if !empty(_e) +.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_PREFERENCE:M*${MACHINE}:[1]} +.endif +.endif +.MAKE.DEPENDFILE ?= ${.MAKE.DEPENDFILE_DEFAULT} Index: vendor/NetBSD/bmake/20201101/mk/sys.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/sys.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/sys.mk (revision 367461) @@ -0,0 +1,156 @@ +# $Id: sys.mk,v 1.51 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2003-2009, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# Avoid putting anything platform specific in here. + +# _DEBUG_MAKE_FLAGS etc. +.include + +.if !empty(_DEBUG_MAKE_FLAGS) +.if ${_DEBUG_MAKE_SYS_DIRS:Uno:@x@${.CURDIR:M$x}@} != "" +.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS} +.endif +.endif + +# useful modifiers +.include + +# we expect a recent bmake +.if !defined(_TARGETS) +# some things we do only once +_TARGETS := ${.TARGETS} +.-include +.endif + +# we need HOST_TARGET etc below. +.include + +# early customizations +.-include + +# Popular suffixes for C++ +CXX_SUFFIXES += .cc .cpp .cxx .C +CXX_SUFFIXES := ${CXX_SUFFIXES:O:u} + +# find the OS specifics +.if defined(SYS_OS_MK) +.include <${SYS_OS_MK}> +.else +_sys_mk = +.for x in ${HOST_OSTYPE} ${HOST_TARGET} ${HOST_OS} ${MACHINE} Generic +.if empty(_sys_mk) +.-include +_sys_mk := ${.MAKE.MAKEFILES:M*/$x.mk} +.if !empty(_sys_mk) +_sys_mk := sys/${_sys_mk:T} +.endif +.endif +.if empty(_sys_mk) +# might be an old style +.-include <$x.sys.mk> +_sys_mk := ${.MAKE.MAKEFILES:M*/$x.sys.mk:T} +.endif +.endfor + +SYS_OS_MK := ${_sys_mk} +.export SYS_OS_MK +.endif + +# some options we need to know early +OPTIONS_DEFAULT_NO += \ + DIRDEPS_BUILD \ + DIRDEPS_CACHE + +OPTIONS_DEFAULT_DEPENDENT += \ + AUTO_OBJ/DIRDEPS_BUILD \ + META_MODE/DIRDEPS_BUILD \ + STAGING/DIRDEPS_BUILD \ + STATIC_DIRDEPS_CACHE/DIRDEPS_CACHE \ + +.-include + +.if ${MK_DIRDEPS_BUILD:Uno} == "yes" +MK_META_MODE = yes +.-include +.elif ${MK_META_MODE:Uno} == "yes" +.MAKE.MODE = meta verbose ${META_MODE} +.endif +# make sure we have a harmless value +.MAKE.MODE ?= normal + +# if you want objdirs make them automatic +# and do it early before we compute .PATH +.if ${MK_AUTO_OBJ:Uno} == "yes" || ${MKOBJDIRS:Uno} == "auto" +.include +.endif + +.if !empty(SRCTOP) +.if ${.CURDIR} == ${SRCTOP} +RELDIR = . +.elif ${.CURDIR:M${SRCTOP}/*} +RELDIR := ${.CURDIR:S,${SRCTOP}/,,} +.endif +.endif + +MACHINE_ARCH.host ?= ${_HOST_ARCH} +MACHINE_ARCH.${MACHINE} ?= ${MACHINE} +.if empty(MACHINE_ARCH) +MACHINE_ARCH = ${MACHINE_ARCH.${MACHINE}} +.endif + +.ifndef ROOT_GROUP +ROOT_GROUP != sed -n /:0:/s/:.*//p /etc/group +.export ROOT_GROUP +.endif + +unix ?= We run ${_HOST_OSNAME}. + +# We need a Bourne/POSIX shell +MAKE_SHELL ?= sh +SHELL ?= ${MAKE_SHELL} + +# A race condition in mkdir, means that it can bail if another +# process made a dir that mkdir expected to. +# We repeat the mkdir -p a number of times to try and work around this. +# We stop looping as soon as the dir exists. +# If we get to the end of the loop, a plain mkdir will issue an error. +Mkdirs= Mkdirs() { \ + for d in $$*; do \ + for i in 1 2 3 4 5 6; do \ + mkdir -p $$d; \ + test -d $$d && return 0; \ + done; \ + mkdir $$d || exit $$?; \ + done; } + +# this often helps with debugging +.SUFFIXES: .cpp-out + +.c.cpp-out: + @${COMPILE.c:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$' + +${CXX_SUFFIXES:%=%.cpp-out}: + @${COMPILE.cc:N-c} -E ${.IMPSRC} | grep -v '^[ ]*$$' + +# late customizations +.-include + +# if .CURDIR is matched by any entry in DEBUG_MAKE_DIRS we +# will apply DEBUG_MAKE_FLAGS, now. +.if !empty(_DEBUG_MAKE_FLAGS) +.if ${_DEBUG_MAKE_DIRS:Uno:@x@${.CURDIR:M$x}@} != "" +.MAKEFLAGS: ${_DEBUG_MAKE_FLAGS} +.endif +.endif Index: vendor/NetBSD/bmake/20201101/mk/target-flags.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/target-flags.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/target-flags.mk (revision 367461) @@ -0,0 +1,62 @@ +# NAME: +# target-flags.mk - target specific flags +# +# DESCRIPTION: +# Include this macro file after all others in a makefile and +# follow it with any target specific flag settings. +# For each such variable v in TARGET_FLAG_VARS we set: +#.nf +# +# _$v := ${$v} +# $v = ${${v}_${.TARGET:T}:U${_$v}} +#.fi +# +# This allows one to do things like: +#.nf +# +# TARGET_FLAG_VARS= CFLAGS +# .include +# CFLAGS_fu.o = ${_CFLAGS:N-Wall} +#.fi +# +# To turn off -Wall for just the target fu.o +# Actually CFLAGS is the default value for TARGET_FLAG_VARS. +# +# BUGS: +# One must be careful to avoid creating circular references in +# variables. The original version of this macro file did +# elaborate things with CFLAGS. The current, simpler +# implementation is ultimately more flexible. +# +# It is important that target-flags.mk is included after other +# macro files and that target specific flags that may reference +# _$v are set after that. +# +# Only works with a make(1) that does nested evaluation correctly. + + + +# RCSid: +# $Id: target-flags.mk,v 1.10 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 1998-2002, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +TARGET_FLAG_VARS?= CFLAGS +.for v in ${TARGET_FLAG_VARS} +.ifndef _$v +_$v := ${$v} +$v = ${${v}_${.TARGET:T}:U${_$v}} +.endif +.endfor + Index: vendor/NetBSD/bmake/20201101/mk/warnings.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/warnings.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/warnings.mk (revision 367461) @@ -0,0 +1,139 @@ +# RCSid: +# $Id: warnings.mk,v 1.15 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2002, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.ifndef _w_cflags +# make sure we get the behavior we expect +.MAKE.SAVE_DOLLARS = no + +# Any number of warnings sets can be added. +.-include + +# Modest defaults - put more elaborate sets in warnings-sets.mk +# -Wunused etc are here so you can set +# W_unused=-Wno-unused etc. +MIN_WARNINGS?= -Wall \ + -Wformat \ + -Wimplicit \ + -Wunused \ + -Wuninitialized + +LOW_WARNINGS?= ${MIN_WARNINGS} -W -Wstrict-prototypes -Wmissing-prototypes + +MEDIUM_WARNINGS?= ${LOW_WARNINGS} -Werror + +HIGH_WARNINGS?= ${MEDIUM_WARNINGS} \ + -Wcast-align \ + -Wcast-qual \ + -Wparentheses \ + -Wpointer-arith \ + -Wmissing-declarations \ + -Wreturn-type \ + -Wswitch \ + -Wwrite-strings + +EXTRA_WARNINGS?= ${HIGH_WARNINGS} -Wextra + +# The two step default makes it easier to test build with different defaults. +DEFAULT_WARNINGS_SET?= MIN +WARNINGS_SET?= ${DEFAULT_WARNINGS_SET} + +# There is always someone who wants more... +.if !empty(WARNINGS_XTRAS) +${WARNINGS_SET}_WARNINGS += ${WARNINGS_XTRAS} +.endif + +# If you add sets, besure to list them (you don't have to touch this list). +ALL_WARNINGS_SETS+= MIN LOW MEDIUM HIGH EXTRA + +.if !empty(WARNINGS_SET) +.for ws in ${WARNINGS_SET} +.if empty(${ws}_WARNINGS) +.if ${MAKE_VERSION:[1]:C/.*-//} >= 20050530 +.BEGIN: _empty_warnings +_empty_warnings: .PHONY +.else +.BEGIN: +.endif + @echo "ERROR: Invalid: WARNINGS_SET=${ws}" + @echo "ERROR: Try one of: ${ALL_WARNINGS_SETS:O:u}"; exit 1 + +.endif +.endfor +.endif + +# Without -O or if we've set -O0 somewhere - to make debugging more effective, +# we need to turn off -Wuninitialized as otherwise we get a warning that +# -Werror turns into an error. To be safe, set W_uninitialized blank. +_w_cflags= ${CFLAGS} ${CFLAGS_LAST} ${CPPFLAGS} +.if ${_w_cflags:M-O*} == "" || ${_w_cflags:M-O0} != "" +W_uninitialized= +.endif + + +# .for loops have the [dis]advantage of being evaluated when read, +# so adding to WARNINGS_SET[_${MACHINE_ARCH}] after this file is +# read has no effect. +# Replacing the above .for loops with the WARNINGS+= below solves that +# but tiggers a double free bug in bmake-20040118 and earlier. +# Don't try and read this too fast! +# +# The first :@ "loop" handles multiple sets in WARNINGS_SET +# +# In the second :@ "loop", the ::?= noise sets W_foo?=-Wfoo etc +# which makes it easy to turn off override individual flags +# (see W_uninitialized above). +# +# The last bit expands to ${W_foo_${.TARGET:T}:U${W_foo}} +# which is the bit we ultimately want. It allows W_* to be set on a +# per target basis. +# +# NOTE: that we force the target extension to be .o +# + +# define this once, we use it a couple of times below (hence the doubled $$). +M_warnings_list = @s@$${$$s_WARNINGS}@:O:u:@w@$${$${w:C/-(.)/\1_/}::?=$$w} $${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:R}.o:U$${$${w:C/-(.)/\1_/}_${.TARGET:T:R}.o:U$${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U$${$${w:C/-(.)/\1_/}}}}}@ + +# first a list of warnings from the chosen set +_warnings = ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:${M_warnings_list}} +# now a list of all -Wno-* overrides not just those defined by WARNINGS_SET +# since things like -Wall imply lots of others. +# this should be a super-set of the -Wno-* in _warnings, but +# just in case... +_no_warnings = ${_warnings:M-Wno-*} ${ALL_WARNINGS_SETS:${M_warnings_list}:M-Wno-*} +# -Wno-* must follow any others +WARNINGS += ${_warnings:N-Wno-*} ${_no_warnings:O:u} + +.ifndef NO_CFLAGS_WARNINGS +# Just ${WARNINGS} should do, but this is more flexible? +CFLAGS+= ${WARNINGS_${.TARGET:T:R}.o:U${WARNINGS}} +.endif + +# it is rather silly that g++ blows up on some warning flags +NO_CXX_WARNINGS+= \ + implicit \ + missing-declarations \ + missing-prototypes \ + nested-externs \ + shadow \ + strict-prototypes + +.for s in ${SRCS:M*.c*:N*.c:N*h} +.for w in ${NO_CXX_WARNINGS} +W_$w_${s:T:R}.o= +.endfor +.endfor + +.endif # _w_cflags Index: vendor/NetBSD/bmake/20201101/mk/whats.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/whats.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/whats.mk (revision 367461) @@ -0,0 +1,69 @@ +# $Id: whats.mk,v 1.10 2020/08/19 17:51:53 sjg Exp $ +# +# @(#) Copyright (c) 2014-2020, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +.if ${MK_WHATSTRING:Uno} == "yes" +# it can be useful to embed a what(1) string in binaries +# so that the build location can be seen from a core file. +.if defined(KMOD) +what_thing ?= ${KMOD} +.elif defined(LIB) +what_thing ?= lib${LIB} +.elif defined(PROG) +what_thing ?= ${PROG} +SRCS ?= ${PROG}.c +.elif defined(SHLIB) +what_thing ?= lib${SHLIB} +.endif + +.if !empty(what_thing) +# a unique name that won't conflict with anything +what_uuid = what_${what_thing}_${.CURDIR:T:hash} +what_var = what_${.CURDIR:T:hash} + +SRCS += ${what_uuid}.c +CLEANFILES += ${what_uuid}.c +# we do not need to capture this +SUPPRESS_DEPEND += *${what_uuid}.c + +SB ?= ${SRCTOP:H} +SB_LOCATION ?= ${HOST}:${SB} +# make customization easy +WHAT_LOCATION ?= ${.OBJDIR:S,${SB},${SB_LOCATION},} +WHAT_1 ?= ${what_thing:tu} built ${%Y%m%d:L:localtime} by ${USER} +WHAT_2 ?= ${what_location} +WHAT_LINE_IDS ?= 1 2 +WHAT_NOCMP_LINE_IDS ?= 1 +# you can add other WHAT_* just be sure to set WHAT_LINE_IDS +# and WHAT_NOCMP_LINE_IDS accordingly + +# this works with clang and gcc +what_t = const char __attribute__ ((section(".data"))) +what_location := ${WHAT_LOCATION} + +# this script is done in multiple lines so we can +# use the token ${.OODATE:MNO_META_CMP} +# to prevent the variable parts making this constantly out-of-date +${what_uuid}.c: + echo 'extern const char ${WHAT_LINE_IDS:@i@${what_var}_$i[]@:ts,};' > $@ +.for i in ${WHAT_LINE_IDS} +.if ${WHAT_NOCMP_LINE_IDS:M$i} != "" + echo '${what_t} ${what_var}_$i[] = "@(#)${WHAT_$i}";' >> $@ ${.OODATE:MNO_META_CMP} +.else + echo '${what_t} ${what_var}_$i[] = "@(#)${WHAT_$i}";' >> $@ +.endif +.endfor + +.endif +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/whats.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/yacc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/yacc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/yacc.mk (revision 367461) @@ -0,0 +1,57 @@ +# $Id: yacc.mk,v 1.7 2020/08/19 17:51:53 sjg Exp $ + +# +# @(#) Copyright (c) 1999-2011, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# this file contains rules to DTRT when SRCS contains foo.y or foo.c +# when only a foo.y exists. + +YACC?= yacc +YFLAGS?= -v -t +RM?= rm + +YACC.y?= ${YACC} ${YFLAGS} + +.if ${YACC.y:M-d} == "" || defined(NO_RENAME_Y_TAB_H) + +.y.c: + ${YACC.y} ${.IMPSRC} + [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET} + ${RM} -f y.tab.[!h] + +.else + +# the touch of the .c is to ensure it is newer than .h (paranoia) +.y.h: + ${YACC.y} ${.IMPSRC} + [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET:T:R}.c + [ ! -s y.tab.h ] || cmp -s y.tab.h ${.TARGET:T:R}.h \ + || mv y.tab.h ${.TARGET:T:R}.h + touch ${.TARGET:T:R}.c + ${RM} -f y.tab.* + +# Normally the .y.h rule does the work - to avoid races. +# If for any reason the .c is lost but the .h remains, +# regenerate the .c +.y.c: ${.TARGET:T:R}.h + [ -s ${.TARGET} ] || { \ + ${YACC.y} ${.IMPSRC} && \ + { [ ! -s y.tab.c ] || mv y.tab.c ${.TARGET}; \ + ${RM} y.tab.*; }; } +.endif + +beforedepend: ${SRCS:T:M*.y:S/.y/.c/g} + +CLEANFILES+= ${SRCS:T:M*.y:S/.y/.[ch]/g} +CLEANFILES+= y.tab.[ch] Index: vendor/NetBSD/bmake/20201101/mk/doc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/doc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/doc.mk (revision 367461) @@ -0,0 +1,64 @@ +# $Id: doc.mk,v 1.7 2019/06/09 16:22:08 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.include + +BIB?= bib +EQN?= eqn +GREMLIN?= grn +GRIND?= vgrind -f +INDXBIB?= indxbib +PIC?= pic +REFER?= refer +ROFF?= groff -M/usr/share/tmac ${MACROS} ${PAGES} +SOELIM?= soelim +TBL?= tbl + +.PATH: ${.CURDIR} + +.if !defined(_SKIP_BUILD) +realbuild: paper.ps +.endif + +.if !target(paper.ps) +paper.ps: ${SRCS} + ${ROFF} ${SRCS} > ${.TARGET} +.endif + +.if !target(print) +print: paper.ps + lpr -P${PRINTER} paper.ps +.endif + +.if !target(manpages) +manpages: +.endif + +.if !target(obj) +obj: +.endif + +clean cleandir: + rm -f paper.* [eE]rrs mklog ${CLEANFILES} + +.if ${MK_DOC} == "no" +install: +.else +FILES?= ${SRCS} +install: + test -d ${DESTDIR}${DOCDIR}/${DIR} || \ + ${INSTALL} -d ${DOC_INSTALL_OWN} -m ${DIRMODE} ${DESTDIR}${DOCDIR}/${DIR} + ${INSTALL} ${COPY} ${DOC_INSTALL_OWN} -m ${DOCMODE} \ + Makefile ${FILES} ${EXTRA} ${DESTDIR}${DOCDIR}/${DIR} +.endif + +spell: ${SRCS} + spell ${SRCS} | sort | comm -23 - spell.ok > paper.spell + +.if !empty(DOCOWN) +DOC_INSTALL_OWN?= -o ${DOCOWN} -g ${DOCGRP} +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/ldorder.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/ldorder.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/ldorder.mk (revision 367461) @@ -0,0 +1,156 @@ +# $Id: ldorder.mk,v 1.25 2018/04/24 23:50:26 sjg Exp $ +# +# @(#) Copyright (c) 2015, Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# Try to compute optimal link order. +# When using only shared libs link order does not much matter, +# but archive libs are a different matter. + +# We can construct a graph of .ldorder-lib${LIB*} dependencies +# and associate each with _LDORDER_USE to output the relevant +# ld flags. +# Due to the nature of make, the result will be in the reverse order +# that we want to feed to ld. +# So we need to reverse it before use. + +.if !target(_LDORDER_USE) +# does caller want to use ldorder? +# yes for prog, normally no for lib +.if ${.ALLTARGETS:Mldorder} != "" +_ldorder_use: +.endif + +# define this if we need a barrier between local and external libs +# see below +LDORDER_EXTERN_BARRIER ?= .ldorder-extern-barrier + +.-include + +# convert /path/to/libfoo.a into _{LIBFOO} +LDORDER_INC_FILTER += S,+,PLUS,g S,.so$$,,g +LDORDER_LIBS_FILTER += O:u +LDORDER_INC ?= ldorder.inc +# for meta mode +REFERENCE_FILE ?= : + +_LDORDER_USE: .ldorder-rm .USE .NOTMAIN + @echo depends: ${.ALLSRC:M.ldorder-lib*} > /dev/null + @echo ${LDADD_${.TARGET:T:S,.ldorder-,,}:U${.TARGET:T:S/.ldorder-lib/-l/}} >> .ldorder + @${META_COOKIE_TOUCH} + +# we need to truncate our working file +.ldorder-rm: .NOTMAIN + @rm -f .ldorder ldorder-* + @${.ALLSRC:O:u:@f@${REFERENCE_FILE} < $f;@} + @${META_COOKIE_TOUCH} + +# make sure this exists +.ldorder: .NOTMAIN + +# and finally we need to reverse the order of content +ldorder: .ldorder .NOTMAIN + @{ test ! -s .ldorder || cat -n .ldorder | sort -rn | \ + sed '/ldorder-/d;s,^[[:space:]0-9]*,,'; } > ${.TARGET} + +# Initially we hook contents of DPLIBS and DPADD into our graph +LDORDER_LIBS ?= ${DPLIBS} ${DPADD:M*/lib*} ${__dpadd_libs} +# we need to remember this +_LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}} + +.if empty(_LDORDER_LIBS) +# don't use stale ldorder +LDADD_LDORDER = +.else +# this is how you use it +LDADD_LDORDER ?= `cat ldorder` +.endif + +# for debug below +_ldorder = ${RELDIR}.${TARGET_SPEC} + +# we make have some libs that exist outside of $SB +# and want to insert a barrier +.if target(${LDORDER_EXTERN_BARRIER}) +# eg. in local.ldorder.mk +# ${LDORDER_EXTERN_BARRIER}: +# @test -z "${extern_ldorders}" || \ +# echo -Wl,-Bdynamic >> .ldorder +# +# feel free to put more suitable version in local.ldorder.mk if needed +# we do *not* count host libs in extern_ldorders +extern_ldorders ?= ${__dpadd_libs:tA:N/lib*:N/usr/lib*:N${SB}/*:N${SB_OBJROOT:tA}*:T:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//:S,^,.ldorder-,:N.ldorder-} +sb_ldorders ?= ${.ALLTARGETS:M.ldorder-*:N${LDORDER_EXTERN_BARRIER}:N.ldorder-rm:${extern_ldorders:${M_ListToSkip}}:N.ldorder-} + +# finally in Makefile after include of *.mk put +# .ldorder ${sb_ldorders}: ${LDORDER_EXTERN_BARRIER} +# ${LDORDER_EXTERN_BARRIER}: ${extern_ldorders} +.endif + +.endif # !target(_LDORDER_USE) + +.if !empty(LDORDER_LIBS) && target(_ldorder_use) +# canonicalize - these are just tokens anyway +LDORDER_LIBS := ${LDORDER_LIBS:${LDORDER_LIBS_FILTER:ts:}:R:C/\.so.*//} +_ldorders := ${LDORDER_LIBS:T:Mlib*:S,^,.ldorder-,} + +.for t in ${_ldorders} +.if !target($t) +$t: _LDORDER_USE +.endif +.endfor + +# and this makes it all happen +.ldorder: ${_ldorders} + +# this is how we get the dependencies +.if ${.INCLUDEDFROMFILE:M*.${LDORDER_INC}} != "" +_ldorder := .ldorder-${.INCLUDEDFROMFILE:S/.${LDORDER_INC}//} +${_ldorder}: ${_ldorders} +.ldorder-rm: ${.INCLUDEDFROMDIR}/${.INCLUDEDFROMFILE} +.endif + +# set DEBUG_LDORDER to pattern[s] that match the dirs of interest +.if ${DEBUG_LDORDER:Uno:@x@${RELDIR:M$x}@} != "" +.info ${_ldorder}: ${_ldorders} +.endif + +# now try to find more ... +# each *.${LDORDER_INC} should set LDORDER_LIBS to what it needs +# it can also add to CFLAGS etc. +.for __inc in ${LDORDER_LIBS:S,$,.${LDORDER_INC},} +.if !target(__${__inc}__) +__${__inc}__: +# make sure this is reset +LDORDER_LIBS = +_ldorders = +.-include <${__inc}> +.endif +.endfor + +.endif # !empty(LDORDER_LIBS) + +.ifdef LIB +# you can make this depend on files (must match *ldorder*) +# to add extra content - like CFLAGS +libLDORDER_INC = lib${LIB}.${LDORDER_INC} +.if !commands(${libLDORDER_INC}) +.if target(ldorder-header) +${libLDORDER_INC}: ldorder-header +.endif +${libLDORDER_INC}: + @(cat /dev/null ${.ALLSRC:M*ldorder*}; \ + echo 'LDORDER_LIBS= ${_LDORDER_LIBS:T:R:${LDORDER_INC_FILTER:ts:}:tu:C,.*,_{&},:N_{}}'; \ + echo; echo '.include ' ) | sed 's,_{,$${,g' > ${.TARGET} +.endif +.endif Property changes on: vendor/NetBSD/bmake/20201101/mk/ldorder.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mk/final.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/final.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/final.mk (revision 367461) @@ -0,0 +1,22 @@ +# $Id: final.mk,v 1.9 2018/01/24 22:57:11 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# provide a hook for folk who want to do scary stuff +.-include <${.CURDIR:H}/Makefile-final.inc> + +.-include + +.if ${MK_STAGING} == "yes" +.include +.elif !empty(STAGE) +.-include +.endif + +.if empty(_SKIP_BUILD) +install: realinstall +.endif +realinstall: + +.endif Index: vendor/NetBSD/bmake/20201101/mk/subdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/subdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/subdir.mk (revision 367461) @@ -0,0 +1,102 @@ +# $Id: subdir.mk,v 1.16 2017/02/08 22:16:59 sjg Exp $ +# skip missing directories... + +# $NetBSD: bsd.subdir.mk,v 1.11 1996/04/04 02:05:06 jtc Exp $ +# @(#)bsd.subdir.mk 5.9 (Berkeley) 2/1/91 + +.if ${.MAKE.LEVEL} == 0 && ${.MAKE.MODE:Uno:Mmeta*} != "" +.include +# keep everyone happy +_SUBDIRUSE: +.elif !commands(_SUBDIRUSE) && !defined(NO_SUBDIR) && !defined(NOSUBDIR) +.-include <${.CURDIR}/Makefile.inc> +.if !target(.MAIN) +.MAIN: all +.endif + +ECHO_DIR ?= echo +.ifdef SUBDIR_MUST_EXIST +MISSING_DIR=echo "Missing ===> ${.CURDIR}/$${entry}"; exit 1 +.else +MISSING_DIR=echo "Skipping ===> ${.CURDIR}/$${entry}"; continue +.endif + +_SUBDIRUSE: .USE +.if defined(SUBDIR) + @Exists() { test -f $$1; }; \ + for entry in ${SUBDIR}; do \ + (set -e; \ + if Exists ${.CURDIR}/$${entry}.${MACHINE}/[mM]akefile; then \ + _newdir_="$${entry}.${MACHINE}"; \ + elif Exists ${.CURDIR}/$${entry}/[mM]akefile; then \ + _newdir_="$${entry}"; \ + else \ + ${MISSING_DIR}; \ + fi; \ + if test X"${_THISDIR_}" = X""; then \ + _nextdir_="$${_newdir_}"; \ + else \ + _nextdir_="$${_THISDIR_}/$${_newdir_}"; \ + fi; \ + ${ECHO_DIR} "===> $${_nextdir_}"; \ + cd ${.CURDIR}/$${_newdir_}; \ + ${.MAKE} _THISDIR_="$${_nextdir_}" \ + ${.TARGET:S/realinstall/install/:S/.depend/depend/}) || exit 1; \ + done + +${SUBDIR}:: + @set -e; _r=${.CURDIR}/; \ + if test -z "${.TARGET:M/*}"; then \ + if test -d ${.CURDIR}/${.TARGET}.${MACHINE}; then \ + _newdir_=${.TARGET}.${MACHINE}; \ + else \ + _newdir_=${.TARGET}; \ + fi; \ + else \ + _r= _newdir_=${.TARGET}; \ + fi; \ + ${ECHO_DIR} "===> $${_newdir_}"; \ + cd $${_r}$${_newdir_}; \ + ${.MAKE} _THISDIR_="$${_newdir_}" all +.endif + +.if !target(install) +.if !target(beforeinstall) +beforeinstall: +.endif +.if !target(afterinstall) +afterinstall: +.endif +install: maninstall +maninstall: afterinstall +afterinstall: realinstall +realinstall: beforeinstall _SUBDIRUSE +.endif + +.if defined(SRCS) +etags: ${SRCS} + -cd ${.CURDIR}; etags `echo ${.ALLSRC:N*.h} | sed 's;${.CURDIR}/;;'` +.endif + +SUBDIR_TARGETS += \ + all \ + clean \ + cleandir \ + includes \ + depend \ + lint \ + obj \ + tags \ + etags + +.for t in ${SUBDIR_TARGETS:O:u} +$t: _SUBDIRUSE +.endfor + +.include +.if make(destroy*) +.include +.endif +.endif +# make sure this exists +all: Index: vendor/NetBSD/bmake/20201101/mk/nls.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/nls.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/nls.mk (revision 367461) @@ -0,0 +1,47 @@ +# $NetBSD: bsd.nls.mk,v 1.3 1996/10/18 02:34:45 thorpej Exp $ + +.if !target(.MAIN) +# init.mk not included +.-include <${.CURDIR:H}/Makefile.inc> + +.MAIN: all +.endif + +.SUFFIXES: .cat .msg + +.msg.cat: + @rm -f ${.TARGET} + gencat ${.TARGET} ${.IMPSRC} + +.if defined(NLS) && !empty(NLS) +NLSALL= ${NLS:.msg=.cat} +.NOPATH: ${NLSALL} +.endif + +.if !defined(NLSNAME) +.if defined(PROG) +NLSNAME=${PROG} +.else +NLSNAME=lib${LIB} +.endif +.endif + +nlsinstall: +.if defined(NLSALL) + @for msg in ${NLSALL}; do \ + NLSLANG=`basename $$msg .cat`; \ + dir=${DESTDIR}${NLSDIR}/$${NLSLANG}; \ + ${INSTALL} -d $$dir; \ + ${INSTALL} ${COPY} -o ${NLSOWN} -g ${NLSGRP} -m ${NLSMODE} $$msg $$dir/${NLSNAME}.cat; \ + done +.endif + +.if defined(NLSALL) +all: ${NLSALL} + +install: nlsinstall + +cleandir: cleannls +cleannls: + rm -f ${NLSALL} +.endif Index: vendor/NetBSD/bmake/20201101/mk/dep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/dep.mk (revision 367461) @@ -0,0 +1,127 @@ +# $Id: dep.mk,v 1.17 2014/08/04 05:12:27 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +# handle Proc*C as well... +.if defined(SRCS) +.if !empty(SRCS:M*.pc) +.include +.endif + +# it would be nice to be able to query .SUFFIXES +OBJ_EXTENSIONS+= .o .po .lo .So + +# explicit dependencies help short-circuit .SUFFIX searches +SRCS_DEP_FILTER+= N*.[hly] +.for s in ${SRCS:${SRCS_DEP_FILTER:O:u:ts:}} +.for e in ${OBJ_EXTENSIONS:O:u} +.if !target(${s:T:R}$e) +${s:T:R}$e: $s +.endif +.endfor +.endfor +.endif + +.if exists(/usr/bin/mkdep) +MKDEP_CMD?= mkdep +.elif exists(/usr/local/share/bin/mkdeps.sh) +MKDEP_CMD?= /usr/local/share/bin/mkdeps.sh -N +.endif +MKDEP_CMD?= mkdep + +MKDEP ?= ${MKDEP_CMD} + +.NOPATH: .depend + +.if ${MKDEP_MK:Uno} == "auto.dep.mk" && make(depend) +# auto.dep.mk does not "do" depend +MK_AUTODEP= no +.endif + +.if ${MK_AUTODEP} == yes +MKDEP_MK ?= autodep.mk +.include <${MKDEP_MK}> +.else +MKDEP_ENV_VARS += CC CXX +.for v in ${MKDEP_ENV_VARS:O:u} +.if !empty($v) +MKDEP_ENV += $v='${$v}' +.endif +.endfor + +_MKDEP = ${MKDEP_ENV} ${MKDEP} + +# some of the rules involve .h sources, so remove them from mkdep line +.if !target(depend) +depend: beforedepend .depend _SUBDIRUSE afterdepend + +.if defined(SRCS) +# libs can have too many SRCS for a single command line +# so do them one at a time. +.depend: ${SRCS} ${.PARSEDIR}/${.PASEFILE} + @rm -f .depend +.ifdef LIB + @files="${.ALLSRC:M*.[sS]}"; \ + set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$f; done + @files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \ + set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done + @files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \ + set -x; for f in $$files; do ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$f; done +.else + @files="${.ALLSRC:M*.[Ss]}"; \ + case "$$files" in *.[Ss]*) \ + echo ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files; \ + ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} ${AINC} $$files;; \ + esac + @files="${.ALLSRC:M*.c} ${.ALLSRC:M*.pc:T:.pc=.c}"; \ + case "$$files" in *.c*) \ + echo ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \ + ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \ + esac + @files="${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cxx}"; \ + case "$$files" in *.[Cc]*) \ + echo ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files; \ + ${_MKDEP} -a ${MKDEPFLAGS} \ + ${CXXFLAGS:M-[ID]*} ${CPPFLAGS} $$files;; \ + esac +.endif +.else +.depend: +.endif +.if !target(beforedepend) +beforedepend: +.endif +.if !target(afterdepend) +afterdepend: +.endif +.endif +.endif + +.if !target(tags) +.if defined(SRCS) +tags: ${SRCS} _SUBDIRUSE + -cd ${.CURDIR}; ctags -f /dev/stdout ${.ALLSRC:N*.h} | \ + sed "s;\${.CURDIR}/;;" > tags +.else +tags: +.endif +.endif + +.if defined(SRCS) +cleandir: cleandepend +.if !target(cleandepend) +cleandepend: + rm -f .depend ${.CURDIR}/tags +.endif +.endif + +.endif Index: vendor/NetBSD/bmake/20201101/mk/man.mk =================================================================== --- vendor/NetBSD/bmake/20201101/mk/man.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/mk/man.mk (revision 367461) @@ -0,0 +1,137 @@ +# $Id: man.mk,v 1.20 2012/12/13 01:51:01 sjg Exp $ + +.if !target(__${.PARSEFILE}__) +__${.PARSEFILE}__: + +.include + +# unlike bsd.man.mk we handle 3 approaches +# 1. install unformated nroff (default) +# 2. install formatted pages +# 3. install formatted pages but with extension of .0 +# sadly we cannot rely on a shell that supports ${foo#...} and ${foo%...} +# so we have to use sed(1). + +# set MANTARGET=cat for formatted pages +MANTARGET?= man +# set this to .0 for same behavior as bsd.man.mk +MCATEXT?= + +NROFF?= nroff +MANDIR?= /usr/share/man +MANDOC?= man + +.SUFFIXES: .1 .2 .3 .4 .5 .6 .7 .8 .9 .cat1 .cat2 .cat3 .cat4 .cat5 .cat6 \ + .cat7 .cat8 .cat9 + +.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3.cat3 .2.cat2 .1.cat1: + @echo "${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T}" + @${NROFF} -${MANDOC} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false ) + +.if defined(MAN) && !empty(MAN) + +# we use cmt2doc.pl to extract manpages from source +# this is triggered by the setting of EXTRACT_MAN or MAN being set but +# not existsing. + +.if !exists(${MAN:[1]}) && !target(${MAN:[1]}) +.if defined(EXTRACT_MAN) && ${EXTRACT_MAN} == "no" +MAN= +.else +.if exists(/usr/local/share/bin/cmt2doc.pl) +CMT2DOC?= cmt2doc.pl +CMT2DOC_OPTS?= ${CMT2DOC_ORGOPT} -pmS${.TARGET:E} +.endif +.ifdef CMT2DOC +.c.8 .c.5 .c.3 .c.4 .c.1 \ + .cc.8 .cc.5 .cc.3 .cc.4 .cc.1 \ + .h.8 .h.5 .h.3 .h.4 .h.1 \ + .sh.8 .sh.5 .sh.3 .sh.4 .sh.1 \ + .pl.8 .pl.5 .pl.3 .pl.4 .pl.1: + @echo "${CMT2DOC} ${.IMPSRC} > ${.TARGET:T}" + @${CMT2DOC} ${CMT2DOC_OPTS} ${.IMPSRC} > ${.TARGET:T} || ( rm -f ${.TARGET:T} ; false ) +.else +MAN= +.endif +.endif +.endif + +_mandir=${DESTDIR}${MANDIR}/${MANTARGET}`echo $$page | sed -e 's/.*\.cat/./' -e 's/.*\.//'` +.if ${MANTARGET} == "cat" +_mfromdir?=. +MANALL= ${MAN:S/.1$/.cat1/g:S/.2$/.cat2/g:S/.3$/.cat3/g:S/.4$/.cat4/g:S/.5$/.cat5/g:S/.6$/.cat6/g:S/.7$/.cat7/g:S/.8$/.cat8/g:S/.9$/.cat9/g} +.if ${MCATEXT} == "" +_minstpage=`echo $$page | sed 's/\.cat/./'` +.else +_minstpage=`echo $$page | sed 's/\.cat.*//'`${MCATEXT} +.endif +.endif +.if target(${MAN:[1]}) +_mfromdir?=. +.endif +_mfromdir?=${.CURDIR} +MANALL?= ${MAN} +_minstpage?=$${page} +.endif + +.if !empty(MANOWN) +MAN_INSTALL_OWN ?= -o ${MANOWN} -g ${MANGRP} +MAN_CHOWN ?= chown +.else +MAN_CHOWN = : +.endif + +MINSTALL= ${INSTALL} ${COPY} ${MAN_INSTALL_OWN} -m ${MANMODE} +.if defined(MANZ) +# chown and chmod are done afterward automatically +MCOMPRESS= gzip -cf +MCOMPRESSSUFFIX= .gz +.endif + +maninstall: +.if defined(MANALL) && !empty(MANALL) + @for page in ${MANALL:T}; do \ + test -s ${_mfromdir}/$$page || continue; \ + dir=${_mandir}; \ + test -d $$dir || ${INSTALL} -d ${MAN_INSTALL_OWN} -m 775 $$dir; \ + instpage=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \ + if [ X"${MCOMPRESS}" = X ]; then \ + echo ${MINSTALL} ${_mfromdir}/$$page $$instpage; \ + ${MINSTALL} ${_mfromdir}/$$page $$instpage; \ + else \ + rm -f $$instpage; \ + echo ${MCOMPRESS} ${_mfromdir}/$$page \> $$instpage; \ + ${MCOMPRESS} ${_mfromdir}/$$page > $$instpage; \ + ${MAN_CHOWN} ${MANOWN}:${MANGRP} $$instpage; \ + chmod ${MANMODE} $$instpage; \ + fi \ + done +.if defined(MLINKS) && !empty(MLINKS) + @set ${MLINKS}; \ + while test $$# -ge 2; do \ + page=$$1; \ + shift; \ + dir=${_mandir}; \ + l=${_minstpage}${MCOMPRESSSUFFIX}; \ + page=$$1; \ + shift; \ + dir=${_mandir}; \ + t=$${dir}${MANSUBDIR}/${_minstpage}${MCOMPRESSSUFFIX}; \ + echo $$t -\> $$l; \ + rm -f $$t; \ + ln -s $$l $$t; \ + done +.endif +.endif + +.if defined(MANALL) && !empty(MANALL) +manall: ${MANALL} +all: manall +.endif + +.if defined(CLEANMAN) && !empty(CLEANMAN) +cleandir: cleanman +cleanman: + rm -f ${CLEANMAN} +.endif +.endif Index: vendor/NetBSD/bmake/20201101/nonints.h =================================================================== --- vendor/NetBSD/bmake/20201101/nonints.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/nonints.h (revision 367461) @@ -0,0 +1,315 @@ +/* $NetBSD: nonints.h,v 1.149 2020/11/01 00:24:57 rillig Exp $ */ + +/*- + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)nonints.h 8.3 (Berkeley) 3/19/94 + */ + +/*- + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)nonints.h 8.3 (Berkeley) 3/19/94 + */ + +/* arch.c */ +void Arch_Init(void); +void Arch_End(void); + +Boolean Arch_ParseArchive(char **, GNodeList *, GNode *); +void Arch_Touch(GNode *); +void Arch_TouchLib(GNode *); +time_t Arch_MTime(GNode *); +time_t Arch_MemMTime(GNode *); +void Arch_FindLib(GNode *, SearchPath *); +Boolean Arch_LibOODate(GNode *); +Boolean Arch_IsLib(GNode *); + +/* compat.c */ +int Compat_RunCommand(const char *, GNode *); +void Compat_Run(GNodeList *); +void Compat_Make(GNode *, GNode *); + +/* cond.c */ +CondEvalResult Cond_EvalCondition(const char *, Boolean *); +CondEvalResult Cond_EvalLine(const char *); +void Cond_restore_depth(unsigned int); +unsigned int Cond_save_depth(void); + +/* for.c */ +int For_Eval(const char *); +Boolean For_Accum(const char *); +void For_Run(int); + +/* job.c */ +#ifdef WAIT_T +void JobReapChild(pid_t, WAIT_T, Boolean); +#endif + +/* main.c */ +void Main_ParseArgLine(const char *); +void MakeMode(const char *); +char *Cmd_Exec(const char *, const char **); +void Error(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); +void Fatal(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD; +void Punt(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2) MAKE_ATTR_DEAD; +void DieHorribly(void) MAKE_ATTR_DEAD; +void Finish(int) MAKE_ATTR_DEAD; +int eunlink(const char *); +void execDie(const char *, const char *); +char *getTmpdir(void); +Boolean s2Boolean(const char *, Boolean); +Boolean getBoolean(const char *, Boolean); +char *cached_realpath(const char *, char *); + +/* parse.c */ +void Parse_Init(void); +void Parse_End(void); + +typedef enum VarAssignOp { + VAR_NORMAL, /* = */ + VAR_SUBST, /* := */ + VAR_SHELL, /* != or :sh= */ + VAR_APPEND, /* += */ + VAR_DEFAULT /* ?= */ +} VarAssignOp; + +typedef struct VarAssign { + char *varname; /* unexpanded */ + VarAssignOp op; + const char *value; /* unexpanded */ +} VarAssign; + +typedef char *(*NextBufProc)(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 *); +void Parse_AddIncludeDir(const char *); +void Parse_File(const char *, int); +void Parse_SetInput(const char *, int, int, NextBufProc, void *); +GNodeList *Parse_MainName(void); +int Parse_GetFatals(void); + +/* str.c */ +typedef struct Words { + char **words; + size_t len; + void *freeIt; +} Words; + +Words Str_Words(const char *, Boolean); +static inline MAKE_ATTR_UNUSED 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 */ +size_t strlcpy(char *, const char *, size_t); +#endif + +/* suff.c */ +void Suff_Init(void); +void Suff_End(void); + +void Suff_ClearSuffixes(void); +Boolean 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_AddInclude(const char *); +void Suff_AddLib(const char *); +void Suff_FindDeps(GNode *); +SearchPath *Suff_FindPath(GNode *); +void Suff_SetNull(const char *); +void Suff_PrintAll(void); + +/* targ.c */ +void Targ_Init(void); +void Targ_End(void); + +void Targ_Stats(void); +GNodeList *Targ_List(void); +GNode *Targ_NewGN(const char *); +GNode *Targ_FindNode(const char *); +GNode *Targ_GetNode(const char *); +GNode *Targ_NewInternalNode(const char *); +GNode *Targ_GetEndNode(void); +GNodeList *Targ_FindList(StringList *); +Boolean Targ_Ignore(GNode *); +Boolean Targ_Silent(GNode *); +Boolean Targ_Precious(GNode *); +void Targ_SetMain(GNode *); +void Targ_PrintCmds(GNode *); +void Targ_PrintNode(GNode *, int); +void Targ_PrintNodes(GNodeList *, int); +char *Targ_FmtTime(time_t); +void Targ_PrintType(int); +void Targ_PrintGraph(int); +void Targ_Propagate(void); + +/* var.c */ +void Var_Init(void); +void Var_End(void); + +typedef enum VarEvalFlags { + VARE_NONE = 0, + /* Treat undefined variables as errors. */ + VARE_UNDEFERR = 0x01, + /* Expand and evaluate variables during parsing. */ + VARE_WANTRES = 0x02, + /* In an assignment using the ':=' operator, keep '$$' as '$$' instead + * of reducing it to a single '$'. */ + VARE_ASSIGN = 0x04 +} VarEvalFlags; + +typedef enum VarSet_Flags { + VAR_NO_EXPORT = 0x01, /* do not export */ + /* Make the variable read-only. No further modification is possible, + * except for another call to Var_Set with the same flag. */ + VAR_SET_READONLY = 0x02 +} VarSet_Flags; + +/* The state of error handling returned by Var_Parse. + * + * As of 2020-09-13, this bitset looks quite bloated, + * with all the constants doubled. + * + * Its purpose is to first document the existing behavior, + * and then migrate away from the SILENT constants, step by step, + * as these are not suited for reliable, consistent error handling + * and reporting. */ +typedef enum VarParseResult { + + /* Both parsing and evaluation succeeded. */ + VPR_OK = 0x0000, + + /* See if a message has already been printed for this error. */ + VPR_ANY_MSG = 0x0001, + + /* Parsing failed. + * No error message has been printed yet. + * Deprecated, migrate to VPR_PARSE_MSG instead. */ + VPR_PARSE_SILENT = 0x0002, + + /* Parsing failed. + * An error message has already been printed. */ + VPR_PARSE_MSG = VPR_PARSE_SILENT | VPR_ANY_MSG, + + /* Parsing succeeded. + * During evaluation, VARE_UNDEFERR was set and there was an undefined + * variable. + * No error message has been printed yet. + * Deprecated, migrate to VPR_UNDEF_MSG instead. */ + VPR_UNDEF_SILENT = 0x0004, + + /* Parsing succeeded. + * During evaluation, VARE_UNDEFERR was set and there was an undefined + * variable. + * An error message has already been printed. */ + VPR_UNDEF_MSG = VPR_UNDEF_SILENT | VPR_ANY_MSG, + + /* Parsing succeeded. + * Evaluation failed. + * No error message has been printed yet. + * Deprecated, migrate to VPR_EVAL_MSG instead. */ + VPR_EVAL_SILENT = 0x0006, + + /* Parsing succeeded. + * Evaluation failed. + * An error message has already been printed. */ + VPR_EVAL_MSG = VPR_EVAL_SILENT | VPR_ANY_MSG, + + /* The exact error handling status is not known yet. + * Deprecated, migrate to VPR_OK or any VPE_*_MSG instead. */ + VPR_UNKNOWN = 0x0008 +} VarParseResult; + +void Var_Delete(const char *, GNode *); +void Var_Set(const char *, const char *, GNode *); +void Var_Set_with_flags(const char *, const char *, GNode *, VarSet_Flags); +void Var_Append(const char *, const char *, GNode *); +Boolean Var_Exists(const char *, GNode *); +const char *Var_Value(const char *, GNode *, void **); +const char *Var_ValueDirect(const char *, GNode *); +VarParseResult Var_Parse(const char **, GNode *, VarEvalFlags, + const char **, void **); +VarParseResult Var_Subst(const char *, GNode *, VarEvalFlags, char **); +void Var_Stats(void); +void Var_Dump(GNode *); +void Var_ExportVars(void); +void Var_Export(const char *, Boolean); +void Var_UnExport(const char *); + +/* util.c */ +typedef void (*SignalProc)(int); +SignalProc bmake_signal(int, SignalProc); Property changes on: vendor/NetBSD/bmake/20201101/nonints.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/parse.c =================================================================== --- vendor/NetBSD/bmake/20201101/parse.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/parse.c (revision 367461) @@ -0,0 +1,3246 @@ +/* $NetBSD: parse.c,v 1.420 2020/11/01 00:24:57 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Parsing of makefiles. + * + * Parse_File is the main entry point and controls most of the other + * functions in this module. + * + * The directories for the .include "..." directive are kept in + * 'parseIncPath', while those for .include <...> are kept in 'sysIncPath'. + * The targets currently being defined are kept in 'targets'. + * + * Interface: + * Parse_Init Initialize the module + * + * Parse_End Clean up the module + * + * Parse_File Parse a top-level makefile. Included files are + * handled by Parse_include_file though. + * + * Parse_IsVar Return TRUE if the given line is a variable + * assignment. Used by MainParseArgs to determine if + * an argument is a target or a variable assignment. + * Used internally for pretty much the same thing. + * + * Parse_Error Report a parse error, a warning or an informational + * message. + * + * Parse_MainName Returns a list of the main target to create. + */ + +#include +#include +#include +#include + +#include "make.h" + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_MMAP +#include + +#ifndef MAP_COPY +#define MAP_COPY MAP_PRIVATE +#endif +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#endif + +#include "dir.h" +#include "job.h" +#include "pathnames.h" + +/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: parse.c,v 1.420 2020/11/01 00:24:57 rillig Exp $"); + +/* types and constants */ + +/* + * Structure for a file being read ("included file") + */ +typedef struct IFile { + char *fname; /* name of file */ + Boolean fromForLoop; /* simulated .include by the .for loop */ + int lineno; /* current line number in file */ + int first_lineno; /* line number of start of text */ + unsigned int cond_depth; /* 'if' nesting when file opened */ + Boolean depending; /* state of doing_depend on EOF */ + + /* The buffer from which the file's content is read. */ + char *buf_freeIt; + char *buf_ptr; /* next char to be read */ + char *buf_end; + + char *(*nextbuf)(void *, size_t *); /* Function to get more data */ + void *nextbuf_arg; /* Opaque arg for nextbuf() */ + struct loadedfile *lf; /* loadedfile object, if any */ +} IFile; + +/* + * Tokens for target attributes + */ +typedef enum ParseSpecial { + SP_ATTRIBUTE, /* Generic attribute */ + SP_BEGIN, /* .BEGIN */ + SP_DEFAULT, /* .DEFAULT */ + SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */ + SP_END, /* .END */ + SP_ERROR, /* .ERROR */ + SP_IGNORE, /* .IGNORE */ + SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */ + SP_INTERRUPT, /* .INTERRUPT */ + SP_LIBS, /* .LIBS; not mentioned in the manual page */ + SP_MAIN, /* .MAIN and we don't have anything user-specified to + * make */ + SP_META, /* .META */ + SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */ + SP_NOMETA, /* .NOMETA */ + SP_NOMETA_CMP, /* .NOMETA_CMP */ + SP_NOPATH, /* .NOPATH */ + SP_NOT, /* Not special */ + SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */ + SP_NULL, /* .NULL; not mentioned in the manual page */ + SP_OBJDIR, /* .OBJDIR */ + SP_ORDER, /* .ORDER */ + SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */ + SP_PATH, /* .PATH or .PATH.suffix */ + SP_PHONY, /* .PHONY */ +#ifdef POSIX + SP_POSIX, /* .POSIX; not mentioned in the manual page */ +#endif + SP_PRECIOUS, /* .PRECIOUS */ + SP_SHELL, /* .SHELL */ + SP_SILENT, /* .SILENT */ + SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */ + SP_STALE, /* .STALE */ + SP_SUFFIXES, /* .SUFFIXES */ + SP_WAIT /* .WAIT */ +} ParseSpecial; + +typedef List SearchPathList; +typedef ListNode SearchPathListNode; + +/* result data */ + +/* + * The main target to create. This is the first target on the first + * dependency line in the first makefile. + */ +static GNode *mainNode; + +/* eval state */ + +/* During parsing, the targets from the left-hand side of the currently + * active dependency line, or NULL if the current line does not belong to a + * dependency line, for example because it is a variable assignment. + * + * See unit-tests/deptgt.mk, keyword "parse.c:targets". */ +static GNodeList *targets; + +#ifdef CLEANUP +/* All shell commands for all targets, in no particular order and possibly + * with duplicates. Kept in a separate list since the commands from .USE or + * .USEBEFORE nodes are shared with other GNodes, thereby giving up the + * easily understandable ownership over the allocated strings. */ +static StringList *targCmds; +#endif + +/* + * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER + * seen, then set to each successive source on the line. + */ +static GNode *order_pred; + +/* parser state */ + +/* number of fatal errors */ +static int fatals = 0; + +/* + * Variables for doing includes + */ + +/* The include chain of makefiles. At the bottom is the top-level makefile + * from the command line, and on top of that, there are the included files or + * .for loops, up to and including the current file. + * + * This data could be used to print stack traces on parse errors. As of + * 2020-09-14, this is not done though. It seems quite simple to print the + * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is + * made complicated by the fact that the .for loops also use this stack for + * storing information. + * + * The lineno fields of the IFiles with fromForLoop == TRUE look confusing, + * which is demonstrated by the test 'include-main.mk'. They seem sorted + * backwards since they tell the number of completely parsed lines, which for + * a .for loop is right after the terminating .endfor. To compensate for this + * confusion, there is another field first_lineno pointing at the start of the + * .for loop, 1-based for human consumption. + * + * To make the stack trace intuitive, the entry below the first .for loop must + * be ignored completely since neither its lineno nor its first_lineno is + * useful. Instead, the topmost of each chain of .for loop needs to be + * printed twice, once with its first_lineno and once with its lineno. + * + * As of 2020-10-28, using the above rules, the stack trace for the .info line + * in include-subsub.mk would be: + * + * includes[5]: include-subsub.mk:4 + * (lineno, from an .include) + * includes[4]: include-sub.mk:32 + * (lineno, from a .for loop below an .include) + * includes[4]: include-sub.mk:31 + * (first_lineno, from a .for loop, lineno == 32) + * includes[3]: include-sub.mk:30 + * (first_lineno, from a .for loop, lineno == 33) + * includes[2]: include-sub.mk:29 + * (first_lineno, from a .for loop, lineno == 34) + * includes[1]: include-sub.mk:35 + * (not printed since it is below a .for loop) + * includes[0]: include-main.mk:27 + */ +static Vector /* of IFile */ includes; + +static IFile * +GetInclude(size_t i) +{ + return Vector_Get(&includes, i); +} + +/* The file that is currently being read. */ +static IFile * +CurFile(void) +{ + return GetInclude(includes.len - 1); +} + +/* include paths */ +SearchPath *parseIncPath; /* dirs for "..." includes */ +SearchPath *sysIncPath; /* dirs for <...> includes */ +SearchPath *defSysIncPath; /* default for sysIncPath */ + +/* parser tables */ + +/* + * The parseKeywords table is searched using binary search when deciding + * if a target or source is special. The 'spec' field is the ParseSpecial + * type of the keyword (SP_NOT if the keyword isn't special as a target) while + * the 'op' field is the operator to apply to the list of targets if the + * keyword is used as a source ("0" if the keyword isn't special as a source) + */ +static const struct { + const char *name; /* Name of keyword */ + ParseSpecial spec; /* Type when used as a target */ + GNodeType op; /* Operator when used as a source */ +} parseKeywords[] = { + { ".BEGIN", SP_BEGIN, 0 }, + { ".DEFAULT", SP_DEFAULT, 0 }, + { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, 0 }, + { ".END", SP_END, 0 }, + { ".ERROR", SP_ERROR, 0 }, + { ".EXEC", SP_ATTRIBUTE, OP_EXEC }, + { ".IGNORE", SP_IGNORE, OP_IGNORE }, + { ".INCLUDES", SP_INCLUDES, 0 }, + { ".INTERRUPT", SP_INTERRUPT, 0 }, + { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE }, + { ".JOIN", SP_ATTRIBUTE, OP_JOIN }, + { ".LIBS", SP_LIBS, 0 }, + { ".MADE", SP_ATTRIBUTE, OP_MADE }, + { ".MAIN", SP_MAIN, 0 }, + { ".MAKE", SP_ATTRIBUTE, OP_MAKE }, + { ".MAKEFLAGS", SP_MFLAGS, 0 }, + { ".META", SP_META, OP_META }, + { ".MFLAGS", SP_MFLAGS, 0 }, + { ".NOMETA", SP_NOMETA, OP_NOMETA }, + { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP }, + { ".NOPATH", SP_NOPATH, OP_NOPATH }, + { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN }, + { ".NOTPARALLEL", SP_NOTPARALLEL, 0 }, + { ".NO_PARALLEL", SP_NOTPARALLEL, 0 }, + { ".NULL", SP_NULL, 0 }, + { ".OBJDIR", SP_OBJDIR, 0 }, + { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL }, + { ".ORDER", SP_ORDER, 0 }, + { ".PARALLEL", SP_PARALLEL, 0 }, + { ".PATH", SP_PATH, 0 }, + { ".PHONY", SP_PHONY, OP_PHONY }, +#ifdef POSIX + { ".POSIX", SP_POSIX, 0 }, +#endif + { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS }, + { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE }, + { ".SHELL", SP_SHELL, 0 }, + { ".SILENT", SP_SILENT, OP_SILENT }, + { ".SINGLESHELL", SP_SINGLESHELL, 0 }, + { ".STALE", SP_STALE, 0 }, + { ".SUFFIXES", SP_SUFFIXES, 0 }, + { ".USE", SP_ATTRIBUTE, OP_USE }, + { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE }, + { ".WAIT", SP_WAIT, 0 }, +}; + +/* file loader */ + +struct loadedfile { + const char *path; /* name, for error reports */ + char *buf; /* contents buffer */ + size_t len; /* length of contents */ + size_t maplen; /* length of mmap area, or 0 */ + Boolean used; /* XXX: have we used the data yet */ +}; + +static struct loadedfile * +loadedfile_create(const char *path) +{ + struct loadedfile *lf; + + lf = bmake_malloc(sizeof(*lf)); + lf->path = path == NULL ? "(stdin)" : path; + lf->buf = NULL; + lf->len = 0; + lf->maplen = 0; + lf->used = FALSE; + return lf; +} + +static void +loadedfile_destroy(struct loadedfile *lf) +{ + if (lf->buf != NULL) { + if (lf->maplen > 0) { +#ifdef HAVE_MMAP + munmap(lf->buf, lf->maplen); +#endif + } else { + free(lf->buf); + } + } + free(lf); +} + +/* + * nextbuf() operation for loadedfile, as needed by the weird and twisted + * logic below. Once that's cleaned up, we can get rid of lf->used... + */ +static char * +loadedfile_nextbuf(void *x, size_t *len) +{ + struct loadedfile *lf = x; + + if (lf->used) { + return NULL; + } + lf->used = TRUE; + *len = lf->len; + return lf->buf; +} + +/* + * Try to get the size of a file. + */ +static Boolean +load_getsize(int fd, size_t *ret) +{ + struct stat st; + + if (fstat(fd, &st) < 0) { + return FALSE; + } + + if (!S_ISREG(st.st_mode)) { + return FALSE; + } + + /* + * st_size is an off_t, which is 64 bits signed; *ret is + * size_t, which might be 32 bits unsigned or 64 bits + * unsigned. Rather than being elaborate, just punt on + * files that are more than 2^31 bytes. We should never + * see a makefile that size in practice... + * + * While we're at it reject negative sizes too, just in case. + */ + if (st.st_size < 0 || st.st_size > 0x7fffffff) { + return FALSE; + } + + *ret = (size_t)st.st_size; + return TRUE; +} + +#ifdef HAVE_MMAP +static Boolean +loadedfile_mmap(struct loadedfile *lf, int fd) +{ + static unsigned long pagesize = 0; + + if (load_getsize(fd, &lf->len)) { + + /* found a size, try mmap */ +#ifdef _SC_PAGESIZE + if (pagesize == 0) + pagesize = (unsigned long)sysconf(_SC_PAGESIZE); +#endif + if (pagesize == 0 || pagesize == (unsigned long)-1) { + pagesize = 0x1000; + } + /* round size up to a page */ + lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize); + + /* + * XXX hack for dealing with empty files; remove when + * we're no longer limited by interfacing to the old + * logic elsewhere in this file. + */ + if (lf->maplen == 0) { + lf->maplen = pagesize; + } + + /* + * FUTURE: remove PROT_WRITE when the parser no longer + * needs to scribble on the input. + */ + lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE, + MAP_FILE|MAP_COPY, fd, 0); + if (lf->buf != MAP_FAILED) { + /* succeeded */ + if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') { + char *b = bmake_malloc(lf->len + 1); + b[lf->len] = '\n'; + memcpy(b, lf->buf, lf->len++); + munmap(lf->buf, lf->maplen); + lf->maplen = 0; + lf->buf = b; + } + return TRUE; + } + } + return FALSE; +} +#endif + +/* + * Read in a file. + * + * Until the path search logic can be moved under here instead of + * being in the caller in another source file, we need to have the fd + * passed in already open. Bleh. + * + * If the path is NULL use stdin and (to insure against fd leaks) + * assert that the caller passed in -1. + */ +static struct loadedfile * +loadfile(const char *path, int fd) +{ + struct loadedfile *lf; + ssize_t result; + size_t bufpos; + + lf = loadedfile_create(path); + + if (path == NULL) { + assert(fd == -1); + fd = STDIN_FILENO; + } else { +#if 0 /* notyet */ + fd = open(path, O_RDONLY); + if (fd < 0) { + ... + Error("%s: %s", path, strerror(errno)); + exit(1); + } +#endif + } + +#ifdef HAVE_MMAP + if (loadedfile_mmap(lf, fd)) + goto done; +#endif + + /* cannot mmap; load the traditional way */ + + lf->maplen = 0; + lf->len = 1024; + lf->buf = bmake_malloc(lf->len); + + bufpos = 0; + while (1) { + assert(bufpos <= lf->len); + if (bufpos == lf->len) { + if (lf->len > SIZE_MAX/2) { + errno = EFBIG; + Error("%s: file too large", path); + exit(1); + } + lf->len *= 2; + lf->buf = bmake_realloc(lf->buf, lf->len); + } + assert(bufpos < lf->len); + result = read(fd, lf->buf + bufpos, lf->len - bufpos); + if (result < 0) { + Error("%s: read error: %s", path, strerror(errno)); + exit(1); + } + if (result == 0) { + break; + } + bufpos += (size_t)result; + } + assert(bufpos <= lf->len); + lf->len = bufpos; + + /* truncate malloc region to actual length (maybe not useful) */ + if (lf->len > 0) { + /* as for mmap case, ensure trailing \n */ + if (lf->buf[lf->len - 1] != '\n') + lf->len++; + lf->buf = bmake_realloc(lf->buf, lf->len); + lf->buf[lf->len - 1] = '\n'; + } + +#ifdef HAVE_MMAP +done: +#endif + if (path != NULL) { + close(fd); + } + return lf; +} + +/* old code */ + +/* Check if the current character is escaped on the current line. */ +static Boolean +ParseIsEscaped(const char *line, const char *c) +{ + Boolean active = FALSE; + for (;;) { + if (line == c) + return active; + if (*--c != '\\') + return active; + active = !active; + } +} + +/* Add the filename and lineno to the GNode so that we remember where it + * was first defined. */ +static void +ParseMark(GNode *gn) +{ + IFile *curFile = CurFile(); + gn->fname = curFile->fname; + gn->lineno = curFile->lineno; +} + +/* Look in the table of keywords for one matching the given string. + * Return the index of the keyword, or -1 if it isn't there. */ +static int +ParseFindKeyword(const char *str) +{ + int start, end, cur; + int diff; + + start = 0; + end = sizeof parseKeywords / sizeof parseKeywords[0] - 1; + + do { + cur = start + (end - start) / 2; + diff = strcmp(str, parseKeywords[cur].name); + + if (diff == 0) { + return cur; + } else if (diff < 0) { + end = cur - 1; + } else { + start = cur + 1; + } + } while (start <= end); + return -1; +} + +static void +PrintLocation(FILE *f, const char *filename, size_t lineno) +{ + char dirbuf[MAXPATHLEN+1]; + const char *dir, *base; + void *dir_freeIt, *base_freeIt; + + if (*filename == '/' || strcmp(filename, "(stdin)") == 0) { + (void)fprintf(f, "\"%s\" line %zu: ", filename, lineno); + return; + } + + /* Find out which makefile is the culprit. + * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */ + + dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &dir_freeIt); + if (dir == NULL) + dir = "."; + if (*dir != '/') + dir = realpath(dir, dirbuf); + + base = Var_Value(".PARSEFILE", VAR_GLOBAL, &base_freeIt); + if (base == NULL) { + const char *slash = strrchr(filename, '/'); + base = slash != NULL ? slash + 1 : filename; + } + + (void)fprintf(f, "\"%s/%s\" line %zu: ", dir, base, lineno); + bmake_free(base_freeIt); + bmake_free(dir_freeIt); +} + +/* Print a parse error message, including location information. + * + * Increment "fatals" if the level is PARSE_FATAL, and continue parsing + * until the end of the current top-level makefile, then exit (see + * Parse_File). */ +static void +ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, + ParseErrorLevel type, const char *fmt, va_list ap) +{ + static Boolean fatal_warning_error_printed = FALSE; + + (void)fprintf(f, "%s: ", progname); + + if (cfname != NULL) + PrintLocation(f, cfname, clineno); + if (type == PARSE_WARNING) + (void)fprintf(f, "warning: "); + (void)vfprintf(f, fmt, ap); + (void)fprintf(f, "\n"); + (void)fflush(f); + + if (type == PARSE_INFO) + return; + if (type == PARSE_FATAL || opts.parseWarnFatal) + fatals++; + if (opts.parseWarnFatal && !fatal_warning_error_printed) { + Error("parsing warnings being treated as errors"); + fatal_warning_error_printed = TRUE; + } +} + +static void +ParseErrorInternal(const char *cfname, size_t clineno, ParseErrorLevel type, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + (void)fflush(stdout); + ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap); + va_end(ap); + + if (opts.debug_file != stderr && opts.debug_file != stdout) { + va_start(ap, fmt); + ParseVErrorInternal(opts.debug_file, cfname, clineno, type, + fmt, ap); + va_end(ap); + } +} + +/* External interface to ParseErrorInternal; uses the default filename and + * line number. + * + * Fmt is given without a trailing newline. */ +void +Parse_Error(ParseErrorLevel type, const char *fmt, ...) +{ + va_list ap; + const char *fname; + size_t lineno; + + if (includes.len == 0) { + fname = NULL; + lineno = 0; + } else { + IFile *curFile = CurFile(); + fname = curFile->fname; + lineno = (size_t)curFile->lineno; + } + + va_start(ap, fmt); + (void)fflush(stdout); + ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); + va_end(ap); + + if (opts.debug_file != stderr && opts.debug_file != stdout) { + va_start(ap, fmt); + ParseVErrorInternal(opts.debug_file, fname, lineno, type, + fmt, ap); + va_end(ap); + } +} + + +/* Parse a .info .warning or .error directive. + * + * The input is the line minus the ".". We substitute variables, print the + * message and exit(1) (for .error) or just print a warning if the directive + * is malformed. + */ +static Boolean +ParseMessage(const char *directive) +{ + const char *p = directive; + int mtype = *p == 'i' ? PARSE_INFO : + *p == 'w' ? PARSE_WARNING : PARSE_FATAL; + char *arg; + + while (ch_isalpha(*p)) + p++; + if (!ch_isspace(*p)) + return FALSE; /* missing argument */ + + cpp_skip_whitespace(&p); + (void)Var_Subst(p, VAR_CMDLINE, VARE_WANTRES, &arg); + /* TODO: handle errors */ + + Parse_Error(mtype, "%s", arg); + free(arg); + + if (mtype == PARSE_FATAL) { + PrintOnError(NULL, NULL); + exit(1); + } + return TRUE; +} + +/* Add the child to the parent's children. + * + * Additionally, add the parent to the child's parents, but only if the + * target is not special. An example for such a special target is .END, + * which does not need to be informed once the child target has been made. */ +static void +LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial) +{ + if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts)) + pgn = pgn->cohorts->last->datum; + + Lst_Append(pgn->children, cgn); + pgn->unmade++; + + /* Special targets like .END don't need any children. */ + if (!isSpecial) + Lst_Append(cgn->parents, pgn); + + if (DEBUG(PARSE)) { + debug_printf("# %s: added child %s - %s\n", + __func__, pgn->name, cgn->name); + Targ_PrintNode(pgn, 0); + Targ_PrintNode(cgn, 0); + } +} + +/* Add the node to each target from the current dependency group. */ +static void +LinkToTargets(GNode *gn, Boolean isSpecial) +{ + GNodeListNode *ln; + for (ln = targets->first; ln != NULL; ln = ln->next) + LinkSource(ln->datum, gn, isSpecial); +} + +static Boolean +TryApplyDependencyOperator(GNode *gn, GNodeType op) +{ + /* + * If the node occurred on the left-hand side of a dependency and the + * operator also defines a dependency, they must match. + */ + if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) && + ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) + { + Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); + return FALSE; + } + + if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { + /* + * If the node was the object of a :: operator, we need to create a + * new instance of it for the children and commands on this dependency + * line. The new instance is placed on the 'cohorts' list of the + * initial one (note the initial one is not on its own cohorts list) + * and the new instance is linked to all parents of the initial + * instance. + */ + GNode *cohort; + + /* + * Propagate copied bits to the initial node. They'll be propagated + * back to the rest of the cohorts later. + */ + gn->type |= op & ~OP_OPMASK; + + cohort = Targ_NewInternalNode(gn->name); + if (doing_depend) + ParseMark(cohort); + /* + * Make the cohort invisible as well to avoid duplicating it into + * other variables. True, parents of this target won't tend to do + * anything with their local variables, but better safe than + * sorry. (I think this is pointless now, since the relevant list + * traversals will no longer see this node anyway. -mycroft) + */ + cohort->type = op | OP_INVISIBLE; + Lst_Append(gn->cohorts, cohort); + cohort->centurion = gn; + gn->unmade_cohorts++; + snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", + (unsigned int)gn->unmade_cohorts % 1000000); + } else { + /* + * We don't want to nuke any previous flags (whatever they were) so we + * just OR the new operator into the old + */ + gn->type |= op; + } + + return TRUE; +} + +static void +ApplyDependencyOperator(GNodeType op) +{ + GNodeListNode *ln; + for (ln = targets->first; ln != NULL; ln = ln->next) + if (!TryApplyDependencyOperator(ln->datum, op)) + break; +} + +static Boolean +ParseDoSrcKeyword(const char *src, ParseSpecial specType) +{ + static int wait_number = 0; + char wait_src[16]; + GNode *gn; + + if (*src == '.' && ch_isupper(src[1])) { + int keywd = ParseFindKeyword(src); + if (keywd != -1) { + int op = parseKeywords[keywd].op; + if (op != 0) { + ApplyDependencyOperator(op); + return TRUE; + } + if (parseKeywords[keywd].spec == SP_WAIT) { + /* + * We add a .WAIT node in the dependency list. + * After any dynamic dependencies (and filename globbing) + * have happened, it is given a dependency on the each + * previous child back to and previous .WAIT node. + * The next child won't be scheduled until the .WAIT node + * is built. + * We give each .WAIT node a unique name (mainly for diag). + */ + snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); + gn = Targ_NewInternalNode(wait_src); + if (doing_depend) + ParseMark(gn); + gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; + LinkToTargets(gn, specType != SP_NOT); + return TRUE; + } + } + } + return FALSE; +} + +static void +ParseDoSrcMain(const char *src) +{ + /* + * If we have noted the existence of a .MAIN, it means we need + * to add the sources of said target to the list of things + * to create. The string 'src' is likely to be free, so we + * must make a new copy of it. Note that this will only be + * invoked if the user didn't specify a target on the command + * line. This is to allow #ifmake's to succeed, or something... + */ + Lst_Append(opts.create, bmake_strdup(src)); + /* + * Add the name to the .TARGETS variable as well, so the user can + * employ that, if desired. + */ + Var_Append(".TARGETS", src, VAR_GLOBAL); +} + +static void +ParseDoSrcOrder(const char *src) +{ + GNode *gn; + /* + * Create proper predecessor/successor links between the previous + * source and the current one. + */ + gn = Targ_GetNode(src); + if (doing_depend) + ParseMark(gn); + if (order_pred != NULL) { + Lst_Append(order_pred->order_succ, gn); + Lst_Append(gn->order_pred, order_pred); + if (DEBUG(PARSE)) { + debug_printf("# %s: added Order dependency %s - %s\n", + __func__, order_pred->name, gn->name); + Targ_PrintNode(order_pred, 0); + Targ_PrintNode(gn, 0); + } + } + /* + * The current source now becomes the predecessor for the next one. + */ + order_pred = gn; +} + +static void +ParseDoSrcOther(const char *src, GNodeType tOp, ParseSpecial specType) +{ + GNode *gn; + + /* + * If the source is not an attribute, we need to find/create + * a node for it. After that we can apply any operator to it + * from a special target or link it to its parents, as + * appropriate. + * + * In the case of a source that was the object of a :: operator, + * the attribute is applied to all of its instances (as kept in + * the 'cohorts' list of the node) or all the cohorts are linked + * to all the targets. + */ + + /* Find/create the 'src' node and attach to all targets */ + gn = Targ_GetNode(src); + if (doing_depend) + ParseMark(gn); + if (tOp) { + gn->type |= tOp; + } else { + LinkToTargets(gn, specType != SP_NOT); + } +} + +/* Given the name of a source in a dependency line, figure out if it is an + * attribute (such as .SILENT) and apply it to the targets if it is. Else + * decide if there is some attribute which should be applied *to* the source + * because of some special target (such as .PHONY) and apply it if so. + * Otherwise, make the source a child of the targets in the list 'targets'. + * + * Input: + * tOp operator (if any) from special targets + * src name of the source to handle + */ +static void +ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType) +{ + if (ParseDoSrcKeyword(src, specType)) + return; + + if (specType == SP_MAIN) + ParseDoSrcMain(src); + else if (specType == SP_ORDER) + ParseDoSrcOrder(src); + else + ParseDoSrcOther(src, tOp, specType); +} + +/* If we have yet to decide on a main target to make, in the absence of any + * user input, we want the first target on the first dependency line that is + * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made. */ +static void +FindMainTarget(void) +{ + GNodeListNode *ln; + + if (mainNode != NULL) + return; + + for (ln = targets->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + if (!(gn->type & OP_NOTARGET)) { + mainNode = gn; + Targ_SetMain(gn); + return; + } + } +} + +/* + * We got to the end of the line while we were still looking at targets. + * + * Ending a dependency line without an operator is a Bozo no-no. As a + * heuristic, this is also often triggered by undetected conflicts from + * cvs/rcs merges. + */ +static void +ParseErrorNoDependency(const char *lstart) +{ + if ((strncmp(lstart, "<<<<<<", 6) == 0) || + (strncmp(lstart, "======", 6) == 0) || + (strncmp(lstart, ">>>>>>", 6) == 0)) + Parse_Error(PARSE_FATAL, + "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); + else if (lstart[0] == '.') { + const char *dirstart = lstart + 1; + const char *dirend; + cpp_skip_whitespace(&dirstart); + dirend = dirstart; + while (ch_isalnum(*dirend) || *dirend == '-') + dirend++; + Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"", + (int)(dirend - dirstart), dirstart); + } else + Parse_Error(PARSE_FATAL, "Need an operator"); +} + +static void +ParseDependencyTargetWord(/*const*/ char **pp, const char *lstart) +{ + /*const*/ char *cp = *pp; + + while (*cp != '\0') { + if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' || *cp == '(') && + !ParseIsEscaped(lstart, cp)) + break; + + if (*cp == '$') { + /* + * Must be a dynamic source (would have been expanded + * otherwise), so call the Var module to parse the puppy + * so we can safely advance beyond it...There should be + * no errors in this, as they would have been discovered + * in the initial Var_Subst and we wouldn't be here. + */ + const char *nested_p = cp; + const char *nested_val; + void *freeIt; + + (void)Var_Parse(&nested_p, VAR_CMDLINE, VARE_UNDEFERR|VARE_WANTRES, + &nested_val, &freeIt); + /* TODO: handle errors */ + free(freeIt); + cp += nested_p - cp; + } else + cp++; + } + + *pp = cp; +} + +/* + * Certain special targets have special semantics: + * .PATH Have to set the dirSearchPath + * variable too + * .MAIN Its sources are only used if + * nothing has been specified to + * create. + * .DEFAULT Need to create a node to hang + * commands on, but we don't want + * it in the graph, nor do we want + * it to be the Main Target, so we + * create it, set OP_NOTMAIN and + * add it to the list, setting + * DEFAULT to the new node for + * later use. We claim the node is + * A transformation rule to make + * life easier later, when we'll + * use Make_HandleUse to actually + * apply the .DEFAULT commands. + * .PHONY The list of targets + * .NOPATH Don't search for file in the path + * .STALE + * .BEGIN + * .END + * .ERROR + * .DELETE_ON_ERROR + * .INTERRUPT Are not to be considered the + * main target. + * .NOTPARALLEL Make only one target at a time. + * .SINGLESHELL Create a shell for each command. + * .ORDER Must set initial predecessor to NULL + */ +static void +ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType, + const char *line, + SearchPathList **inout_paths) +{ + switch (*inout_specType) { + case SP_PATH: + if (*inout_paths == NULL) { + *inout_paths = Lst_New(); + } + Lst_Append(*inout_paths, dirSearchPath); + break; + case SP_MAIN: + if (!Lst_IsEmpty(opts.create)) { + *inout_specType = SP_NOT; + } + break; + case SP_BEGIN: + case SP_END: + case SP_STALE: + case SP_ERROR: + case SP_INTERRUPT: { + GNode *gn = Targ_GetNode(line); + if (doing_depend) + ParseMark(gn); + gn->type |= OP_NOTMAIN|OP_SPECIAL; + Lst_Append(targets, gn); + break; + } + case SP_DEFAULT: { + GNode *gn = Targ_NewGN(".DEFAULT"); + gn->type |= OP_NOTMAIN|OP_TRANSFORM; + Lst_Append(targets, gn); + DEFAULT = gn; + break; + } + case SP_DELETE_ON_ERROR: + deleteOnError = TRUE; + break; + case SP_NOTPARALLEL: + opts.maxJobs = 1; + break; + case SP_SINGLESHELL: + opts.compatMake = TRUE; + break; + case SP_ORDER: + order_pred = NULL; + break; + default: + break; + } +} + +/* + * .PATH has to be handled specially. + * Call on the suffix module to give us a path to modify. + */ +static Boolean +ParseDoDependencyTargetPath(const char *line, SearchPathList **inout_paths) +{ + SearchPath *path; + + path = Suff_GetPath(&line[5]); + if (path == NULL) { + Parse_Error(PARSE_FATAL, + "Suffix '%s' not defined (yet)", + &line[5]); + return FALSE; + } else { + if (*inout_paths == NULL) { + *inout_paths = Lst_New(); + } + Lst_Append(*inout_paths, path); + } + return TRUE; +} + +/* + * See if it's a special target and if so set specType to match it. + */ +static Boolean +ParseDoDependencyTarget(const char *line, ParseSpecial *inout_specType, + GNodeType *out_tOp, SearchPathList **inout_paths) +{ + int keywd; + + if (!(*line == '.' && ch_isupper(line[1]))) + return TRUE; + + /* + * See if the target is a special target that must have it + * or its sources handled specially. + */ + keywd = ParseFindKeyword(line); + if (keywd != -1) { + if (*inout_specType == SP_PATH && parseKeywords[keywd].spec != SP_PATH) { + Parse_Error(PARSE_FATAL, "Mismatched special targets"); + return FALSE; + } + + *inout_specType = parseKeywords[keywd].spec; + *out_tOp = parseKeywords[keywd].op; + + ParseDoDependencyTargetSpecial(inout_specType, line, inout_paths); + + } else if (strncmp(line, ".PATH", 5) == 0) { + *inout_specType = SP_PATH; + if (!ParseDoDependencyTargetPath(line, inout_paths)) + return FALSE; + } + return TRUE; +} + +static void +ParseDoDependencyTargetMundane(char *line, StringList *curTargs) +{ + if (Dir_HasWildcards(line)) { + /* + * Targets are to be sought only in the current directory, + * so create an empty path for the thing. Note we need to + * use Dir_Destroy in the destruction of the path as the + * Dir module could have added a directory to the path... + */ + SearchPath *emptyPath = Lst_New(); + + Dir_Expand(line, emptyPath, curTargs); + + Lst_Destroy(emptyPath, Dir_Destroy); + } else { + /* + * No wildcards, but we want to avoid code duplication, + * so create a list with the word on it. + */ + Lst_Append(curTargs, line); + } + + /* Apply the targets. */ + + while (!Lst_IsEmpty(curTargs)) { + char *targName = Lst_Dequeue(curTargs); + GNode *gn = Suff_IsTransform(targName) + ? Suff_AddTransform(targName) + : Targ_GetNode(targName); + if (doing_depend) + ParseMark(gn); + + Lst_Append(targets, gn); + } +} + +static void +ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart) +{ + Boolean warning = FALSE; + char *cp = *pp; + + while (*cp && (ParseIsEscaped(lstart, cp) || + (*cp != '!' && *cp != ':'))) { + if (ParseIsEscaped(lstart, cp) || + (*cp != ' ' && *cp != '\t')) { + warning = TRUE; + } + cp++; + } + if (warning) { + Parse_Error(PARSE_WARNING, "Extra target ignored"); + } + *pp = cp; +} + +static void +ParseDoDependencyCheckSpec(ParseSpecial specType) +{ + switch (specType) { + default: + Parse_Error(PARSE_WARNING, + "Special and mundane targets don't mix. Mundane ones ignored"); + break; + case SP_DEFAULT: + case SP_STALE: + case SP_BEGIN: + case SP_END: + case SP_ERROR: + case SP_INTERRUPT: + /* + * These four create nodes on which to hang commands, so + * targets shouldn't be empty... + */ + case SP_NOT: + /* + * Nothing special here -- targets can be empty if it wants. + */ + break; + } +} + +static Boolean +ParseDoDependencyParseOp(char **pp, const char *lstart, GNodeType *out_op) +{ + const char *cp = *pp; + + if (*cp == '!') { + *out_op = OP_FORCE; + (*pp)++; + return TRUE; + } + + if (*cp == ':') { + if (cp[1] == ':') { + *out_op = OP_DOUBLEDEP; + (*pp) += 2; + } else { + *out_op = OP_DEPENDS; + (*pp)++; + } + return TRUE; + } + + { + const char *msg = lstart[0] == '.' ? "Unknown directive" + : "Missing dependency operator"; + Parse_Error(PARSE_FATAL, "%s", msg); + return FALSE; + } +} + +static void +ClearPaths(SearchPathList *paths) +{ + if (paths != NULL) { + SearchPathListNode *ln; + for (ln = paths->first; ln != NULL; ln = ln->next) + Dir_ClearPath(ln->datum); + } + + Dir_SetPATH(); +} + +static void +ParseDoDependencySourcesEmpty(ParseSpecial specType, SearchPathList *paths) +{ + switch (specType) { + case SP_SUFFIXES: + Suff_ClearSuffixes(); + break; + case SP_PRECIOUS: + allPrecious = TRUE; + break; + case SP_IGNORE: + opts.ignoreErrors = TRUE; + break; + case SP_SILENT: + opts.beSilent = TRUE; + break; + case SP_PATH: + ClearPaths(paths); + break; +#ifdef POSIX + case SP_POSIX: + Var_Set("%POSIX", "1003.2", VAR_GLOBAL); + break; +#endif + default: + break; + } +} + +static void +AddToPaths(const char *dir, SearchPathList *paths) +{ + if (paths != NULL) { + SearchPathListNode *ln; + for (ln = paths->first; ln != NULL; ln = ln->next) + (void)Dir_AddDir(ln->datum, dir); + } +} + +/* + * If the target was one that doesn't take files as its sources + * but takes something like suffixes, we take each + * space-separated word on the line as a something and deal + * with it accordingly. + * + * If the target was .SUFFIXES, we take each source as a + * suffix and add it to the list of suffixes maintained by the + * Suff module. + * + * If the target was a .PATH, we add the source as a directory + * to search on the search path. + * + * If it was .INCLUDES, the source is taken to be the suffix of + * files which will be #included and whose search path should + * be present in the .INCLUDES variable. + * + * If it was .LIBS, the source is taken to be the suffix of + * files which are considered libraries and whose search path + * should be present in the .LIBS variable. + * + * If it was .NULL, the source is the suffix to use when a file + * has no valid suffix. + * + * If it was .OBJDIR, the source is a new definition for .OBJDIR, + * and will cause make to do a new chdir to that path. + */ +static void +ParseDoDependencySourceSpecial(ParseSpecial specType, char *word, + SearchPathList *paths) +{ + switch (specType) { + case SP_SUFFIXES: + Suff_AddSuffix(word, &mainNode); + break; + case SP_PATH: + AddToPaths(word, paths); + break; + case SP_INCLUDES: + Suff_AddInclude(word); + break; + case SP_LIBS: + Suff_AddLib(word); + break; + case SP_NULL: + Suff_SetNull(word); + break; + case SP_OBJDIR: + Main_SetObjdir("%s", word); + break; + default: + break; + } +} + +static Boolean +ParseDoDependencyTargets(char **inout_cp, + char **inout_line, + const char *lstart, + ParseSpecial *inout_specType, + GNodeType *inout_tOp, + SearchPathList **inout_paths, + StringList *curTargs) +{ + char *cp = *inout_cp; + char *line = *inout_line; + char savec; + + for (;;) { + /* + * Here LINE points to the beginning of the next word, and + * LSTART points to the actual beginning of the line. + */ + + /* Find the end of the next word. */ + cp = line; + ParseDependencyTargetWord(&cp, lstart); + + /* + * If the word is followed by a left parenthesis, it's the + * name of an object file inside an archive (ar file). + */ + if (!ParseIsEscaped(lstart, cp) && *cp == '(') { + /* + * Archives must be handled specially to make sure the OP_ARCHV + * flag is set in their 'type' field, for one thing, and because + * things like "archive(file1.o file2.o file3.o)" are permissible. + * Arch_ParseArchive will set 'line' to be the first non-blank + * after the archive-spec. It creates/finds nodes for the members + * and places them on the given list, returning TRUE if all + * went well and FALSE if there was an error in the + * specification. On error, line should remain untouched. + */ + if (!Arch_ParseArchive(&line, targets, VAR_CMDLINE)) { + Parse_Error(PARSE_FATAL, + "Error in archive specification: \"%s\"", line); + return FALSE; + } else { + /* Done with this word; on to the next. */ + cp = line; + continue; + } + } + + if (!*cp) { + ParseErrorNoDependency(lstart); + return FALSE; + } + + /* Insert a null terminator. */ + savec = *cp; + *cp = '\0'; + + if (!ParseDoDependencyTarget(line, inout_specType, inout_tOp, + inout_paths)) + return FALSE; + + /* + * Have word in line. Get or create its node and stick it at + * the end of the targets list + */ + if (*inout_specType == SP_NOT && *line != '\0') { + ParseDoDependencyTargetMundane(line, curTargs); + } else if (*inout_specType == SP_PATH && *line != '.' && *line != '\0') { + Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); + } + + /* Don't need the inserted null terminator any more. */ + *cp = savec; + + /* + * If it is a special type and not .PATH, it's the only target we + * allow on this line... + */ + if (*inout_specType != SP_NOT && *inout_specType != SP_PATH) { + ParseDoDependencyTargetExtraWarn(&cp, lstart); + } else { + pp_skip_whitespace(&cp); + } + line = cp; + if (*line == '\0') + break; + if ((*line == '!' || *line == ':') && !ParseIsEscaped(lstart, line)) + break; + } + + *inout_cp = cp; + *inout_line = line; + return TRUE; +} + +static void +ParseDoDependencySourcesSpecial(char *start, char *end, + ParseSpecial specType, SearchPathList *paths) +{ + char savec; + + while (*start) { + while (*end && !ch_isspace(*end)) + end++; + savec = *end; + *end = '\0'; + ParseDoDependencySourceSpecial(specType, start, paths); + *end = savec; + if (savec != '\0') + end++; + pp_skip_whitespace(&end); + start = end; + } +} + +static Boolean +ParseDoDependencySourcesMundane(char *start, char *end, + ParseSpecial specType, GNodeType tOp) +{ + while (*start) { + /* + * The targets take real sources, so we must beware of archive + * specifications (i.e. things with left parentheses in them) + * and handle them accordingly. + */ + for (; *end && !ch_isspace(*end); end++) { + if (*end == '(' && end > start && end[-1] != '$') { + /* + * Only stop for a left parenthesis if it isn't at the + * start of a word (that'll be for variable changes + * later) and isn't preceded by a dollar sign (a dynamic + * source). + */ + break; + } + } + + if (*end == '(') { + GNodeList *sources = Lst_New(); + if (!Arch_ParseArchive(&start, sources, VAR_CMDLINE)) { + Parse_Error(PARSE_FATAL, + "Error in source archive spec \"%s\"", start); + return FALSE; + } + + while (!Lst_IsEmpty(sources)) { + GNode *gn = Lst_Dequeue(sources); + ParseDoSrc(tOp, gn->name, specType); + } + Lst_Free(sources); + end = start; + } else { + if (*end) { + *end = '\0'; + end++; + } + + ParseDoSrc(tOp, start, specType); + } + pp_skip_whitespace(&end); + start = end; + } + return TRUE; +} + +/* Parse a dependency line consisting of targets, followed by a dependency + * operator, optionally followed by sources. + * + * The nodes of the sources are linked as children to the nodes of the + * targets. Nodes are created as necessary. + * + * The operator is applied to each node in the global 'targets' list, + * which is where the nodes found for the targets are kept, by means of + * the ParseDoOp function. + * + * The sources are parsed in much the same way as the targets, except + * that they are expanded using the wildcarding scheme of the C-Shell, + * and all instances of the resulting words in the list of all targets + * are found. Each of the resulting nodes is then linked to each of the + * targets as one of its children. + * + * Certain targets and sources such as .PHONY or .PRECIOUS are handled + * specially. These are the ones detailed by the specType variable. + * + * The storing of transformation rules such as '.c.o' is also taken care of + * here. A target is recognized as a transformation rule by calling + * Suff_IsTransform. If it is a transformation rule, its node is gotten + * from the suffix module via Suff_AddTransform rather than the standard + * Targ_FindNode in the target module. + */ +static void +ParseDoDependency(char *line) +{ + char *cp; /* our current position */ + GNodeType op; /* the operator on the line */ + SearchPathList *paths; /* search paths to alter when parsing + * a list of .PATH targets */ + int tOp; /* operator from special target */ + StringList *curTargs; /* target names to be found and added + * to the targets list */ + char *lstart = line; + + /* + * specType contains the SPECial TYPE of the current target. It is SP_NOT + * if the target is unspecial. If it *is* special, however, the children + * are linked as children of the parent but not vice versa. + */ + ParseSpecial specType = SP_NOT; + + DEBUG1(PARSE, "ParseDoDependency(%s)\n", line); + tOp = 0; + + paths = NULL; + + curTargs = Lst_New(); + + /* + * First, grind through the targets. + */ + if (!ParseDoDependencyTargets(&cp, &line, lstart, &specType, &tOp, &paths, + curTargs)) + goto out; + + /* + * Don't need the list of target names anymore... + */ + Lst_Free(curTargs); + curTargs = NULL; + + if (!Lst_IsEmpty(targets)) + ParseDoDependencyCheckSpec(specType); + + /* + * Have now parsed all the target names. Must parse the operator next. + */ + if (!ParseDoDependencyParseOp(&cp, lstart, &op)) + goto out; + + /* + * Apply the operator to the target. This is how we remember which + * operator a target was defined with. It fails if the operator + * used isn't consistent across all references. + */ + ApplyDependencyOperator(op); + + /* + * Onward to the sources. + * + * LINE will now point to the first source word, if any, or the + * end of the string if not. + */ + pp_skip_whitespace(&cp); + line = cp; + + /* + * Several special targets take different actions if present with no + * sources: + * a .SUFFIXES line with no sources clears out all old suffixes + * a .PRECIOUS line makes all targets precious + * a .IGNORE line ignores errors for all targets + * a .SILENT line creates silence when making all targets + * a .PATH removes all directories from the search path(s). + */ + if (!*line) { + ParseDoDependencySourcesEmpty(specType, paths); + } else if (specType == SP_MFLAGS) { + /* + * Call on functions in main.c to deal with these arguments and + * set the initial character to a null-character so the loop to + * get sources won't get anything + */ + Main_ParseArgLine(line); + *line = '\0'; + } else if (specType == SP_SHELL) { + if (!Job_ParseShell(line)) { + Parse_Error(PARSE_FATAL, "improper shell specification"); + goto out; + } + *line = '\0'; + } else if (specType == SP_NOTPARALLEL || specType == SP_SINGLESHELL || + specType == SP_DELETE_ON_ERROR) { + *line = '\0'; + } + + /* + * NOW GO FOR THE SOURCES + */ + if (specType == SP_SUFFIXES || specType == SP_PATH || + specType == SP_INCLUDES || specType == SP_LIBS || + specType == SP_NULL || specType == SP_OBJDIR) + { + ParseDoDependencySourcesSpecial(line, cp, specType, paths); + if (paths) { + Lst_Free(paths); + paths = NULL; + } + if (specType == SP_PATH) + Dir_SetPATH(); + } else { + assert(paths == NULL); + if (!ParseDoDependencySourcesMundane(line, cp, specType, tOp)) + goto out; + } + + FindMainTarget(); + +out: + if (paths != NULL) + Lst_Free(paths); + if (curTargs != NULL) + Lst_Free(curTargs); +} + +typedef struct VarAssignParsed { + const char *nameStart; /* unexpanded */ + const char *nameEnd; /* before operator adjustment */ + const char *eq; /* the '=' of the assignment operator */ +} VarAssignParsed; + +/* Determine the assignment operator and adjust the end of the variable + * name accordingly. */ +static void +AdjustVarassignOp(const VarAssignParsed *pvar, const char *value, + VarAssign *out_var) +{ + const char *op = pvar->eq; + const char * const name = pvar->nameStart; + VarAssignOp type; + + if (op > name && op[-1] == '+') { + type = VAR_APPEND; + op--; + + } else if (op > name && op[-1] == '?') { + op--; + type = VAR_DEFAULT; + + } else if (op > name && op[-1] == ':') { + op--; + type = VAR_SUBST; + + } else if (op > name && op[-1] == '!') { + op--; + type = VAR_SHELL; + + } else { + type = VAR_NORMAL; +#ifdef SUNSHCMD + while (op > name && ch_isspace(op[-1])) + op--; + + if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' && op[-1] == 'h') { + type = VAR_SHELL; + op -= 3; + } +#endif + } + + { + const char *nameEnd = pvar->nameEnd < op ? pvar->nameEnd : op; + out_var->varname = bmake_strsedup(pvar->nameStart, nameEnd); + out_var->op = type; + out_var->value = value; + } +} + +/* Parse a variable assignment, consisting of a single-word variable name, + * optional whitespace, an assignment operator, optional whitespace and the + * variable value. + * + * Note: There is a lexical ambiguity with assignment modifier characters + * in variable names. This routine interprets the character before the = + * as a modifier. Therefore, an assignment like + * C++=/usr/bin/CC + * is interpreted as "C+ +=" instead of "C++ =". + * + * Used for both lines in a file and command line arguments. */ +Boolean +Parse_IsVar(const char *p, VarAssign *out_var) +{ + VarAssignParsed pvar; + const char *firstSpace = NULL; + char ch; + int level = 0; + + /* Skip to variable name */ + while (*p == ' ' || *p == '\t') + p++; + + /* During parsing, the '+' of the '+=' operator is initially parsed + * as part of the variable name. It is later corrected, as is the ':sh' + * modifier. Of these two (nameEnd and op), the earlier one determines the + * actual end of the variable name. */ + pvar.nameStart = p; +#ifdef CLEANUP + pvar.nameEnd = NULL; + pvar.eq = NULL; +#endif + + /* Scan for one of the assignment operators outside a variable expansion */ + while ((ch = *p++) != 0) { + if (ch == '(' || ch == '{') { + level++; + continue; + } + if (ch == ')' || ch == '}') { + level--; + continue; + } + + if (level != 0) + continue; + + if (ch == ' ' || ch == '\t') + if (firstSpace == NULL) + firstSpace = p - 1; + while (ch == ' ' || ch == '\t') + ch = *p++; + +#ifdef SUNSHCMD + if (ch == ':' && strncmp(p, "sh", 2) == 0) { + p += 2; + continue; + } +#endif + if (ch == '=') { + pvar.eq = p - 1; + pvar.nameEnd = firstSpace != NULL ? firstSpace : p - 1; + cpp_skip_whitespace(&p); + AdjustVarassignOp(&pvar, p, out_var); + return TRUE; + } + if (*p == '=' && (ch == '+' || ch == ':' || ch == '?' || ch == '!')) { + pvar.eq = p; + pvar.nameEnd = firstSpace != NULL ? firstSpace : p; + p++; + cpp_skip_whitespace(&p); + AdjustVarassignOp(&pvar, p, out_var); + return TRUE; + } + if (firstSpace != NULL) + return FALSE; + } + + return FALSE; +} + +static void +VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt) +{ + if (DEBUG(LINT)) { + if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) { + /* Check for syntax errors such as unclosed expressions or + * unknown modifiers. */ + char *expandedValue; + + (void)Var_Subst(uvalue, ctxt, VARE_NONE, &expandedValue); + /* TODO: handle errors */ + free(expandedValue); + } + } +} + +static void +VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt, + const char **out_avalue, void **out_avalue_freeIt) +{ + const char *avalue = uvalue; + char *evalue; + /* + * Allow variables in the old value to be undefined, but leave their + * expressions alone -- this is done by forcing oldVars to be false. + * XXX: This can cause recursive variables, but that's not hard to do, + * and this allows someone to do something like + * + * CFLAGS = $(.INCLUDES) + * CFLAGS := -I.. $(CFLAGS) + * + * And not get an error. + */ + Boolean oldOldVars = oldVars; + + oldVars = FALSE; + + /* + * make sure that we set the variable the first time to nothing + * so that it gets substituted! + */ + if (!Var_Exists(name, ctxt)) + Var_Set(name, "", ctxt); + + (void)Var_Subst(uvalue, ctxt, VARE_WANTRES|VARE_ASSIGN, &evalue); + /* TODO: handle errors */ + oldVars = oldOldVars; + avalue = evalue; + Var_Set(name, avalue, ctxt); + + *out_avalue = avalue; + *out_avalue_freeIt = evalue; +} + +static void +VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt, + const char **out_avalue, void **out_avalue_freeIt) +{ + const char *cmd, *errfmt; + char *cmdOut; + void *cmd_freeIt = NULL; + + cmd = uvalue; + if (strchr(cmd, '$') != NULL) { + char *ecmd; + (void)Var_Subst(cmd, VAR_CMDLINE, VARE_UNDEFERR | VARE_WANTRES, &ecmd); + /* TODO: handle errors */ + cmd = cmd_freeIt = ecmd; + } + + cmdOut = Cmd_Exec(cmd, &errfmt); + Var_Set(name, cmdOut, ctxt); + *out_avalue = *out_avalue_freeIt = cmdOut; + + if (errfmt) + Parse_Error(PARSE_WARNING, errfmt, cmd); + + free(cmd_freeIt); +} + +/* Perform a variable assignment. + * + * The actual value of the variable is returned in *out_avalue and + * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ + * from the literal value. + * + * Return whether the assignment was actually done. The assignment is only + * skipped if the operator is '?=' and the variable already exists. */ +static Boolean +VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue, + GNode *ctxt, const char **out_avalue, void **out_avalue_freeIt) +{ + const char *avalue = uvalue; + void *avalue_freeIt = NULL; + + if (op == VAR_APPEND) { + Var_Append(name, uvalue, ctxt); + } else if (op == VAR_SUBST) { + VarAssign_EvalSubst(name, uvalue, ctxt, &avalue, &avalue_freeIt); + } else if (op == VAR_SHELL) { + VarAssign_EvalShell(name, uvalue, ctxt, &avalue, &avalue_freeIt); + } else { + if (op == VAR_DEFAULT && Var_Exists(name, ctxt)) { + *out_avalue_freeIt = NULL; + return FALSE; + } + + /* Normal assignment -- just do it. */ + Var_Set(name, uvalue, ctxt); + } + + *out_avalue = avalue; + *out_avalue_freeIt = avalue_freeIt; + return TRUE; +} + +static void +VarAssignSpecial(const char *name, const char *avalue) +{ + if (strcmp(name, MAKEOVERRIDES) == 0) + Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ + else if (strcmp(name, ".CURDIR") == 0) { + /* + * Someone is being (too?) clever... + * Let's pretend they know what they are doing and + * re-initialize the 'cur' CachedDir. + */ + Dir_InitCur(avalue); + Dir_SetPATH(); + } else if (strcmp(name, MAKE_JOB_PREFIX) == 0) { + Job_SetPrefix(); + } else if (strcmp(name, MAKE_EXPORTED) == 0) { + Var_Export(avalue, FALSE); + } +} + +/* Perform the variable variable assignment in the given context. */ +void +Parse_DoVar(VarAssign *var, GNode *ctxt) +{ + const char *avalue; /* actual value (maybe expanded) */ + void *avalue_freeIt; + + VarCheckSyntax(var->op, var->value, ctxt); + if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, + &avalue, &avalue_freeIt)) + VarAssignSpecial(var->varname, avalue); + + free(avalue_freeIt); + free(var->varname); +} + + +/* + * ParseMaybeSubMake -- + * Scan the command string to see if it a possible submake node + * Input: + * cmd the command to scan + * Results: + * TRUE if the command is possibly a submake, FALSE if not. + */ +static Boolean +ParseMaybeSubMake(const char *cmd) +{ + size_t i; + static struct { + const char *name; + size_t len; + } vals[] = { +#define MKV(A) { A, sizeof(A) - 1 } + MKV("${MAKE}"), + MKV("${.MAKE}"), + MKV("$(MAKE)"), + MKV("$(.MAKE)"), + MKV("make"), + }; + for (i = 0; i < sizeof vals / sizeof vals[0]; i++) { + char *ptr; + if ((ptr = strstr(cmd, vals[i].name)) == NULL) + continue; + if ((ptr == cmd || !ch_isalnum(ptr[-1])) + && !ch_isalnum(ptr[vals[i].len])) + return TRUE; + } + return FALSE; +} + +/* Append the command to the target node. + * + * The node may be marked as a submake node if the command is determined to + * be that. */ +static void +ParseAddCmd(GNode *gn, char *cmd) +{ + /* Add to last (ie current) cohort for :: targets */ + if ((gn->type & OP_DOUBLEDEP) && gn->cohorts->last != NULL) + gn = gn->cohorts->last->datum; + + /* if target already supplied, ignore commands */ + if (!(gn->type & OP_HAS_COMMANDS)) { + Lst_Append(gn->commands, cmd); + if (ParseMaybeSubMake(cmd)) + gn->type |= OP_SUBMAKE; + ParseMark(gn); + } else { +#if 0 + /* XXX: We cannot do this until we fix the tree */ + Lst_Append(gn->commands, cmd); + Parse_Error(PARSE_WARNING, + "overriding commands for target \"%s\"; " + "previous commands defined at %s: %d ignored", + gn->name, gn->fname, gn->lineno); +#else + Parse_Error(PARSE_WARNING, + "duplicate script for target \"%s\" ignored", + gn->name); + ParseErrorInternal(gn->fname, (size_t)gn->lineno, PARSE_WARNING, + "using previous script for \"%s\" defined here", + gn->name); +#endif + } +} + +/* Add a directory to the path searched for included makefiles bracketed + * by double-quotes. */ +void +Parse_AddIncludeDir(const char *dir) +{ + (void)Dir_AddDir(parseIncPath, dir); +} + +/* Push to another file. + * + * The input is the line minus the '.'. A file spec is a string enclosed in + * <> or "". The <> file is looked for only in sysIncPath. The "" file is + * first searched in the parsedir and then in the directories specified by + * the -I command line options. + */ +static void +Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent) +{ + struct loadedfile *lf; + char *fullname; /* full pathname of file */ + char *newName; + char *prefEnd, *incdir; + int fd; + int i; + + /* + * Now we know the file's name and its search path, we attempt to + * find the durn thing. A return of NULL indicates the file don't + * exist. + */ + fullname = file[0] == '/' ? bmake_strdup(file) : NULL; + + if (fullname == NULL && !isSystem) { + /* + * Include files contained in double-quotes are first searched for + * relative to the including file's location. We don't want to + * cd there, of course, so we just tack on the old file's + * leading path components and call Dir_FindFile to see if + * we can locate the beast. + */ + + incdir = bmake_strdup(CurFile()->fname); + prefEnd = strrchr(incdir, '/'); + if (prefEnd != NULL) { + *prefEnd = '\0'; + /* Now do lexical processing of leading "../" on the filename */ + for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) { + prefEnd = strrchr(incdir + 1, '/'); + if (prefEnd == NULL || strcmp(prefEnd, "/..") == 0) + break; + *prefEnd = '\0'; + } + newName = str_concat3(incdir, "/", file + i); + fullname = Dir_FindFile(newName, parseIncPath); + if (fullname == NULL) + fullname = Dir_FindFile(newName, dirSearchPath); + free(newName); + } + free(incdir); + + if (fullname == NULL) { + /* + * Makefile wasn't found in same directory as included makefile. + * Search for it first on the -I search path, + * then on the .PATH search path, if not found in a -I directory. + * If we have a suffix specific path we should use that. + */ + char *suff; + SearchPath *suffPath = NULL; + + if ((suff = strrchr(file, '.'))) { + suffPath = Suff_GetPath(suff); + if (suffPath != NULL) { + fullname = Dir_FindFile(file, suffPath); + } + } + if (fullname == NULL) { + fullname = Dir_FindFile(file, parseIncPath); + if (fullname == NULL) { + fullname = Dir_FindFile(file, dirSearchPath); + } + } + } + } + + /* Looking for a system file or file still not found */ + if (fullname == NULL) { + /* + * Look for it on the system path + */ + SearchPath *path = Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath; + fullname = Dir_FindFile(file, path); + } + + if (fullname == NULL) { + if (!silent) + Parse_Error(PARSE_FATAL, "Could not find %s", file); + return; + } + + /* Actually open the file... */ + fd = open(fullname, O_RDONLY); + if (fd == -1) { + if (!silent) + Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); + free(fullname); + return; + } + + /* load it */ + lf = loadfile(fullname, fd); + + /* Start reading from this file next */ + Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf); + CurFile()->lf = lf; + if (depinc) + doing_depend = depinc; /* only turn it on */ +} + +static void +ParseDoInclude(char *line) +{ + char endc; /* the character which ends the file spec */ + char *cp; /* current position in file spec */ + int silent = *line != 'i'; + char *file = line + (silent ? 8 : 7); + + /* Skip to delimiter character so we know where to look */ + while (*file == ' ' || *file == '\t') + file++; + + if (*file != '"' && *file != '<') { + Parse_Error(PARSE_FATAL, + ".include filename must be delimited by '\"' or '<'"); + return; + } + + /* + * Set the search path on which to find the include file based on the + * characters which bracket its name. Angle-brackets imply it's + * a system Makefile while double-quotes imply it's a user makefile + */ + if (*file == '<') { + endc = '>'; + } else { + endc = '"'; + } + + /* Skip to matching delimiter */ + for (cp = ++file; *cp && *cp != endc; cp++) + continue; + + if (*cp != endc) { + Parse_Error(PARSE_FATAL, + "Unclosed %cinclude filename. '%c' expected", + '.', endc); + return; + } + *cp = '\0'; + + /* + * Substitute for any variables in the file name before trying to + * find the thing. + */ + (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &file); + /* TODO: handle errors */ + + Parse_include_file(file, endc == '>', *line == 'd', silent); + free(file); +} + +/* Split filename into dirname + basename, then assign these to the + * given variables. */ +static void +SetFilenameVars(const char *filename, const char *dirvar, const char *filevar) +{ + const char *slash, *dirname, *basename; + void *freeIt; + + slash = strrchr(filename, '/'); + if (slash == NULL) { + dirname = curdir; + basename = filename; + freeIt = NULL; + } else { + dirname = freeIt = bmake_strsedup(filename, slash); + basename = slash + 1; + } + + Var_Set(dirvar, dirname, VAR_GLOBAL); + Var_Set(filevar, basename, VAR_GLOBAL); + + DEBUG5(PARSE, "%s: ${%s} = `%s' ${%s} = `%s'\n", + __func__, dirvar, dirname, filevar, basename); + free(freeIt); +} + +/* Return the immediately including file. + * + * This is made complicated since the .for loop is implemented as a special + * kind of .include; see For_Run. */ +static const char * +GetActuallyIncludingFile(void) +{ + size_t i; + const IFile *incs = GetInclude(0); + + for (i = includes.len; i >= 2; i--) + if (!incs[i - 1].fromForLoop) + return incs[i - 2].fname; + return NULL; +} + +/* Set .PARSEDIR, .PARSEFILE, .INCLUDEDFROMDIR and .INCLUDEDFROMFILE. */ +static void +ParseSetParseFile(const char *filename) +{ + const char *including; + + SetFilenameVars(filename, ".PARSEDIR", ".PARSEFILE"); + + including = GetActuallyIncludingFile(); + if (including != NULL) { + SetFilenameVars(including, + ".INCLUDEDFROMDIR", ".INCLUDEDFROMFILE"); + } else { + Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL); + Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL); + } +} + +static Boolean +StrContainsWord(const char *str, const char *word) +{ + size_t strLen = strlen(str); + size_t wordLen = strlen(word); + const char *p, *end; + + if (strLen < wordLen) + return FALSE; /* str is too short to contain word */ + + end = str + strLen - wordLen; + for (p = str; p != NULL; p = strchr(p, ' ')) { + if (*p == ' ') + p++; + if (p > end) + return FALSE; /* cannot contain word */ + + if (memcmp(p, word, wordLen) == 0 && + (p[wordLen] == '\0' || p[wordLen] == ' ')) + return TRUE; + } + return FALSE; +} + +/* XXX: Searching through a set of words with this linear search is + * inefficient for variables that contain thousands of words. */ +static Boolean +VarContainsWord(const char *varname, const char *word) +{ + void *val_freeIt; + const char *val = Var_Value(varname, VAR_GLOBAL, &val_freeIt); + Boolean found = val != NULL && StrContainsWord(val, word); + bmake_free(val_freeIt); + return found; +} + +/* Track the makefiles we read - so makefiles can set dependencies on them. + * Avoid adding anything more than once. */ +static void +ParseTrackInput(const char *name) +{ + if (!VarContainsWord(MAKE_MAKEFILES, name)) + Var_Append(MAKE_MAKEFILES, name, VAR_GLOBAL); +} + + +/* Start Parsing from the given source. + * + * The given file is added to the includes stack. */ +void +Parse_SetInput(const char *name, int line, int fd, + char *(*nextbuf)(void *, size_t *), void *arg) +{ + IFile *curFile; + char *buf; + size_t len; + Boolean fromForLoop = name == NULL; + + if (fromForLoop) + name = CurFile()->fname; + else + ParseTrackInput(name); + + if (DEBUG(PARSE)) + debug_printf("%s: file %s, line %d, fd %d, nextbuf %s, arg %p\n", + __func__, name, line, fd, + nextbuf == loadedfile_nextbuf ? "loadedfile" : "other", + arg); + + if (fd == -1 && nextbuf == NULL) + /* sanity */ + return; + + curFile = Vector_Push(&includes); + + /* + * Once the previous state has been saved, we can get down to reading + * the new file. We set up the name of the file to be the absolute + * name of the include file so error messages refer to the right + * place. + */ + curFile->fname = bmake_strdup(name); + curFile->fromForLoop = fromForLoop; + curFile->lineno = line; + curFile->first_lineno = line; + curFile->nextbuf = nextbuf; + curFile->nextbuf_arg = arg; + curFile->lf = NULL; + curFile->depending = doing_depend; /* restore this on EOF */ + + assert(nextbuf != NULL); + + /* Get first block of input data */ + buf = curFile->nextbuf(curFile->nextbuf_arg, &len); + if (buf == NULL) { + /* Was all a waste of time ... */ + if (curFile->fname) + free(curFile->fname); + free(curFile); + return; + } + curFile->buf_freeIt = buf; + curFile->buf_ptr = buf; + curFile->buf_end = buf + len; + + curFile->cond_depth = Cond_save_depth(); + ParseSetParseFile(name); +} + +/* Check if the directive is an include directive. */ +static Boolean +IsInclude(const char *dir, Boolean sysv) +{ + if (dir[0] == 's' || dir[0] == '-' || (dir[0] == 'd' && !sysv)) + dir++; + + if (strncmp(dir, "include", 7) != 0) + return FALSE; + + /* Space is not mandatory for BSD .include */ + return !sysv || ch_isspace(dir[7]); +} + + +#ifdef SYSVINCLUDE +/* Check if the line is a SYSV include directive. */ +static Boolean +IsSysVInclude(const char *line) +{ + const char *p; + + if (!IsInclude(line, TRUE)) + return FALSE; + + /* Avoid interpreting a dependency line as an include */ + for (p = line; (p = strchr(p, ':')) != NULL;) { + if (*++p == '\0') { + /* end of line -> dependency */ + return FALSE; + } + if (*p == ':' || ch_isspace(*p)) { + /* :: operator or ': ' -> dependency */ + return FALSE; + } + } + return TRUE; +} + +/* Push to another file. The line points to the word "include". */ +static void +ParseTraditionalInclude(char *line) +{ + char *cp; /* current position in file spec */ + int done = 0; + int silent = line[0] != 'i'; + char *file = line + (silent ? 8 : 7); + char *all_files; + + DEBUG2(PARSE, "%s: %s\n", __func__, file); + + pp_skip_whitespace(&file); + + /* + * Substitute for any variables in the file name before trying to + * find the thing. + */ + (void)Var_Subst(file, VAR_CMDLINE, VARE_WANTRES, &all_files); + /* TODO: handle errors */ + + if (*file == '\0') { + Parse_Error(PARSE_FATAL, "Filename missing from \"include\""); + goto out; + } + + for (file = all_files; !done; file = cp + 1) { + /* Skip to end of line or next whitespace */ + for (cp = file; *cp && !ch_isspace(*cp); cp++) + continue; + + if (*cp) + *cp = '\0'; + else + done = 1; + + Parse_include_file(file, FALSE, FALSE, silent); + } +out: + free(all_files); +} +#endif + +#ifdef GMAKEEXPORT +/* Parse "export =", and actually export it. */ +static void +ParseGmakeExport(char *line) +{ + char *variable = line + 6; + char *value; + + DEBUG2(PARSE, "%s: %s\n", __func__, variable); + + pp_skip_whitespace(&variable); + + for (value = variable; *value && *value != '='; value++) + continue; + + if (*value != '=') { + Parse_Error(PARSE_FATAL, + "Variable/Value missing from \"export\""); + return; + } + *value++ = '\0'; /* terminate variable */ + + /* + * Expand the value before putting it in the environment. + */ + (void)Var_Subst(value, VAR_CMDLINE, VARE_WANTRES, &value); + /* TODO: handle errors */ + + setenv(variable, value, 1); + free(value); +} +#endif + +/* Called when EOF is reached in the current file. If we were reading an + * include file, the includes stack is popped and things set up to go back + * to reading the previous file at the previous location. + * + * Results: + * TRUE to continue parsing, i.e. it had only reached the end of an + * included file, FALSE if the main file has been parsed completely. + */ +static Boolean +ParseEOF(void) +{ + char *ptr; + size_t len; + IFile *curFile = CurFile(); + + assert(curFile->nextbuf != NULL); + + doing_depend = curFile->depending; /* restore this */ + /* get next input buffer, if any */ + ptr = curFile->nextbuf(curFile->nextbuf_arg, &len); + curFile->buf_ptr = ptr; + curFile->buf_freeIt = ptr; + curFile->buf_end = ptr + len; + curFile->lineno = curFile->first_lineno; + if (ptr != NULL) { + /* Iterate again */ + return TRUE; + } + + /* Ensure the makefile (or loop) didn't have mismatched conditionals */ + Cond_restore_depth(curFile->cond_depth); + + if (curFile->lf != NULL) { + loadedfile_destroy(curFile->lf); + curFile->lf = NULL; + } + + /* Dispose of curFile info */ + /* Leak curFile->fname because all the gnodes have pointers to it */ + free(curFile->buf_freeIt); + Vector_Pop(&includes); + + if (includes.len == 0) { + /* We've run out of input */ + Var_Delete(".PARSEDIR", VAR_GLOBAL); + Var_Delete(".PARSEFILE", VAR_GLOBAL); + Var_Delete(".INCLUDEDFROMDIR", VAR_GLOBAL); + Var_Delete(".INCLUDEDFROMFILE", VAR_GLOBAL); + return FALSE; + } + + curFile = CurFile(); + DEBUG2(PARSE, "ParseEOF: returning to file %s, line %d\n", + curFile->fname, curFile->lineno); + + ParseSetParseFile(curFile->fname); + return TRUE; +} + +#define PARSE_RAW 1 +#define PARSE_SKIP 2 + +static char * +ParseGetLine(int flags) +{ + IFile *cf = CurFile(); + char *ptr; + char ch; + char *line; + char *line_end; + char *escaped; + char *comment; + char *tp; + + /* Loop through blank lines and comment lines */ + for (;;) { + cf->lineno++; + line = cf->buf_ptr; + ptr = line; + line_end = line; + escaped = NULL; + comment = NULL; + for (;;) { + /* XXX: can buf_end ever be null? */ + if (cf->buf_end != NULL && ptr == cf->buf_end) { + /* end of buffer */ + ch = 0; + break; + } + ch = *ptr; + if (ch == 0 || (ch == '\\' && ptr[1] == 0)) { + /* XXX: can buf_end ever be null? */ + if (cf->buf_end == NULL) + /* End of string (aka for loop) data */ + break; + /* see if there is more we can parse */ + while (ptr++ < cf->buf_end) { + if ((ch = *ptr) == '\n') { + if (ptr > line && ptr[-1] == '\\') + continue; + Parse_Error(PARSE_WARNING, + "Zero byte read from file, " + "skipping rest of line."); + break; + } + } + if (cf->nextbuf != NULL) { + /* + * End of this buffer; return EOF and outer logic + * will get the next one. (eww) + */ + break; + } + Parse_Error(PARSE_FATAL, "Zero byte read from file"); + return NULL; + } + + if (ch == '\\') { + /* Don't treat next character as special, remember first one */ + if (escaped == NULL) + escaped = ptr; + if (ptr[1] == '\n') + cf->lineno++; + ptr += 2; + line_end = ptr; + continue; + } + if (ch == '#' && comment == NULL) { + /* Remember first '#' for comment stripping */ + /* Unless previous char was '[', as in modifier :[#] */ + if (!(ptr > line && ptr[-1] == '[')) + comment = line_end; + } + ptr++; + if (ch == '\n') + break; + if (!ch_isspace(ch)) + /* We are not interested in trailing whitespace */ + line_end = ptr; + } + + /* Save next 'to be processed' location */ + cf->buf_ptr = ptr; + + /* Check we have a non-comment, non-blank line */ + if (line_end == line || comment == line) { + if (ch == 0) + /* At end of file */ + return NULL; + /* Parse another line */ + continue; + } + + /* We now have a line of data */ + *line_end = 0; + + if (flags & PARSE_RAW) { + /* Leave '\' (etc) in line buffer (eg 'for' lines) */ + return line; + } + + if (flags & PARSE_SKIP) { + /* Completely ignore non-directives */ + if (line[0] != '.') + continue; + /* We could do more of the .else/.elif/.endif checks here */ + } + break; + } + + /* Brutally ignore anything after a non-escaped '#' in non-commands */ + if (comment != NULL && line[0] != '\t') { + line_end = comment; + *line_end = 0; + } + + /* If we didn't see a '\\' then the in-situ data is fine */ + if (escaped == NULL) + return line; + + /* Remove escapes from '\n' and '#' */ + tp = ptr = escaped; + escaped = line; + for (; ; *tp++ = ch) { + ch = *ptr++; + if (ch != '\\') { + if (ch == 0) + break; + continue; + } + + ch = *ptr++; + if (ch == 0) { + /* Delete '\\' at end of buffer */ + tp--; + break; + } + + if (ch == '#' && line[0] != '\t') + /* Delete '\\' from before '#' on non-command lines */ + continue; + + if (ch != '\n') { + /* Leave '\\' in buffer for later */ + *tp++ = '\\'; + /* Make sure we don't delete an escaped ' ' from the line end */ + escaped = tp + 1; + continue; + } + + /* Escaped '\n' replace following whitespace with a single ' ' */ + while (ptr[0] == ' ' || ptr[0] == '\t') + ptr++; + ch = ' '; + } + + /* Delete any trailing spaces - eg from empty continuations */ + while (tp > escaped && ch_isspace(tp[-1])) + tp--; + + *tp = 0; + return line; +} + +/* Read an entire line from the input file. Called only by Parse_File. + * + * Results: + * A line without its newline. + * + * Side Effects: + * Only those associated with reading a character + */ +static char * +ParseReadLine(void) +{ + char *line; /* Result */ + int lineno; /* Saved line # */ + int rval; + + for (;;) { + line = ParseGetLine(0); + if (line == NULL) + return NULL; + + if (line[0] != '.') + return line; + + /* + * The line might be a conditional. Ask the conditional module + * about it and act accordingly + */ + switch (Cond_EvalLine(line)) { + case COND_SKIP: + /* Skip to next conditional that evaluates to COND_PARSE. */ + do { + line = ParseGetLine(PARSE_SKIP); + } while (line && Cond_EvalLine(line) != COND_PARSE); + if (line == NULL) + break; + continue; + case COND_PARSE: + continue; + case COND_INVALID: /* Not a conditional line */ + /* Check for .for loops */ + rval = For_Eval(line); + if (rval == 0) + /* Not a .for line */ + break; + if (rval < 0) + /* Syntax error - error printed, ignore line */ + continue; + /* Start of a .for loop */ + lineno = CurFile()->lineno; + /* Accumulate loop lines until matching .endfor */ + do { + line = ParseGetLine(PARSE_RAW); + if (line == NULL) { + Parse_Error(PARSE_FATAL, + "Unexpected end of file in for loop."); + break; + } + } while (For_Accum(line)); + /* Stash each iteration as a new 'input file' */ + For_Run(lineno); + /* Read next line from for-loop buffer */ + continue; + } + return line; + } +} + +static void +FinishDependencyGroup(void) +{ + if (targets != NULL) { + GNodeListNode *ln; + for (ln = targets->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + + Suff_EndTransform(gn); + + /* Mark the target as already having commands if it does, to + * keep from having shell commands on multiple dependency lines. */ + if (!Lst_IsEmpty(gn->commands)) + gn->type |= OP_HAS_COMMANDS; + } + + Lst_Free(targets); + targets = NULL; + } +} + +/* Add the command to each target from the current dependency spec. */ +static void +ParseLine_ShellCommand(const char *p) +{ + cpp_skip_whitespace(&p); + if (*p == '\0') + return; /* skip empty commands */ + + if (targets == NULL) { + Parse_Error(PARSE_FATAL, "Unassociated shell command \"%s\"", p); + return; + } + + { + char *cmd = bmake_strdup(p); + GNodeListNode *ln; + + for (ln = targets->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + ParseAddCmd(gn, cmd); + } +#ifdef CLEANUP + Lst_Append(targCmds, cmd); +#endif + } +} + +static Boolean +ParseDirective(char *line) +{ + char *cp; + + if (*line == '.') { + /* + * Lines that begin with the special character may be + * include or undef directives. + * On the other hand they can be suffix rules (.c.o: ...) + * or just dependencies for filenames that start '.'. + */ + cp = line + 1; + pp_skip_whitespace(&cp); + if (IsInclude(cp, FALSE)) { + ParseDoInclude(cp); + return TRUE; + } + if (strncmp(cp, "undef", 5) == 0) { + const char *varname; + cp += 5; + pp_skip_whitespace(&cp); + varname = cp; + for (; !ch_isspace(*cp) && *cp != '\0'; cp++) + continue; + *cp = '\0'; + Var_Delete(varname, VAR_GLOBAL); + /* TODO: undefine all variables, not only the first */ + /* TODO: use Str_Words, like everywhere else */ + return TRUE; + } else if (strncmp(cp, "export", 6) == 0) { + cp += 6; + pp_skip_whitespace(&cp); + Var_Export(cp, TRUE); + return TRUE; + } else if (strncmp(cp, "unexport", 8) == 0) { + Var_UnExport(cp); + return TRUE; + } else if (strncmp(cp, "info", 4) == 0 || + strncmp(cp, "error", 5) == 0 || + strncmp(cp, "warning", 7) == 0) { + if (ParseMessage(cp)) + return TRUE; + } + } + return FALSE; +} + +static Boolean +ParseVarassign(const char *line) +{ + VarAssign var; + if (Parse_IsVar(line, &var)) { + FinishDependencyGroup(); + Parse_DoVar(&var, VAR_GLOBAL); + return TRUE; + } + return FALSE; +} + +static char * +FindSemicolon(char *p) +{ + int level = 0; + + for (; *p != '\0'; p++) { + if (*p == '\\' && p[1] != '\0') { + p++; + continue; + } + + if (*p == '$' && (p[1] == '(' || p[1] == '{')) { + level++; + continue; + } + + if (level > 0 && (*p == ')' || *p == '}')) { + level--; + continue; + } + + if (level == 0 && *p == ';') { + break; + } + } + return p; +} + +/* dependency -> target... op [source...] + * op -> ':' | '::' | '!' */ +static void +ParseDependency(char *line) +{ + VarEvalFlags eflags; + char *expanded_line; + const char *shellcmd = NULL; + + /* + * For some reason - probably to make the parser impossible - + * a ';' can be used to separate commands from dependencies. + * Attempt to avoid ';' inside substitution patterns. + */ + { + char *semicolon = FindSemicolon(line); + if (*semicolon != '\0') { + /* Terminate the dependency list at the ';' */ + *semicolon = '\0'; + shellcmd = semicolon + 1; + } + } + + /* + * We now know it's a dependency line so it needs to have all + * variables expanded before being parsed. + * + * XXX: Ideally the dependency line would first be split into + * its left-hand side, dependency operator and right-hand side, + * and then each side would be expanded on its own. This would + * allow for the left-hand side to allow only defined variables + * and to allow variables on the right-hand side to be undefined + * as well. + * + * Parsing the line first would also prevent that targets + * generated from variable expressions are interpreted as the + * dependency operator, such as in "target${:U:} middle: source", + * in which the middle is interpreted as a source, not a target. + */ + + /* In lint mode, allow undefined variables to appear in + * dependency lines. + * + * Ideally, only the right-hand side would allow undefined + * variables since it is common to have no dependencies. + * Having undefined variables on the left-hand side is more + * unusual though. Since both sides are expanded in a single + * pass, there is not much choice what to do here. + * + * In normal mode, it does not matter whether undefined + * variables are allowed or not since as of 2020-09-14, + * Var_Parse does not print any parse errors in such a case. + * It simply returns the special empty string var_Error, + * which cannot be detected in the result of Var_Subst. */ + eflags = DEBUG(LINT) ? VARE_WANTRES : VARE_UNDEFERR | VARE_WANTRES; + (void)Var_Subst(line, VAR_CMDLINE, eflags, &expanded_line); + /* TODO: handle errors */ + + /* Need a fresh list for the target nodes */ + if (targets != NULL) + Lst_Free(targets); + targets = Lst_New(); + + ParseDoDependency(expanded_line); + free(expanded_line); + + if (shellcmd != NULL) + ParseLine_ShellCommand(shellcmd); +} + +static void +ParseLine(char *line) +{ + if (ParseDirective(line)) + return; + + if (*line == '\t') { + ParseLine_ShellCommand(line + 1); + return; + } + +#ifdef SYSVINCLUDE + if (IsSysVInclude(line)) { + /* + * It's an S3/S5-style "include". + */ + ParseTraditionalInclude(line); + return; + } +#endif + +#ifdef GMAKEEXPORT + if (strncmp(line, "export", 6) == 0 && ch_isspace(line[6]) && + strchr(line, ':') == NULL) { + /* + * It's a Gmake "export". + */ + ParseGmakeExport(line); + return; + } +#endif + + if (ParseVarassign(line)) + return; + + FinishDependencyGroup(); + + ParseDependency(line); +} + +/* Parse a top-level makefile into its component parts, incorporating them + * into the global dependency graph. + * + * Input: + * name The name of the file being read + * fd The open file to parse; will be closed at the end + */ +void +Parse_File(const char *name, int fd) +{ + char *line; /* the line we're working on */ + struct loadedfile *lf; + + lf = loadfile(name, fd); + + assert(targets == NULL); + fatals = 0; + + if (name == NULL) + name = "(stdin)"; + + Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf); + CurFile()->lf = lf; + + do { + while ((line = ParseReadLine()) != NULL) { + DEBUG2(PARSE, "ParseReadLine (%d): '%s'\n", + CurFile()->lineno, line); + ParseLine(line); + } + /* + * Reached EOF, but it may be just EOF of an include file... + */ + } while (ParseEOF()); + + FinishDependencyGroup(); + + if (fatals) { + (void)fflush(stdout); + (void)fprintf(stderr, + "%s: Fatal errors encountered -- cannot continue", + progname); + PrintOnError(NULL, NULL); + exit(1); + } +} + +/* Initialize the parsing module. */ +void +Parse_Init(void) +{ + mainNode = NULL; + parseIncPath = Lst_New(); + sysIncPath = Lst_New(); + defSysIncPath = Lst_New(); + Vector_Init(&includes, sizeof(IFile)); +#ifdef CLEANUP + targCmds = Lst_New(); +#endif +} + +/* Clean up the parsing module. */ +void +Parse_End(void) +{ +#ifdef CLEANUP + Lst_Destroy(targCmds, free); + assert(targets == NULL); + Lst_Destroy(defSysIncPath, Dir_Destroy); + Lst_Destroy(sysIncPath, Dir_Destroy); + Lst_Destroy(parseIncPath, Dir_Destroy); + assert(includes.len == 0); + Vector_Done(&includes); +#endif +} + + +/*- + *----------------------------------------------------------------------- + * Parse_MainName -- + * Return a Lst of the main target to create for main()'s sake. If + * no such target exists, we Punt with an obnoxious error message. + * + * Results: + * A Lst of the single node to create. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ +GNodeList * +Parse_MainName(void) +{ + GNodeList *mainList; + + mainList = Lst_New(); + + if (mainNode == NULL) { + Punt("no target to make."); + /*NOTREACHED*/ + } else if (mainNode->type & OP_DOUBLEDEP) { + Lst_Append(mainList, mainNode); + Lst_AppendAll(mainList, mainNode->cohorts); + } else + Lst_Append(mainList, mainNode); + Var_Append(".TARGETS", mainNode->name, VAR_GLOBAL); + return mainList; +} + +int +Parse_GetFatals(void) +{ + return fatals; +} Property changes on: vendor/NetBSD/bmake/20201101/parse.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/str.c =================================================================== --- vendor/NetBSD/bmake/20201101/str.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/str.c (revision 367461) @@ -0,0 +1,374 @@ +/* $NetBSD: str.c,v 1.70 2020/10/24 20:51:49 rillig Exp $ */ + +/*- + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include "make.h" + +/* "@(#)str.c 5.8 (Berkeley) 6/1/90" */ +MAKE_RCSID("$NetBSD: str.c,v 1.70 2020/10/24 20:51:49 rillig Exp $"); + +/* Return the concatenation of s1 and s2, freshly allocated. */ +char * +str_concat2(const char *s1, const char *s2) +{ + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + char *result = bmake_malloc(len1 + len2 + 1); + memcpy(result, s1, len1); + memcpy(result + len1, s2, len2 + 1); + return result; +} + +/* Return the concatenation of s1, s2 and s3, freshly allocated. */ +char * +str_concat3(const char *s1, const char *s2, const char *s3) +{ + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + size_t len3 = strlen(s3); + char *result = bmake_malloc(len1 + len2 + len3 + 1); + memcpy(result, s1, len1); + memcpy(result + len1, s2, len2); + memcpy(result + len1 + len2, s3, len3 + 1); + 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. Leading tabs/spaces are ignored. + * + * If expand is TRUE, quotes are removed and escape sequences such as \r, \t, + * etc... are expanded. In this case, the return value is NULL on parse + * errors. + * + * Returns the fractured words, which must be freed later using Words_Free. + * If expand was TRUE and there was a parse error, words is NULL, and in that + * case, nothing needs to be freed. + */ +Words +Str_Words(const char *str, Boolean expand) +{ + size_t str_len; + char *words_buf; + size_t words_cap; + char **words; + size_t words_len; + char inquote; + char *word_start; + char *word_end; + const char *str_p; + + /* skip leading space chars. */ + for (; *str == ' ' || *str == '\t'; ++str) + continue; + + /* words_buf holds the words, separated by '\0'. */ + str_len = strlen(str); + words_buf = bmake_malloc(strlen(str) + 1); + + words_cap = str_len / 5 > 50 ? str_len / 5 : 50; + words = bmake_malloc((words_cap + 1) * sizeof(char *)); + + /* + * copy the string; at the same time, parse backslashes, + * quotes and build the word list. + */ + words_len = 0; + inquote = '\0'; + word_start = words_buf; + word_end = words_buf; + for (str_p = str;; ++str_p) { + char ch = *str_p; + switch (ch) { + case '"': + case '\'': + if (inquote) { + if (inquote == ch) + inquote = '\0'; + else + break; + } else { + inquote = ch; + /* Don't miss "" or '' */ + if (word_start == NULL && str_p[1] == inquote) { + if (!expand) { + word_start = word_end; + *word_end++ = ch; + } else + word_start = word_end + 1; + str_p++; + inquote = '\0'; + break; + } + } + if (!expand) { + if (word_start == NULL) + word_start = word_end; + *word_end++ = ch; + } + continue; + case ' ': + case '\t': + case '\n': + if (inquote) + break; + if (word_start == NULL) + continue; + /* FALLTHROUGH */ + case '\0': + /* + * end of a token -- make sure there's enough words + * space and save off a pointer. + */ + if (word_start == NULL) + goto done; + + *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 = bmake_realloc(words, new_size); + } + words[words_len++] = word_start; + word_start = NULL; + if (ch == '\n' || ch == '\0') { + if (expand && inquote) { + free(words); + free(words_buf); + return (Words){ NULL, 0, NULL }; + } + goto done; + } + continue; + case '\\': + if (!expand) { + if (word_start == NULL) + word_start = word_end; + *word_end++ = '\\'; + /* catch '\' at end of line */ + if (str_p[1] == '\0') + continue; + ch = *++str_p; + break; + } + + switch (ch = *++str_p) { + case '\0': + case '\n': + /* hmmm; fix it up as best we can */ + ch = '\\'; + --str_p; + break; + case 'b': + ch = '\b'; + break; + case 'f': + ch = '\f'; + break; + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + } + break; + } + if (word_start == NULL) + word_start = word_end; + *word_end++ = ch; + } +done: + words[words_len] = NULL; + return (Words){ words, words_len, words_buf }; +} + +/* + * Str_Match -- Test if a string matches a pattern like "*.[ch]". + * + * XXX this function does not detect or report malformed patterns. + * + * Results: + * Non-zero is returned if string matches the pattern, 0 otherwise. The + * matching operation permits the following special characters in the + * pattern: *?\[] (as in fnmatch(3)). + * + * Side effects: None. + */ +Boolean +Str_Match(const char *str, const char *pat) +{ + for (;;) { + /* + * See if we're at the end of both the pattern and the + * string. If, we succeeded. If we're at the end of the + * pattern but not at the end of the string, we failed. + */ + if (*pat == 0) + return *str == 0; + if (*str == 0 && *pat != '*') + return FALSE; + + /* + * A '*' in the pattern matches any substring. We handle this + * by calling ourselves for each suffix of the string. + */ + if (*pat == '*') { + pat++; + while (*pat == '*') + pat++; + if (*pat == 0) + return TRUE; + while (*str != 0) { + if (Str_Match(str, pat)) + return TRUE; + str++; + } + return FALSE; + } + + /* A '?' in the pattern matches any single character. */ + if (*pat == '?') + goto thisCharOK; + + /* + * A '[' in the pattern matches a character from a list. + * The '[' is followed by the list of acceptable characters, + * or by ranges (two characters separated by '-'). In these + * character lists, the backslash is an ordinary character. + */ + if (*pat == '[') { + Boolean neg = pat[1] == '^'; + pat += neg ? 2 : 1; + + for (;;) { + if (*pat == ']' || *pat == 0) { + if (neg) + break; + return FALSE; + } + if (*pat == *str) + break; + if (pat[1] == '-') { + if (pat[2] == 0) + return neg; + if (*pat <= *str && pat[2] >= *str) + break; + if (*pat >= *str && pat[2] <= *str) + break; + pat += 2; + } + pat++; + } + if (neg && *pat != ']' && *pat != 0) + return FALSE; + while (*pat != ']' && *pat != 0) + pat++; + if (*pat == 0) + pat--; + goto thisCharOK; + } + + /* + * A backslash in the pattern matches the character following + * it exactly. + */ + if (*pat == '\\') { + pat++; + if (*pat == 0) + return FALSE; + } + + if (*pat != *str) + return FALSE; + + thisCharOK: + pat++; + str++; + } +} Property changes on: vendor/NetBSD/bmake/20201101/str.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/suff.c =================================================================== --- vendor/NetBSD/bmake/20201101/suff.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/suff.c (revision 367461) @@ -0,0 +1,2112 @@ +/* $NetBSD: suff.c,v 1.230 2020/10/31 11:54:33 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * suff.c -- + * Functions to maintain suffix lists and find implicit dependents + * using suffix transformation rules + * + * Interface: + * Suff_Init Initialize all things to do with suffixes. + * + * Suff_End Clean up the module + * + * Suff_DoPaths This function is used to make life easier + * when searching for a file according to its + * suffix. It takes the global search path, + * as defined using the .PATH: target, and appends + * its directories to the path of each of the + * defined suffixes, as specified using + * .PATH: targets. In addition, all + * directories given for suffixes labeled as + * include files or libraries, using the .INCLUDES + * or .LIBS targets, are played with using + * Dir_MakeFlags to create the .INCLUDES and + * .LIBS global variables. + * + * Suff_ClearSuffixes + * Clear out all the suffixes and defined + * transformations. + * + * Suff_IsTransform + * Return TRUE if the passed string is the lhs + * of a transformation rule. + * + * Suff_AddSuffix Add the passed string as another known suffix. + * + * Suff_GetPath Return the search path for the given suffix. + * + * Suff_AddInclude + * Mark the given suffix as denoting an include file. + * + * Suff_AddLib Mark the given suffix as denoting a library. + * + * Suff_AddTransform + * Add another transformation to the suffix + * graph. Returns GNode suitable for framing, I + * mean, tacking commands, attributes, etc. on. + * + * Suff_SetNull Define the suffix to consider the suffix of + * any file that doesn't have a known one. + * + * Suff_FindDeps Find implicit sources for and the location of + * a target based on its suffix. Returns the + * bottom-most node added to the graph or NULL + * if the target had no implicit sources. + * + * Suff_FindPath Return the appropriate path to search in order to + * find the node. + */ + +#include "make.h" +#include "dir.h" + +/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */ +MAKE_RCSID("$NetBSD: suff.c,v 1.230 2020/10/31 11:54:33 rillig Exp $"); + +#define SUFF_DEBUG0(text) DEBUG0(SUFF, text) +#define SUFF_DEBUG1(fmt, arg1) DEBUG1(SUFF, fmt, arg1) +#define SUFF_DEBUG2(fmt, arg1, arg2) DEBUG2(SUFF, fmt, arg1, arg2) +#define SUFF_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(SUFF, fmt, arg1, arg2, arg3) +#define SUFF_DEBUG4(fmt, arg1, arg2, arg3, arg4) \ + DEBUG4(SUFF, fmt, arg1, arg2, arg3, arg4) + +typedef List SuffList; +typedef ListNode SuffListNode; + +typedef List SrcList; +typedef ListNode SrcListNode; + +static SuffList *sufflist; /* List of suffixes */ +#ifdef CLEANUP +static SuffList *suffClean; /* List of suffixes to be cleaned */ +#endif +static SrcList *srclist; /* List of sources */ +static GNodeList *transforms; /* List of transformation rules */ + +static int sNum = 0; /* Counter for assigning suffix numbers */ + +typedef enum SuffFlags { + SUFF_INCLUDE = 0x01, /* One which is #include'd */ + SUFF_LIBRARY = 0x02, /* One which contains a library */ + SUFF_NULL = 0x04 /* The empty suffix */ + /* XXX: Why is SUFF_NULL needed? Wouldn't nameLen == 0 mean the same? */ +} SuffFlags; + +ENUM_FLAGS_RTTI_3(SuffFlags, + SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL); + +typedef List SuffListList; + +/* + * Structure describing an individual suffix. + */ +typedef struct Suff { + char *name; /* The suffix itself, such as ".c" */ + size_t nameLen; /* Length of the name, to avoid strlen calls */ + SuffFlags flags; /* Type of suffix */ + SearchPath *searchPath; /* The path along which files of this suffix + * may be found */ + int sNum; /* The suffix number */ + int refCount; /* Reference count of list membership + * and several other places */ + SuffList *parents; /* Suffixes we have a transformation to */ + SuffList *children; /* Suffixes we have a transformation from */ + SuffListList *ref; /* Lists in which this suffix is referenced */ +} Suff; + +/* + * Structure used in the search for implied sources. + */ +typedef struct Src { + char *file; /* The file to look for */ + char *pref; /* Prefix from which file was formed */ + Suff *suff; /* The suffix on the file */ + struct Src *parent; /* The Src for which this is a source */ + GNode *node; /* The node describing the file */ + int children; /* Count of existing children (so we don't free + * this thing too early or never nuke it) */ +#ifdef DEBUG_SRC + SrcList *childrenList; +#endif +} Src; + +static Suff *suffNull; /* The NULL suffix for this run */ +static Suff *emptySuff; /* The empty suffix required for POSIX + * single-suffix transformation rules */ + + +static void SuffFindDeps(GNode *, SrcList *); +static void SuffExpandWildcards(GNodeListNode *, GNode *); + + /*************** Lst Predicates ****************/ +/*- + *----------------------------------------------------------------------- + * SuffStrIsPrefix -- + * See if pref is a prefix of str. + * + * Input: + * pref possible prefix + * str string to check + * + * Results: + * NULL if it ain't, pointer to character in str after prefix if so + * + * Side Effects: + * None + *----------------------------------------------------------------------- + */ +static const char * +SuffStrIsPrefix(const char *pref, const char *str) +{ + while (*str && *pref == *str) { + pref++; + str++; + } + + return *pref ? NULL : str; +} + +/* See if suff is a suffix of str. + * + * Input: + * s possible suffix + * nameLen length of the string to examine + * nameEnd end of the string to examine + * + * Results: + * NULL if it ain't, pointer to the start of suffix in str if it is. + */ +static const char * +SuffSuffGetSuffix(const Suff *s, size_t nameLen, const char *nameEnd) +{ + const char *p1; /* Pointer into suffix name */ + const char *p2; /* Pointer into string being examined */ + + if (nameLen < s->nameLen) + return NULL; /* this string is shorter than the suffix */ + + p1 = s->name + s->nameLen; + p2 = nameEnd; + + while (p1 >= s->name && *p1 == *p2) { + p1--; + p2--; + } + + /* XXX: s->name - 1 invokes undefined behavior */ + return p1 == s->name - 1 ? p2 + 1 : NULL; +} + +static Boolean +SuffSuffIsSuffix(const Suff *suff, size_t nameLen, const char *nameEnd) +{ + return SuffSuffGetSuffix(suff, nameLen, nameEnd) != NULL; +} + +static Suff * +FindSuffByNameLen(const char *name, size_t nameLen) +{ + SuffListNode *ln; + + for (ln = sufflist->first; ln != NULL; ln = ln->next) { + Suff *suff = ln->datum; + if (suff->nameLen == nameLen && memcmp(suff->name, name, nameLen) == 0) + return suff; + } + return NULL; +} + +static Suff * +FindSuffByName(const char *name) +{ + return FindSuffByNameLen(name, strlen(name)); +} + +static GNode * +FindTransformByName(const char *name) +{ + GNodeListNode *ln; + for (ln = transforms->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + if (strcmp(gn->name, name) == 0) + return gn; + } + return NULL; +} + + /*********** Maintenance Functions ************/ + +static void +SuffUnRef(SuffList *list, Suff *suff) +{ + SuffListNode *ln = Lst_FindDatum(list, suff); + if (ln != NULL) { + Lst_Remove(list, ln); + suff->refCount--; + } +} + +/* Free up all memory associated with the given suffix structure. */ +static void +SuffFree(void *sp) +{ + Suff *s = sp; + + if (s == suffNull) + suffNull = NULL; + + if (s == emptySuff) + emptySuff = NULL; + +#if 0 + /* We don't delete suffixes in order, so we cannot use this */ + if (s->refCount) + Punt("Internal error deleting suffix `%s' with refcount = %d", s->name, + s->refCount); +#endif + + Lst_Free(s->ref); + Lst_Free(s->children); + Lst_Free(s->parents); + Lst_Destroy(s->searchPath, Dir_Destroy); + + free(s->name); + free(s); +} + +/* Remove the suffix from the list, and free if it is otherwise unused. */ +static void +SuffRemove(SuffList *list, Suff *suff) +{ + SuffUnRef(list, suff); + if (suff->refCount == 0) { + SuffUnRef(sufflist, suff); + SuffFree(suff); + } +} + +/* Insert the suffix into the list, keeping the list ordered by suffix + * numbers. */ +static void +SuffInsert(SuffList *list, Suff *suff) +{ + SuffListNode *ln; + Suff *listSuff = NULL; + + for (ln = list->first; ln != NULL; ln = ln->next) { + listSuff = ln->datum; + if (listSuff->sNum >= suff->sNum) + break; + } + + if (ln == NULL) { + SUFF_DEBUG2("inserting \"%s\" (%d) at end of list\n", + suff->name, suff->sNum); + Lst_Append(list, suff); + suff->refCount++; + Lst_Append(suff->ref, list); + } else if (listSuff->sNum != suff->sNum) { + SUFF_DEBUG4("inserting \"%s\" (%d) before \"%s\" (%d)\n", + suff->name, suff->sNum, listSuff->name, listSuff->sNum); + Lst_InsertBefore(list, ln, suff); + suff->refCount++; + Lst_Append(suff->ref, list); + } else { + SUFF_DEBUG2("\"%s\" (%d) is already there\n", suff->name, suff->sNum); + } +} + +static Suff * +SuffNew(const char *name) +{ + Suff *s = bmake_malloc(sizeof(Suff)); + + s->name = bmake_strdup(name); + s->nameLen = strlen(s->name); + s->searchPath = Lst_New(); + s->children = Lst_New(); + s->parents = Lst_New(); + s->ref = Lst_New(); + s->sNum = sNum++; + s->flags = 0; + s->refCount = 1; + + return s; +} + +/* This is gross. Nuke the list of suffixes but keep all transformation + * rules around. The transformation graph is destroyed in this process, but + * we leave the list of rules so when a new graph is formed the rules will + * remain. This function is called from the parse module when a .SUFFIXES:\n + * line is encountered. */ +void +Suff_ClearSuffixes(void) +{ +#ifdef CLEANUP + Lst_MoveAll(suffClean, sufflist); +#endif + sufflist = Lst_New(); + sNum = 0; + if (suffNull) + SuffFree(suffNull); + emptySuff = suffNull = SuffNew(""); + + Dir_Concat(suffNull->searchPath, dirSearchPath); + suffNull->flags = SUFF_NULL; +} + +/* Parse a transformation string such as ".c.o" to find its two component + * 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. + */ +static Boolean +SuffParseTransform(const char *str, Suff **out_src, Suff **out_targ) +{ + SuffListNode *ln; + Suff *singleSrc = NULL; + + /* + * Loop looking first for a suffix that matches the start of the + * string and then for one that exactly matches the rest of it. If + * we can find two that meet these criteria, we've successfully + * parsed the string. + */ + for (ln = sufflist->first; ln != NULL; ln = ln->next) { + Suff *src = ln->datum; + + if (SuffStrIsPrefix(src->name, str) == NULL) + continue; + + if (str[src->nameLen] == '\0') { + singleSrc = src; + } else { + Suff *targ = FindSuffByName(str + src->nameLen); + if (targ != NULL) { + *out_src = src; + *out_targ = targ; + return TRUE; + } + } + } + + if (singleSrc != NULL) { + /* + * Not so fast Mr. Smith! There was a suffix that encompassed + * the entire string, so we assume it was a transformation + * to the null suffix (thank you POSIX). We still prefer to + * find a double rule over a singleton, hence we leave this + * check until the end. + * + * XXX: Use emptySuff over suffNull? + */ + *out_src = singleSrc; + *out_targ = suffNull; + return TRUE; + } + return FALSE; +} + +/* Return TRUE if the given string is a transformation rule, that is, a + * concatenation of two known suffixes. */ +Boolean +Suff_IsTransform(const char *str) +{ + Suff *src, *targ; + + return SuffParseTransform(str, &src, &targ); +} + +/* Add the transformation rule to the list of rules and place the + * transformation itself in the graph. + * + * The transformation is linked to the two suffixes mentioned in the name. + * + * Input: + * name must have the form ".from.to" or just ".from" + * + * Results: + * The created or existing transformation node in the transforms list + */ +GNode * +Suff_AddTransform(const char *name) +{ + GNode *gn; /* GNode of transformation rule */ + Suff *s, /* source suffix */ + *t; /* target suffix */ + Boolean ok; + + gn = FindTransformByName(name); + if (gn == NULL) { + /* + * Make a new graph node for the transformation. It will be filled in + * by the Parse module. + */ + gn = Targ_NewGN(name); + Lst_Append(transforms, gn); + } else { + /* + * New specification for transformation rule. Just nuke the old list + * of commands so they can be filled in again... We don't actually + * free the commands themselves, because a given command can be + * attached to several different transformations. + */ + Lst_Free(gn->commands); + Lst_Free(gn->children); + gn->commands = Lst_New(); + gn->children = Lst_New(); + } + + gn->type = OP_TRANSFORM; + + ok = SuffParseTransform(name, &s, &t); + assert(ok); + (void)ok; + + /* + * link the two together in the proper relationship and order + */ + SUFF_DEBUG2("defining transformation from `%s' to `%s'\n", + s->name, t->name); + SuffInsert(t->children, s); + SuffInsert(s->parents, t); + + return gn; +} + +/* Handle the finish of a transformation definition, removing the + * transformation from the graph if it has neither commands nor sources. + * + * If the node has no commands or children, the children and parents lists + * of the affected suffixes are altered. + * + * Input: + * gn Node for transformation + */ +void +Suff_EndTransform(GNode *gn) +{ + if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts)) + gn = gn->cohorts->last->datum; + if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) && + Lst_IsEmpty(gn->children)) + { + Suff *s, *t; + + /* + * SuffParseTransform() may fail for special rules which are not + * actual transformation rules. (e.g. .DEFAULT) + */ + if (SuffParseTransform(gn->name, &s, &t)) { + SuffList *p; + + SUFF_DEBUG2("deleting transformation from `%s' to `%s'\n", + s->name, t->name); + + /* + * Store s->parents because s could be deleted in SuffRemove + */ + p = s->parents; + + /* + * Remove the source from the target's children list. We check for a + * nil return to handle a beanhead saying something like + * .c.o .c.o: + * + * We'll be called twice when the next target is seen, but .c and .o + * are only linked once... + */ + SuffRemove(t->children, s); + + /* + * Remove the target from the source's parents list + */ + SuffRemove(p, t); + } + } else if (gn->type & OP_TRANSFORM) { + SUFF_DEBUG1("transformation %s complete\n", gn->name); + } +} + +/* Called from Suff_AddSuffix to search through the list of + * existing transformation rules and rebuild the transformation graph when + * it has been destroyed by Suff_ClearSuffixes. If the given rule is a + * transformation involving this suffix and another, existing suffix, the + * proper relationship is established between the two. + * + * The appropriate links will be made between this suffix and others if + * transformation rules exist for it. + * + * Input: + * transform Transformation to test + * suff Suffix to rebuild + */ +static void +SuffRebuildGraph(GNode *transform, Suff *suff) +{ + const char *name = transform->name; + size_t nameLen = strlen(name); + const char *toName; + + /* + * First see if it is a transformation from this suffix. + */ + toName = SuffStrIsPrefix(suff->name, name); + if (toName != NULL) { + Suff *to = FindSuffByName(toName); + if (to != NULL) { + /* Link in and return, since it can't be anything else. */ + SuffInsert(to->children, suff); + SuffInsert(suff->parents, to); + return; + } + } + + /* + * Not from, maybe to? + */ + toName = SuffSuffGetSuffix(suff, nameLen, name + nameLen); + if (toName != NULL) { + Suff *from = FindSuffByNameLen(name, (size_t)(toName - name)); + + if (from != NULL) { + /* establish the proper relationship */ + SuffInsert(suff->children, from); + SuffInsert(from->parents, suff); + } + } +} + +/* During Suff_AddSuffix, search through the list of existing targets and find + * if any of the existing targets can be turned into a transformation rule. + * + * If such a target is found and the target is the current main target, the + * main target is set to NULL and the next target examined (if that exists) + * becomes the main target. + * + * Results: + * TRUE iff a new main target has been selected. + */ +static Boolean +SuffScanTargets(GNode *target, GNode **inout_main, Suff *gs_s, Boolean *gs_r) +{ + Suff *s, *t; + char *ptr; + + if (*inout_main == NULL && *gs_r && !(target->type & OP_NOTARGET)) { + *inout_main = target; + Targ_SetMain(target); + return TRUE; + } + + if (target->type == OP_TRANSFORM) + return FALSE; + + if ((ptr = strstr(target->name, gs_s->name)) == NULL || + ptr == target->name) + return FALSE; + + if (SuffParseTransform(target->name, &s, &t)) { + if (*inout_main == target) { + *gs_r = TRUE; + *inout_main = NULL; + Targ_SetMain(NULL); + } + Lst_Free(target->children); + target->children = Lst_New(); + target->type = OP_TRANSFORM; + /* + * link the two together in the proper relationship and order + */ + SUFF_DEBUG2("defining transformation from `%s' to `%s'\n", + s->name, t->name); + SuffInsert(t->children, s); + SuffInsert(s->parents, t); + } + return FALSE; +} + +/* Look at all existing targets to see if adding this suffix will make one + * of the current targets mutate into a suffix rule. + * + * This is ugly, but other makes treat all targets that start with a '.' as + * suffix rules. */ +static void +UpdateTargets(GNode **inout_main, Suff *s) +{ + Boolean r = FALSE; + GNodeListNode *ln; + for (ln = Targ_List()->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + if (SuffScanTargets(gn, inout_main, s, &r)) + break; + } +} + +/* Add the suffix to the end of the list of known suffixes. + * Should we restructure the suffix graph? Make doesn't... + * + * A GNode is created for the suffix and a Suff structure is created and + * added to the suffixes list unless the suffix was already known. + * The mainNode passed can be modified if a target mutated into a + * transform and that target happened to be the main target. + * + * Input: + * name the name of the suffix to add + */ +void +Suff_AddSuffix(const char *name, GNode **inout_main) +{ + GNodeListNode *ln; + + Suff *s = FindSuffByName(name); + if (s != NULL) + return; + + s = SuffNew(name); + Lst_Append(sufflist, s); + + UpdateTargets(inout_main, s); + + /* + * Look for any existing transformations from or to this suffix. + * XXX: Only do this after a Suff_ClearSuffixes? + */ + for (ln = transforms->first; ln != NULL; ln = ln->next) + SuffRebuildGraph(ln->datum, s); +} + +/* Return the search path for the given suffix, or NULL. */ +SearchPath * +Suff_GetPath(const char *sname) +{ + Suff *s = FindSuffByName(sname); + return s != NULL ? s->searchPath : NULL; +} + +/* Extend the search paths for all suffixes to include the default search + * path. + * + * The searchPath field of all the suffixes is extended by the directories + * in dirSearchPath. If paths were specified for the ".h" suffix, the + * directories are stuffed into a global variable called ".INCLUDES" with + * each directory preceded by a -I. The same is done for the ".a" suffix, + * except the variable is called ".LIBS" and the flag is -L. + */ +void +Suff_DoPaths(void) +{ + SuffListNode *ln; + char *ptr; + SearchPath *inIncludes; /* Cumulative .INCLUDES path */ + SearchPath *inLibs; /* Cumulative .LIBS path */ + + inIncludes = Lst_New(); + inLibs = Lst_New(); + + for (ln = sufflist->first; ln != NULL; ln = ln->next) { + Suff *s = ln->datum; + if (!Lst_IsEmpty(s->searchPath)) { +#ifdef INCLUDES + if (s->flags & SUFF_INCLUDE) { + Dir_Concat(inIncludes, s->searchPath); + } +#endif +#ifdef LIBRARIES + if (s->flags & SUFF_LIBRARY) { + Dir_Concat(inLibs, s->searchPath); + } +#endif + Dir_Concat(s->searchPath, dirSearchPath); + } else { + Lst_Destroy(s->searchPath, Dir_Destroy); + s->searchPath = Dir_CopyDirSearchPath(); + } + } + + Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL); + free(ptr); + Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL); + free(ptr); + + Lst_Destroy(inIncludes, Dir_Destroy); + Lst_Destroy(inLibs, Dir_Destroy); +} + +/* Add the given suffix as a type of file which gets included. + * Called from the parse module when a .INCLUDES line is parsed. + * The suffix must have already been defined. + * The SUFF_INCLUDE bit is set in the suffix's flags field. + * + * Input: + * sname Name of the suffix to mark + */ +void +Suff_AddInclude(const char *sname) +{ + Suff *suff = FindSuffByName(sname); + if (suff != NULL) + suff->flags |= SUFF_INCLUDE; +} + +/* Add the given suffix as a type of file which is a library. + * Called from the parse module when parsing a .LIBS line. + * The suffix must have been defined via .SUFFIXES before this is called. + * The SUFF_LIBRARY bit is set in the suffix's flags field. + * + * Input: + * sname Name of the suffix to mark + */ +void +Suff_AddLib(const char *sname) +{ + Suff *suff = FindSuffByName(sname); + if (suff != NULL) + suff->flags |= SUFF_LIBRARY; +} + + /********** Implicit Source Search Functions *********/ + +#ifdef DEBUG_SRC +static void +SrcList_PrintAddrs(SrcList *srcList) +{ + SrcListNode *ln; + for (ln = srcList->first; ln != NULL; ln = ln->next) + debug_printf(" %p", ln->datum); + debug_printf("\n"); +} +#endif + +static Src * +SrcNew(char *name, char *pref, Suff *suff, Src *parent, GNode *gn) +{ + Src *src = bmake_malloc(sizeof *src); + + src->file = name; + src->pref = pref; + src->suff = suff; + src->parent = parent; + src->node = gn; + src->children = 0; +#ifdef DEBUG_SRC + src->childrenList = Lst_New(); +#endif + + return src; +} + +static void +SuffAddSrc(Suff *suff, SrcList *srcList, Src *targ, char *srcName, + const char *debug_tag) +{ + Src *s2 = SrcNew(srcName, targ->pref, suff, targ, NULL); + suff->refCount++; + targ->children++; + Lst_Append(srcList, s2); +#ifdef DEBUG_SRC + Lst_Append(targ->childrenList, s2); + debug_printf("%s add suff %p src %p to list %p:", + debug_tag, targ, s2, srcList); + SrcList_PrintAddrs(srcList); +#endif +} + +/* Add a suffix as a Src structure to the given list with its parent + * being the given Src structure. If the suffix is the null suffix, + * the prefix is used unaltered as the file name in the Src structure. + * + * Input: + * suff suffix for which to create a Src structure + * srcList list for the new Src + * targ parent for the new Src + */ +static void +SuffAddSources(Suff *suff, SrcList *srcList, Src *targ) +{ + if ((suff->flags & SUFF_NULL) && suff->name[0] != '\0') { + /* + * If the suffix has been marked as the NULL suffix, also create a Src + * structure for a file with no suffix attached. Two birds, and all + * that... + */ + SuffAddSrc(suff, srcList, targ, bmake_strdup(targ->pref), "1"); + } + SuffAddSrc(suff, srcList, targ, str_concat2(targ->pref, suff->name), "2"); +} + +/* Add all the children of targ as Src structures to the given list. + * + * Input: + * l list to which to add the new level + * targ Src structure to use as the parent + */ +static void +SuffAddLevel(SrcList *l, Src *targ) +{ + SrcListNode *ln; + for (ln = targ->suff->children->first; ln != NULL; ln = ln->next) { + Suff *childSuff = ln->datum; + SuffAddSources(childSuff, l, targ); + } +} + +/* Free the first Src in the list that is not referenced anymore. + * Return whether a Src was removed. */ +static Boolean +SuffRemoveSrc(SrcList *l) +{ + SrcListNode *ln; + +#ifdef DEBUG_SRC + debug_printf("cleaning list %p:", l); + SrcList_PrintAddrs(l); +#endif + + for (ln = l->first; ln != NULL; ln = ln->next) { + Src *s = ln->datum; + + if (s->children == 0) { + free(s->file); + if (s->parent == NULL) + free(s->pref); + else { +#ifdef DEBUG_SRC + SrcListNode *ln2 = Lst_FindDatum(s->parent->childrenList, s); + if (ln2 != NULL) + Lst_Remove(s->parent->childrenList, ln2); +#endif + s->parent->children--; + } +#ifdef DEBUG_SRC + debug_printf("free: list %p src %p children %d\n", + l, s, s->children); + Lst_Free(s->childrenList); +#endif + Lst_Remove(l, ln); + free(s); + return TRUE; + } +#ifdef DEBUG_SRC + else { + debug_printf("keep: list %p src %p children %d:", + l, s, s->children); + SrcList_PrintAddrs(s->childrenList); + } +#endif + } + + return FALSE; +} + +/* Find the first existing file/target in the list srcs. + * + * Input: + * srcs list of Src structures to search through + * + * Results: + * The lowest structure in the chain of transformations, or NULL. + */ +static Src * +SuffFindThem(SrcList *srcs, SrcList *slst) +{ + Src *retsrc = NULL; + + while (!Lst_IsEmpty(srcs)) { + Src *src = Lst_Dequeue(srcs); + + SUFF_DEBUG1("\ttrying %s...", src->file); + + /* + * A file is considered to exist if either a node exists in the + * graph for it or the file actually exists. + */ + if (Targ_FindNode(src->file) != NULL) { +#ifdef DEBUG_SRC + debug_printf("remove from list %p src %p\n", srcs, src); +#endif + retsrc = src; + break; + } + + { + char *file = Dir_FindFile(src->file, src->suff->searchPath); + if (file != NULL) { + retsrc = src; +#ifdef DEBUG_SRC + debug_printf("remove from list %p src %p\n", srcs, src); +#endif + free(file); + break; + } + } + + SUFF_DEBUG0("not there\n"); + + SuffAddLevel(srcs, src); + Lst_Append(slst, src); + } + + if (retsrc) { + SUFF_DEBUG0("got it\n"); + } + return retsrc; +} + +/* See if any of the children of the target in the Src structure is one from + * which the target can be transformed. If there is one, a Src structure is + * put together for it and returned. + * + * Input: + * targ Src to play with + * + * Results: + * The Src of the "winning" child, or NULL. + */ +static Src * +SuffFindCmds(Src *targ, SrcList *slst) +{ + GNodeListNode *gln; + GNode *tgn; /* Target GNode */ + GNode *sgn; /* Source GNode */ + size_t prefLen; /* The length of the defined prefix */ + Suff *suff; /* Suffix on matching beastie */ + Src *ret; /* Return value */ + char *cp; + + tgn = targ->node; + prefLen = strlen(targ->pref); + + for (gln = tgn->children->first; gln != NULL; gln = gln->next) { + sgn = gln->datum; + + if (sgn->type & OP_OPTIONAL && Lst_IsEmpty(tgn->commands)) { + /* + * We haven't looked to see if .OPTIONAL files exist yet, so + * don't use one as the implicit source. + * This allows us to use .OPTIONAL in .depend files so make won't + * complain "don't know how to make xxx.h' when a dependent file + * has been moved/deleted. + */ + continue; + } + + cp = strrchr(sgn->name, '/'); + if (cp == NULL) { + cp = sgn->name; + } else { + cp++; + } + if (strncmp(cp, targ->pref, prefLen) != 0) + continue; + /* + * The node matches the prefix ok, see if it has a known + * suffix. + */ + suff = FindSuffByName(cp + prefLen); + if (suff == NULL) + continue; + + /* + * It even has a known suffix, see if there's a transformation + * defined between the node's suffix and the target's suffix. + * + * XXX: Handle multi-stage transformations here, too. + */ + + /* XXX: Can targ->suff be NULL here? */ + if (targ->suff != NULL && + Lst_FindDatum(suff->parents, targ->suff) != NULL) + break; + } + + if (gln == NULL) + return NULL; + + /* + * Hot Damn! Create a new Src structure to describe + * this transformation (making sure to duplicate the + * source node's name so Suff_FindDeps can free it + * again (ick)), and return the new structure. + */ + ret = SrcNew(bmake_strdup(sgn->name), targ->pref, suff, targ, sgn); + suff->refCount++; + targ->children++; +#ifdef DEBUG_SRC + debug_printf("3 add targ %p ret %p\n", targ, ret); + Lst_Append(targ->childrenList, ret); +#endif + Lst_Append(slst, ret); + SUFF_DEBUG1("\tusing existing source %s\n", sgn->name); + return ret; +} + +/* Expand the names of any children of a given node that contain variable + * expressions or file wildcards into actual targets. + * + * The expanded node is removed from the parent's list of children, and the + * parent's unmade counter is decremented, but other nodes may be added. + * + * Input: + * cln Child to examine + * pgn Parent node being processed + */ +static void +SuffExpandChildren(GNodeListNode *cln, GNode *pgn) +{ + GNode *cgn = cln->datum; + GNode *gn; /* New source 8) */ + char *cp; /* Expanded value */ + + if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ)) + /* It is all too hard to process the result of .ORDER */ + return; + + if (cgn->type & OP_WAIT) + /* Ignore these (& OP_PHONY ?) */ + return; + + /* + * First do variable expansion -- this takes precedence over + * wildcard expansion. If the result contains wildcards, they'll be gotten + * to later since the resulting words are tacked on to the end of + * the children list. + */ + if (strchr(cgn->name, '$') == NULL) { + SuffExpandWildcards(cln, pgn); + return; + } + + SUFF_DEBUG1("Expanding \"%s\"...", cgn->name); + (void)Var_Subst(cgn->name, pgn, VARE_UNDEFERR|VARE_WANTRES, &cp); + /* TODO: handle errors */ + + { + GNodeList *members = Lst_New(); + + if (cgn->type & OP_ARCHV) { + /* + * Node was an archive(member) target, so we want to call + * on the Arch module to find the nodes for us, expanding + * variables in the parent's context. + */ + char *sacrifice = cp; + + (void)Arch_ParseArchive(&sacrifice, members, pgn); + } else { + /* + * Break the result into a vector of strings whose nodes + * we can find, then add those nodes to the members list. + * Unfortunately, we can't use brk_string b/c it + * doesn't understand about variable specifications with + * spaces in them... + */ + char *start; + char *initcp = cp; /* For freeing... */ + + for (start = cp; *start == ' ' || *start == '\t'; start++) + continue; + cp = start; + while (*cp != '\0') { + if (*cp == ' ' || *cp == '\t') { + /* + * White-space -- terminate element, find the node, + * add it, skip any further spaces. + */ + *cp++ = '\0'; + gn = Targ_GetNode(start); + Lst_Append(members, gn); + while (*cp == ' ' || *cp == '\t') { + cp++; + } + start = cp; /* Continue at the next non-space. */ + } else if (*cp == '$') { + /* + * Start of a variable spec -- contact variable module + * to find the end so we can skip over it. + */ + const char *nested_p = cp; + const char *junk; + void *freeIt; + + /* XXX: Why VARE_WANTRES when the result is not used? */ + (void)Var_Parse(&nested_p, pgn, + VARE_UNDEFERR|VARE_WANTRES, + &junk, &freeIt); + /* TODO: handle errors */ + if (junk == var_Error) { + Parse_Error(PARSE_FATAL, + "Malformed variable expression at \"%s\"", + cp); + cp++; + } else { + cp += nested_p - cp; + } + + free(freeIt); + } else if (*cp == '\\' && cp[1] != '\0') { + /* + * Escaped something -- skip over it + */ + /* XXX: In other places, escaping at this syntactical + * position is done by a '$', not a '\'. The '\' is only + * used in variable modifiers. */ + cp += 2; + } else { + cp++; + } + } + + if (cp != start) { + /* + * Stuff left over -- add it to the list too + */ + gn = Targ_GetNode(start); + Lst_Append(members, gn); + } + /* + * Point cp back at the beginning again so the variable value + * can be freed. + */ + cp = initcp; + } + + /* + * Add all elements of the members list to the parent node. + */ + while(!Lst_IsEmpty(members)) { + gn = Lst_Dequeue(members); + + SUFF_DEBUG1("%s...", gn->name); + /* Add gn to the parents child list before the original child */ + Lst_InsertBefore(pgn->children, cln, gn); + Lst_Append(gn->parents, pgn); + pgn->unmade++; + /* Expand wildcards on new node */ + SuffExpandWildcards(cln->prev, pgn); + } + Lst_Free(members); + + /* + * Free the result + */ + free(cp); + } + + SUFF_DEBUG0("\n"); + + /* + * Now the source is expanded, remove it from the list of children to + * keep it from being processed. + */ + pgn->unmade--; + Lst_Remove(pgn->children, cln); + Lst_Remove(cgn->parents, Lst_FindDatum(cgn->parents, pgn)); +} + +static void +SuffExpandWildcards(GNodeListNode *cln, GNode *pgn) +{ + GNode *cgn = cln->datum; + StringList *explist; + + if (!Dir_HasWildcards(cgn->name)) + return; + + /* + * Expand the word along the chosen path + */ + explist = Lst_New(); + Dir_Expand(cgn->name, Suff_FindPath(cgn), explist); + + while (!Lst_IsEmpty(explist)) { + GNode *gn; + /* + * Fetch next expansion off the list and find its GNode + */ + char *cp = Lst_Dequeue(explist); + + SUFF_DEBUG1("%s...", cp); + gn = Targ_GetNode(cp); + + /* Add gn to the parents child list before the original child */ + Lst_InsertBefore(pgn->children, cln, gn); + Lst_Append(gn->parents, pgn); + pgn->unmade++; + } + + Lst_Free(explist); + + SUFF_DEBUG0("\n"); + + /* + * Now the source is expanded, remove it from the list of children to + * keep it from being processed. + */ + pgn->unmade--; + Lst_Remove(pgn->children, cln); + Lst_Remove(cgn->parents, Lst_FindDatum(cgn->parents, pgn)); +} + +/* Find a path along which to expand the node. + * + * If the word has a known suffix, use that path. + * If it has no known suffix, use the default system search path. + * + * Input: + * gn Node being examined + * + * Results: + * The appropriate path to search for the GNode. + */ +SearchPath * +Suff_FindPath(GNode* gn) +{ + Suff *suff = gn->suffix; + + if (suff == NULL) { + char *name = gn->name; + size_t nameLen = strlen(gn->name); + SuffListNode *ln; + for (ln = sufflist->first; ln != NULL; ln = ln->next) + if (SuffSuffIsSuffix(ln->datum, nameLen, name + nameLen)) + break; + + SUFF_DEBUG1("Wildcard expanding \"%s\"...", gn->name); + if (ln != NULL) + suff = ln->datum; + /* XXX: Here we can save the suffix so we don't have to do this again */ + } + + if (suff != NULL) { + SUFF_DEBUG1("suffix is \"%s\"...\n", suff->name); + return suff->searchPath; + } else { + SUFF_DEBUG0("\n"); + return dirSearchPath; /* Use default search path */ + } +} + +/* Apply a transformation rule, given the source and target nodes and + * suffixes. + * + * Input: + * tGn Target node + * sGn Source node + * t Target suffix + * s Source suffix + * + * Results: + * TRUE if successful, FALSE if not. + * + * Side Effects: + * The source and target are linked and the commands from the + * transformation are added to the target node's commands list. + * All attributes but OP_DEPMASK and OP_TRANSFORM are applied + * to the target. The target also inherits all the sources for + * the transformation rule. + */ +static Boolean +SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) +{ + GNodeListNode *ln, *nln; /* General node */ + char *tname; /* Name of transformation rule */ + GNode *gn; /* Node for same */ + + /* + * Form the proper links between the target and source. + */ + Lst_Append(tGn->children, sGn); + Lst_Append(sGn->parents, tGn); + tGn->unmade++; + + /* + * Locate the transformation rule itself + */ + tname = str_concat2(s->name, t->name); + gn = FindTransformByName(tname); + free(tname); + + if (gn == NULL) { + /* + * Not really such a transformation rule (can happen when we're + * called to link an OP_MEMBER and OP_ARCHV node), so return + * FALSE. + */ + return FALSE; + } + + SUFF_DEBUG3("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); + + /* + * Record last child for expansion purposes + */ + ln = tGn->children->last; + + /* + * Pass the buck to Make_HandleUse to apply the rule + */ + (void)Make_HandleUse(gn, tGn); + + /* + * Deal with wildcards and variables in any acquired sources + */ + for (ln = ln != NULL ? ln->next : NULL; ln != NULL; ln = nln) { + nln = ln->next; + SuffExpandChildren(ln, tGn); + } + + /* + * Keep track of another parent to which this beast is transformed so + * the .IMPSRC variable can be set correctly for the parent. + */ + Lst_Append(sGn->implicitParents, tGn); + + return TRUE; +} + + +/* Locate dependencies for an OP_ARCHV node. + * + * Input: + * gn Node for which to locate dependencies + * + * Side Effects: + * Same as Suff_FindDeps + */ +static void +SuffFindArchiveDeps(GNode *gn, SrcList *slst) +{ + char *eoarch; /* End of archive portion */ + char *eoname; /* End of member portion */ + GNode *mem; /* Node for member */ + SuffListNode *ln, *nln; /* Next suffix node to check */ + Suff *ms; /* Suffix descriptor for member */ + char *name; /* Start of member's name */ + + /* + * The node is an archive(member) pair. so we must find a + * suffix for both of them. + */ + eoarch = strchr(gn->name, '('); + eoname = strchr(eoarch, ')'); + + /* + * Caller guarantees the format `libname(member)', via + * Arch_ParseArchive. + */ + assert(eoarch != NULL); + assert(eoname != NULL); + + *eoname = '\0'; /* Nuke parentheses during suffix search */ + *eoarch = '\0'; /* So a suffix can be found */ + + name = eoarch + 1; + + /* + * To simplify things, call Suff_FindDeps recursively on the member now, + * so we can simply compare the member's .PREFIX and .TARGET variables + * to locate its suffix. This allows us to figure out the suffix to + * use for the archive without having to do a quadratic search over the + * suffix list, backtracking for each one... + */ + mem = Targ_GetNode(name); + SuffFindDeps(mem, slst); + + /* + * Create the link between the two nodes right off + */ + Lst_Append(gn->children, mem); + Lst_Append(mem->parents, gn); + gn->unmade++; + + /* + * Copy in the variables from the member node to this one. + */ + Var_Set(PREFIX, GNode_VarPrefix(mem), gn); + Var_Set(TARGET, GNode_VarTarget(mem), gn); + + ms = mem->suffix; + if (ms == NULL) { + /* + * Didn't know what it was -- use .NULL suffix if not in make mode + */ + SUFF_DEBUG0("using null suffix\n"); + ms = suffNull; + } + + + /* + * Set the other two local variables required for this target. + */ + Var_Set(MEMBER, name, gn); + Var_Set(ARCHIVE, gn->name, gn); + + /* + * Set $@ for compatibility with other makes + */ + Var_Set(TARGET, gn->name, gn); + + /* + * Now we've got the important local variables set, expand any sources + * that still contain variables or wildcards in their names. + */ + for (ln = gn->children->first; ln != NULL; ln = nln) { + nln = ln->next; + SuffExpandChildren(ln, gn); + } + + if (ms != NULL) { + /* + * Member has a known suffix, so look for a transformation rule from + * it to a possible suffix of the archive. Rather than searching + * through the entire list, we just look at suffixes to which the + * member's suffix may be transformed... + */ + size_t nameLen = (size_t)(eoarch - gn->name); + + /* Use first matching suffix... */ + for (ln = ms->parents->first; ln != NULL; ln = ln->next) + if (SuffSuffIsSuffix(ln->datum, nameLen, eoarch)) + break; + + if (ln != NULL) { + /* + * Got one -- apply it + */ + Suff *suff = ln->datum; + if (!SuffApplyTransform(gn, mem, suff, ms)) { + SUFF_DEBUG2("\tNo transformation from %s -> %s\n", + ms->name, suff->name); + } + } + } + + /* + * Replace the opening and closing parens now we've no need of the separate + * pieces. + */ + *eoarch = '('; *eoname = ')'; + + /* + * Pretend gn appeared to the left of a dependency operator so + * the user needn't provide a transformation from the member to the + * archive. + */ + if (!GNode_IsTarget(gn)) { + gn->type |= OP_DEPENDS; + } + + /* + * Flag the member as such so we remember to look in the archive for + * its modification time. The OP_JOIN | OP_MADE is needed because this + * target should never get made. + */ + mem->type |= OP_MEMBER | OP_JOIN | OP_MADE; +} + +static void +SuffFindNormalDepsKnown(const char *name, size_t nameLen, GNode *gn, + SrcList *srcs, SrcList *targs) +{ + SuffListNode *ln; + Src *targ; + char *pref; + + for (ln = sufflist->first; ln != NULL; ln = ln->next) { + Suff *suff = ln->datum; + if (!SuffSuffIsSuffix(suff, nameLen, name + nameLen)) + continue; + + pref = bmake_strldup(name, (size_t)(nameLen - suff->nameLen)); + targ = SrcNew(bmake_strdup(gn->name), pref, suff, NULL, gn); + suff->refCount++; + + /* + * Add nodes from which the target can be made + */ + SuffAddLevel(srcs, targ); + + /* + * Record the target so we can nuke it + */ + Lst_Append(targs, targ); + } +} + +static void +SuffFindNormalDepsUnknown(GNode *gn, const char *sopref, + SrcList *srcs, SrcList *targs) +{ + Src *targ; + + if (!Lst_IsEmpty(targs) || suffNull == NULL) + return; + + SUFF_DEBUG1("\tNo known suffix on %s. Using .NULL suffix\n", gn->name); + + targ = SrcNew(bmake_strdup(gn->name), bmake_strdup(sopref), + suffNull, NULL, gn); + targ->suff->refCount++; + + /* + * Only use the default suffix rules if we don't have commands + * defined for this gnode; traditional make programs used to + * not define suffix rules if the gnode had children but we + * don't do this anymore. + */ + if (Lst_IsEmpty(gn->commands)) + SuffAddLevel(srcs, targ); + else { + SUFF_DEBUG0("not "); + } + + SUFF_DEBUG0("adding suffix rules\n"); + + Lst_Append(targs, targ); +} + +/* + * Deal with finding the thing on the default search path. We + * always do that, not only if the node is only a source (not + * on the lhs of a dependency operator or [XXX] it has neither + * children or commands) as the old pmake did. + */ +static void +SuffFindNormalDepsPath(GNode *gn, Src *targ) +{ + if (gn->type & (OP_PHONY | OP_NOPATH)) + return; + + free(gn->path); + gn->path = Dir_FindFile(gn->name, + (targ == NULL ? dirSearchPath : + targ->suff->searchPath)); + if (gn->path == NULL) + return; + + Var_Set(TARGET, gn->path, gn); + + if (targ != NULL) { + /* + * Suffix known for the thing -- trim the suffix off + * the path to form the proper .PREFIX variable. + */ + size_t savep = strlen(gn->path) - targ->suff->nameLen; + char savec; + char *ptr; + + if (gn->suffix) + gn->suffix->refCount--; + gn->suffix = targ->suff; + gn->suffix->refCount++; + + savec = gn->path[savep]; + gn->path[savep] = '\0'; + + if ((ptr = strrchr(gn->path, '/')) != NULL) + ptr++; + else + ptr = gn->path; + + Var_Set(PREFIX, ptr, gn); + + gn->path[savep] = savec; + } else { + char *ptr; + + /* The .PREFIX gets the full path if the target has no known suffix. */ + if (gn->suffix) + gn->suffix->refCount--; + gn->suffix = NULL; + + if ((ptr = strrchr(gn->path, '/')) != NULL) + ptr++; + else + ptr = gn->path; + + Var_Set(PREFIX, ptr, gn); + } +} + +/* Locate implicit dependencies for regular targets. + * + * Input: + * gn Node for which to find sources + * + * Side Effects: + * Same as Suff_FindDeps + */ +static void +SuffFindNormalDeps(GNode *gn, SrcList *slst) +{ + SrcList *srcs; /* List of sources at which to look */ + SrcList *targs; /* List of targets to which things can be + * transformed. They all have the same file, + * but different suff and pref fields */ + Src *bottom; /* Start of found transformation path */ + Src *src; /* General Src pointer */ + char *pref; /* Prefix to use */ + Src *targ; /* General Src target pointer */ + + const char *name = gn->name; + size_t nameLen = strlen(name); + + /* + * Begin at the beginning... + */ + srcs = Lst_New(); + targs = Lst_New(); + + /* + * We're caught in a catch-22 here. On the one hand, we want to use any + * transformation implied by the target's sources, but we can't examine + * the sources until we've expanded any variables/wildcards they may hold, + * and we can't do that until we've set up the target's local variables + * and we can't do that until we know what the proper suffix for the + * target is (in case there are two suffixes one of which is a suffix of + * the other) and we can't know that until we've found its implied + * source, which we may not want to use if there's an existing source + * that implies a different transformation. + * + * In an attempt to get around this, which may not work all the time, + * but should work most of the time, we look for implied sources first, + * checking transformations to all possible suffixes of the target, + * use what we find to set the target's local variables, expand the + * children, then look for any overriding transformations they imply. + * Should we find one, we discard the one we found before. + */ + bottom = NULL; + targ = NULL; + + if (!(gn->type & OP_PHONY)) { + + SuffFindNormalDepsKnown(name, nameLen, gn, srcs, targs); + + /* Handle target of unknown suffix... */ + SuffFindNormalDepsUnknown(gn, name, srcs, targs); + + /* + * Using the list of possible sources built up from the target + * suffix(es), try and find an existing file/target that matches. + */ + bottom = SuffFindThem(srcs, slst); + + if (bottom == NULL) { + /* + * No known transformations -- use the first suffix found + * for setting the local variables. + */ + if (!Lst_IsEmpty(targs)) { + targ = targs->first->datum; + } else { + targ = NULL; + } + } else { + /* + * Work up the transformation path to find the suffix of the + * target to which the transformation was made. + */ + for (targ = bottom; targ->parent != NULL; targ = targ->parent) + continue; + } + } + + Var_Set(TARGET, GNode_Path(gn), gn); + + pref = (targ != NULL) ? targ->pref : gn->name; + Var_Set(PREFIX, pref, gn); + + /* + * Now we've got the important local variables set, expand any sources + * that still contain variables or wildcards in their names. + */ + { + SuffListNode *ln, *nln; + for (ln = gn->children->first; ln != NULL; ln = nln) { + nln = ln->next; + SuffExpandChildren(ln, gn); + } + } + + if (targ == NULL) { + SUFF_DEBUG1("\tNo valid suffix on %s\n", gn->name); + +sfnd_abort: + SuffFindNormalDepsPath(gn, targ); + goto sfnd_return; + } + + /* + * If the suffix indicates that the target is a library, mark that in + * the node's type field. + */ + if (targ->suff->flags & SUFF_LIBRARY) { + gn->type |= OP_LIB; + } + + /* + * Check for overriding transformation rule implied by sources + */ + if (!Lst_IsEmpty(gn->children)) { + src = SuffFindCmds(targ, slst); + + if (src != NULL) { + /* + * Free up all the Src structures in the transformation path + * up to, but not including, the parent node. + */ + while (bottom && bottom->parent != NULL) { + if (Lst_FindDatum(slst, bottom) == NULL) { + Lst_Append(slst, bottom); + } + bottom = bottom->parent; + } + bottom = src; + } + } + + if (bottom == NULL) { + /* + * No idea from where it can come -- return now. + */ + goto sfnd_abort; + } + + /* + * We now have a list of Src structures headed by 'bottom' and linked via + * their 'parent' pointers. What we do next is create links between + * source and target nodes (which may or may not have been created) + * and set the necessary local variables in each target. The + * commands for each target are set from the commands of the + * transformation rule used to get from the src suffix to the targ + * suffix. Note that this causes the commands list of the original + * node, gn, to be replaced by the commands of the final + * transformation rule. Also, the unmade field of gn is incremented. + * Etc. + */ + if (bottom->node == NULL) { + bottom->node = Targ_GetNode(bottom->file); + } + + for (src = bottom; src->parent != NULL; src = src->parent) { + targ = src->parent; + + if (src->node->suffix) + src->node->suffix->refCount--; + src->node->suffix = src->suff; + src->node->suffix->refCount++; + + if (targ->node == NULL) { + targ->node = Targ_GetNode(targ->file); + } + + SuffApplyTransform(targ->node, src->node, + targ->suff, src->suff); + + if (targ->node != gn) { + /* + * Finish off the dependency-search process for any nodes + * between bottom and gn (no point in questing around the + * filesystem for their implicit source when it's already + * known). Note that the node can't have any sources that + * need expanding, since SuffFindThem will stop on an existing + * node, so all we need to do is set the standard and System V + * variables. + */ + targ->node->type |= OP_DEPS_FOUND; + + Var_Set(PREFIX, targ->pref, targ->node); + + Var_Set(TARGET, targ->node->name, targ->node); + } + } + + if (gn->suffix) + gn->suffix->refCount--; + gn->suffix = src->suff; + gn->suffix->refCount++; + + /* + * Nuke the transformation path and the Src structures left over in the + * two lists. + */ +sfnd_return: + if (bottom) + if (Lst_FindDatum(slst, bottom) == NULL) + Lst_Append(slst, bottom); + + while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs)) + continue; + + Lst_MoveAll(slst, srcs); + Lst_MoveAll(slst, targs); +} + + +/* Find implicit sources for the target described by the graph node. + * + * Nodes are added to the graph below the passed-in node. The nodes are + * marked to have their IMPSRC variable filled in. The PREFIX variable is set + * for the given node and all its implied children. + * + * The path found by this target is the shortest path in the transformation + * graph, which may pass through non-existent targets, to an existing target. + * The search continues on all paths from the root suffix until a file is + * found. I.e. if there's a path .o -> .c -> .l -> .l,v from the root and the + * .l,v file exists but the .c and .l files don't, the search will branch out + * in all directions from .o and again from all the nodes on the next level + * until the .l,v node is encountered. + */ +void +Suff_FindDeps(GNode *gn) +{ + + SuffFindDeps(gn, srclist); + while (SuffRemoveSrc(srclist)) + continue; +} + +static void +SuffFindDeps(GNode *gn, SrcList *slst) +{ + if (gn->type & OP_DEPS_FOUND) + return; + gn->type |= OP_DEPS_FOUND; + + /* + * Make sure we have these set, may get revised below. + */ + Var_Set(TARGET, GNode_Path(gn), gn); + Var_Set(PREFIX, gn->name, gn); + + SUFF_DEBUG1("SuffFindDeps (%s)\n", gn->name); + + if (gn->type & OP_ARCHV) { + SuffFindArchiveDeps(gn, slst); + } else if (gn->type & OP_LIB) { + /* + * If the node is a library, it is the arch module's job to find it + * and set the TARGET variable accordingly. We merely provide the + * search path, assuming all libraries end in ".a" (if the suffix + * hasn't been defined, there's nothing we can do for it, so we just + * set the TARGET variable to the node's name in order to give it a + * value). + */ + Suff *s = FindSuffByName(LIBSUFF); + if (gn->suffix) + gn->suffix->refCount--; + if (s != NULL) { + gn->suffix = s; + gn->suffix->refCount++; + Arch_FindLib(gn, s->searchPath); + } else { + gn->suffix = NULL; + Var_Set(TARGET, gn->name, gn); + } + /* + * Because a library (-lfoo) target doesn't follow the standard + * filesystem conventions, we don't set the regular variables for + * the thing. .PREFIX is simply made empty... + */ + Var_Set(PREFIX, "", gn); + } else { + SuffFindNormalDeps(gn, slst); + } +} + +/* Define which suffix is the null suffix. + * + * Need to handle the changing of the null suffix gracefully so the old + * transformation rules don't just go away. + * + * Input: + * name Name of null suffix + */ +void +Suff_SetNull(const char *name) +{ + Suff *s = FindSuffByName(name); + if (s == NULL) { + Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", + name); + return; + } + + if (suffNull != NULL) { + suffNull->flags &= ~(unsigned)SUFF_NULL; + } + s->flags |= SUFF_NULL; + /* + * XXX: Here's where the transformation mangling would take place + */ + suffNull = s; +} + +/* Initialize the suffixes module. */ +void +Suff_Init(void) +{ +#ifdef CLEANUP + suffClean = Lst_New(); + sufflist = Lst_New(); +#endif + srclist = Lst_New(); + transforms = Lst_New(); + + /* + * Create null suffix for single-suffix rules (POSIX). The thing doesn't + * actually go on the suffix list or everyone will think that's its + * suffix. + */ + Suff_ClearSuffixes(); +} + + +/* Clean up the suffixes module. */ +void +Suff_End(void) +{ +#ifdef CLEANUP + Lst_Destroy(sufflist, SuffFree); + Lst_Destroy(suffClean, SuffFree); + if (suffNull) + SuffFree(suffNull); + Lst_Free(srclist); + Lst_Free(transforms); +#endif +} + + +/********************* DEBUGGING FUNCTIONS **********************/ + +static void +PrintSuffNames(const char *prefix, SuffList *suffs) +{ + SuffListNode *ln; + + debug_printf("#\t%s: ", prefix); + for (ln = suffs->first; ln != NULL; ln = ln->next) { + Suff *suff = ln->datum; + debug_printf("%s ", suff->name); + } + debug_printf("\n"); +} + +static void +PrintSuff(Suff *s) +{ + debug_printf("# \"%s\" (num %d, ref %d)", s->name, s->sNum, s->refCount); + if (s->flags != 0) { + char flags_buf[SuffFlags_ToStringSize]; + + debug_printf(" (%s)", + Enum_FlagsToString(flags_buf, sizeof flags_buf, + s->flags, SuffFlags_ToStringSpecs)); + } + debug_printf("\n"); + + PrintSuffNames("To", s->parents); + PrintSuffNames("From", s->children); + + debug_printf("#\tSearch Path: "); + Dir_PrintPath(s->searchPath); + debug_printf("\n"); +} + +static void +PrintTransformation(GNode *t) +{ + debug_printf("%-16s:", t->name); + Targ_PrintType(t->type); + debug_printf("\n"); + Targ_PrintCmds(t); + debug_printf("\n"); +} + +void +Suff_PrintAll(void) +{ + debug_printf("#*** Suffixes:\n"); + { + SuffListNode *ln; + for (ln = sufflist->first; ln != NULL; ln = ln->next) + PrintSuff(ln->datum); + } + + debug_printf("#*** Transformations:\n"); + { + GNodeListNode *ln; + for (ln = transforms->first; ln != NULL; ln = ln->next) + PrintTransformation(ln->datum); + } +} Property changes on: vendor/NetBSD/bmake/20201101/suff.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/targ.c =================================================================== --- vendor/NetBSD/bmake/20201101/targ.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/targ.c (revision 367461) @@ -0,0 +1,571 @@ +/* $NetBSD: targ.c,v 1.126 2020/10/30 07:19:30 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/*- + * targ.c -- + * Functions for maintaining the Lst allTargets. Target nodes are + * kept in two structures: a Lst and a hash table. + * + * Interface: + * Targ_Init Initialization procedure. + * + * Targ_End Clean up the module + * + * Targ_List Return the list of all targets so far. + * + * Targ_NewGN Create a new GNode for the passed target + * (string). The node is *not* placed in the + * hash table, though all its fields are + * initialized. + * + * Targ_FindNode Find the node, or return NULL. + * + * Targ_GetNode Find the node, or create it. + * + * Targ_NewInternalNode + * Create an internal node. + * + * Targ_FindList Given a list of names, find nodes for all + * of them, creating them as necessary. + * + * Targ_Ignore Return TRUE if errors should be ignored when + * creating the given target. + * + * Targ_Silent Return TRUE if we should be silent when + * creating the given target. + * + * 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. + * Should be called after the makefiles are parsed + * but before any action is taken. + * + * Debugging: + * Targ_PrintGraph + * Print out the entire graphm all variables and + * statistics for the directory cache. Should print + * something for suffixes, too, but... + */ + +#include + +#include "make.h" +#include "dir.h" + +/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: targ.c,v 1.126 2020/10/30 07:19:30 rillig Exp $"); + +static GNodeList *allTargets; /* the list of all targets found so far */ +#ifdef CLEANUP +static GNodeList *allGNs; /* List of all the GNodes */ +#endif +static HashTable targets; /* a hash table of same */ + +#ifdef CLEANUP +static void TargFreeGN(void *); +#endif + +void +Targ_Init(void) +{ + allTargets = Lst_New(); + HashTable_Init(&targets); +} + +void +Targ_End(void) +{ + Targ_Stats(); +#ifdef CLEANUP + Lst_Free(allTargets); + if (allGNs != NULL) + Lst_Destroy(allGNs, TargFreeGN); + HashTable_Done(&targets); +#endif +} + +void +Targ_Stats(void) +{ + HashTable_DebugStats(&targets, "targets"); +} + +/* Return the list of all targets. */ +GNodeList * +Targ_List(void) +{ + return allTargets; +} + +/* Create and initialize a new graph node. The gnode is added to the list of + * all gnodes. + * + * Input: + * name the name of the node, such as "clean", "src.c", ".END" + */ +GNode * +Targ_NewGN(const char *name) +{ + GNode *gn; + + gn = bmake_malloc(sizeof(GNode)); + gn->name = bmake_strdup(name); + gn->uname = NULL; + gn->path = NULL; + gn->type = name[0] == '-' && name[1] == 'l' ? OP_LIB : 0; + gn->unmade = 0; + gn->unmade_cohorts = 0; + gn->cohort_num[0] = '\0'; + gn->centurion = NULL; + gn->made = UNMADE; + gn->flags = 0; + gn->checked_seqno = 0; + gn->mtime = 0; + gn->youngestChild = NULL; + gn->implicitParents = Lst_New(); + gn->cohorts = Lst_New(); + gn->parents = Lst_New(); + gn->children = Lst_New(); + gn->order_pred = Lst_New(); + gn->order_succ = Lst_New(); + HashTable_Init(&gn->context); + gn->commands = Lst_New(); + gn->suffix = NULL; + gn->fname = NULL; + gn->lineno = 0; + +#ifdef CLEANUP + if (allGNs == NULL) + allGNs = Lst_New(); + Lst_Append(allGNs, gn); +#endif + + return gn; +} + +#ifdef CLEANUP +static void +TargFreeGN(void *gnp) +{ + GNode *gn = gnp; + + free(gn->name); + free(gn->uname); + free(gn->path); + + Lst_Free(gn->implicitParents); + Lst_Free(gn->cohorts); + Lst_Free(gn->parents); + Lst_Free(gn->children); + Lst_Free(gn->order_succ); + Lst_Free(gn->order_pred); + HashTable_Done(&gn->context); + Lst_Free(gn->commands); + + /* XXX: does gn->suffix need to be freed? It is reference-counted. */ + + free(gn); +} +#endif + +/* Get the existing global node, or return NULL. */ +GNode * +Targ_FindNode(const char *name) +{ + return HashTable_FindValue(&targets, name); +} + +/* Get the existing global node, or create it. */ +GNode * +Targ_GetNode(const char *name) +{ + Boolean isNew; + HashEntry *he = HashTable_CreateEntry(&targets, name, &isNew); + if (!isNew) + return HashEntry_Get(he); + + { + GNode *gn = Targ_NewInternalNode(name); + HashEntry_Set(he, gn); + return gn; + } +} + +/* Create a node, register it in .ALLTARGETS but don't store it in the + * table of global nodes. This means it cannot be found by name. + * + * This is used for internal nodes, such as cohorts or .WAIT nodes. */ +GNode * +Targ_NewInternalNode(const char *name) +{ + GNode *gn = Targ_NewGN(name); + Var_Append(".ALLTARGETS", name, VAR_GLOBAL); + Lst_Append(allTargets, gn); + if (doing_depend) + gn->flags |= FROM_DEPEND; + return gn; +} + +/* Return the .END node, which contains the commands to be executed when + * everything else is done. */ +GNode *Targ_GetEndNode(void) +{ + /* Save the node locally to avoid having to search for it all the time. */ + static GNode *endNode = NULL; + if (endNode == NULL) { + endNode = Targ_GetNode(".END"); + endNode->type = OP_SPECIAL; + } + return endNode; +} + +/* Return the named nodes, creating them as necessary. */ +GNodeList * +Targ_FindList(StringList *names) +{ + StringListNode *ln; + GNodeList *nodes = Lst_New(); + for (ln = names->first; ln != NULL; ln = ln->next) { + const char *name = ln->datum; + GNode *gn = Targ_GetNode(name); + Lst_Append(nodes, gn); + } + return nodes; +} + +/* Return true if should ignore errors when creating gn. */ +Boolean +Targ_Ignore(GNode *gn) +{ + return opts.ignoreErrors || gn->type & OP_IGNORE; +} + +/* Return true if be silent when creating gn. */ +Boolean +Targ_Silent(GNode *gn) +{ + return opts.beSilent || gn->type & OP_SILENT; +} + +/* See if the given target is precious. */ +Boolean +Targ_Precious(GNode *gn) +{ + return allPrecious || gn->type & (OP_PRECIOUS | OP_DOUBLEDEP); +} + +/******************* DEBUG INFO PRINTING ****************/ + +static GNode *mainTarg; /* the main target, as set by Targ_SetMain */ + +/* Set our idea of the main target we'll be creating. Used for debugging + * output. */ +void +Targ_SetMain(GNode *gn) +{ + mainTarg = gn; +} + +static void +PrintNodeNames(GNodeList *gnodes) +{ + GNodeListNode *node; + + for (node = gnodes->first; node != NULL; node = node->next) { + GNode *gn = node->datum; + debug_printf(" %s%s", gn->name, gn->cohort_num); + } +} + +static void +PrintNodeNamesLine(const char *label, GNodeList *gnodes) +{ + if (Lst_IsEmpty(gnodes)) + return; + debug_printf("# %s:", label); + PrintNodeNames(gnodes); + debug_printf("\n"); +} + +void +Targ_PrintCmds(GNode *gn) +{ + StringListNode *ln; + for (ln = gn->commands->first; ln != NULL; ln = ln->next) { + const char *cmd = ln->datum; + debug_printf("\t%s\n", cmd); + } +} + +/* Format a modification time in some reasonable way and return it. + * The time is placed in a static area, so it is overwritten with each call. */ +char * +Targ_FmtTime(time_t tm) +{ + struct tm *parts; + static char buf[128]; + + parts = localtime(&tm); + (void)strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts); + return buf; +} + +/* Print out a type field giving only those attributes the user can set. */ +void +Targ_PrintType(int type) +{ + int tbit; + +#define PRINTBIT(attr) case CONCAT(OP_,attr): debug_printf(" ." #attr); break +#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))debug_printf(" ." #attr); break + + type &= ~OP_OPMASK; + + while (type) { + tbit = 1 << (ffs(type) - 1); + type &= ~tbit; + + switch(tbit) { + PRINTBIT(OPTIONAL); + PRINTBIT(USE); + PRINTBIT(EXEC); + PRINTBIT(IGNORE); + PRINTBIT(PRECIOUS); + PRINTBIT(SILENT); + PRINTBIT(MAKE); + PRINTBIT(JOIN); + PRINTBIT(INVISIBLE); + PRINTBIT(NOTMAIN); + PRINTDBIT(LIB); + /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ + case OP_MEMBER: if (DEBUG(TARG))debug_printf(" .MEMBER"); break; + PRINTDBIT(ARCHV); + PRINTDBIT(MADE); + PRINTDBIT(PHONY); + } + } +} + +static const char * +made_name(GNodeMade made) +{ + switch (made) { + case UNMADE: return "unmade"; + case DEFERRED: return "deferred"; + case REQUESTED: return "requested"; + case BEINGMADE: return "being made"; + case MADE: return "made"; + case UPTODATE: return "up-to-date"; + case ERROR: return "error when made"; + case ABORTED: return "aborted"; + default: return "unknown enum_made value"; + } +} + +static const char * +GNode_OpName(const GNode *gn) +{ + switch (gn->type & OP_OPMASK) { + case OP_DEPENDS: + return ":"; + case OP_FORCE: + return "!"; + case OP_DOUBLEDEP: + return "::"; + } + return ""; +} + +/* Print the contents of a node. */ +void +Targ_PrintNode(GNode *gn, int pass) +{ + debug_printf("# %s%s", gn->name, gn->cohort_num); + GNode_FprintDetails(opts.debug_file, ", ", gn, "\n"); + if (gn->flags == 0) + return; + + if (GNode_IsTarget(gn)) { + debug_printf("#\n"); + if (gn == mainTarg) { + debug_printf("# *** MAIN TARGET ***\n"); + } + if (pass >= 2) { + if (gn->unmade) { + debug_printf("# %d unmade children\n", gn->unmade); + } else { + debug_printf("# No unmade children\n"); + } + if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { + if (gn->mtime != 0) { + debug_printf("# last modified %s: %s\n", + Targ_FmtTime(gn->mtime), + made_name(gn->made)); + } else if (gn->made != UNMADE) { + debug_printf("# non-existent (maybe): %s\n", + made_name(gn->made)); + } else { + debug_printf("# unmade\n"); + } + } + PrintNodeNamesLine("implicit parents", gn->implicitParents); + } else { + if (gn->unmade) + debug_printf("# %d unmade children\n", gn->unmade); + } + PrintNodeNamesLine("parents", gn->parents); + PrintNodeNamesLine("order_pred", gn->order_pred); + PrintNodeNamesLine("order_succ", gn->order_succ); + + debug_printf("%-16s%s", gn->name, GNode_OpName(gn)); + Targ_PrintType(gn->type); + PrintNodeNames(gn->children); + debug_printf("\n"); + Targ_PrintCmds(gn); + debug_printf("\n\n"); + if (gn->type & OP_DOUBLEDEP) { + Targ_PrintNodes(gn->cohorts, pass); + } + } +} + +void +Targ_PrintNodes(GNodeList *gnodes, int pass) +{ + GNodeListNode *ln; + for (ln = gnodes->first; ln != NULL; ln = ln->next) + Targ_PrintNode(ln->datum, pass); +} + +/* Print only those targets that are just a source. */ +static void +PrintOnlySources(void) +{ + GNodeListNode *ln; + + for (ln = allTargets->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + if (GNode_IsTarget(gn)) + continue; + + debug_printf("#\t%s [%s]", gn->name, GNode_Path(gn)); + Targ_PrintType(gn->type); + debug_printf("\n"); + } +} + +/* Input: + * pass 1 => before processing + * 2 => after processing + * 3 => after processing, an error occurred + */ +void +Targ_PrintGraph(int pass) +{ + debug_printf("#*** Input graph:\n"); + Targ_PrintNodes(allTargets, pass); + debug_printf("\n\n"); + debug_printf("#\n# Files that are only sources:\n"); + PrintOnlySources(); + debug_printf("#*** Global Variables:\n"); + Var_Dump(VAR_GLOBAL); + debug_printf("#*** Command-line Variables:\n"); + Var_Dump(VAR_CMDLINE); + debug_printf("\n"); + Dir_PrintDirectories(); + debug_printf("\n"); + Suff_PrintAll(); +} + +/* Propagate some type information to cohort nodes (those from the :: + * dependency operator). + * + * Should be called after the makefiles are parsed but before any action is + * taken. */ +void +Targ_Propagate(void) +{ + GNodeListNode *ln, *cln; + + for (ln = allTargets->first; ln != NULL; ln = ln->next) { + GNode *gn = ln->datum; + GNodeType type = gn->type; + + if (!(type & OP_DOUBLEDEP)) + continue; + + for (cln = gn->cohorts->first; cln != NULL; cln = cln->next) { + GNode *cohort = cln->datum; + + cohort->type |= type & ~OP_OPMASK; + } + } +} Property changes on: vendor/NetBSD/bmake/20201101/targ.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/trace.c =================================================================== --- vendor/NetBSD/bmake/20201101/trace.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/trace.c (revision 367461) @@ -0,0 +1,107 @@ +/* $NetBSD: trace.c,v 1.21 2020/10/31 22:05:56 rillig Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bill Sommerfeld + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/*- + * trace.c -- + * handle logging of trace events generated by various parts of make. + * + * Interface: + * Trace_Init Initialize tracing (called once during + * the lifetime of the process) + * + * Trace_End Finalize tracing (called before make exits) + * + * Trace_Log Log an event about a particular make job. + */ + +#include + +#include "make.h" +#include "job.h" +#include "trace.h" + +MAKE_RCSID("$NetBSD: trace.c,v 1.21 2020/10/31 22:05:56 rillig Exp $"); + +static FILE *trfile; +static pid_t trpid; +const char *trwd; + +static const char *evname[] = { + "BEG", + "END", + "ERR", + "JOB", + "DON", + "INT", +}; + +void +Trace_Init(const char *pathname) +{ + if (pathname != NULL) { + void *dontFreeIt; + trpid = getpid(); + /* XXX: This variable may get overwritten later, which + * would make trwd point to undefined behavior. */ + trwd = Var_Value(".CURDIR", VAR_GLOBAL, &dontFreeIt); + + trfile = fopen(pathname, "a"); + } +} + +void +Trace_Log(TrEvent event, Job *job) +{ + struct timeval rightnow; + + if (trfile == NULL) + return; + + gettimeofday(&rightnow, NULL); + + fprintf(trfile, "%lld.%06ld %d %s %d %s", + (long long)rightnow.tv_sec, (long)rightnow.tv_usec, + jobTokensRunning, + evname[event], trpid, trwd); + if (job != NULL) { + fprintf(trfile, " %s %d %x %x", job->node->name, + job->pid, job->flags, job->node->type); + } + fputc('\n', trfile); + fflush(trfile); +} + +void +Trace_End(void) +{ + if (trfile != NULL) + fclose(trfile); +} Property changes on: vendor/NetBSD/bmake/20201101/trace.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/trace.h =================================================================== --- vendor/NetBSD/bmake/20201101/trace.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/trace.h (revision 367461) @@ -0,0 +1,49 @@ +/* $NetBSD: trace.h,v 1.4 2020/10/18 17:19:54 rillig Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bill Sommerfeld + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/*- + * trace.h -- + * Definitions pertaining to the tracing of jobs in parallel mode. + */ + +typedef enum TrEvent { + MAKESTART, + MAKEEND, + MAKEERROR, + JOBSTART, + JOBEND, + MAKEINTR +} TrEvent; + +void Trace_Init(const char *); +void Trace_Log(TrEvent, Job *); +void Trace_End(void); + Property changes on: vendor/NetBSD/bmake/20201101/trace.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/Makefile =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/Makefile (revision 367461) @@ -0,0 +1,565 @@ +# $Id: Makefile,v 1.107 2020/11/02 00:40:25 sjg Exp $ +# +# $NetBSD: Makefile,v 1.181 2020/11/01 19:02:22 rillig Exp $ +# +# Unit tests for make(1) +# +# The main targets are: +# +# all: +# run all the tests +# test: +# run 'all', and compare to expected results +# accept: +# move generated output to expected results +# +# Settable variables +# +# TEST_MAKE +# The make program to be tested. +# +# +# Adding a test case +# +# Each feature should get its own set of tests in its own suitably +# named makefile (*.mk), with its own set of expected results (*.exp), +# and it should be added to the TESTS list. +# +# A few *.mk files are helper files for other tests (such as include-sub.mk) +# and are thus not added to TESTS. Such files must be ignored in +# src/tests/usr.bin/make/t_make.sh. +# + +# Each test is in a sub-makefile. +# Keep the list sorted. +# Any test that is commented out must be ignored in +# src/tests/usr.bin/make/t_make.sh as well. +#TESTS+= archive +TESTS+= archive-suffix +TESTS+= cmd-interrupt +TESTS+= cmdline +TESTS+= comment +TESTS+= cond-cmp-numeric +TESTS+= cond-cmp-numeric-eq +TESTS+= cond-cmp-numeric-ge +TESTS+= cond-cmp-numeric-gt +TESTS+= cond-cmp-numeric-le +TESTS+= cond-cmp-numeric-lt +TESTS+= cond-cmp-numeric-ne +TESTS+= cond-cmp-string +TESTS+= cond-cmp-unary +TESTS+= cond-func +TESTS+= cond-func-commands +TESTS+= cond-func-defined +TESTS+= cond-func-empty +TESTS+= cond-func-exists +TESTS+= cond-func-make +TESTS+= cond-func-target +TESTS+= cond-late +TESTS+= cond-op +TESTS+= cond-op-and +TESTS+= cond-op-not +TESTS+= cond-op-or +TESTS+= cond-op-parentheses +TESTS+= cond-short +TESTS+= cond-token-number +TESTS+= cond-token-plain +TESTS+= cond-token-string +TESTS+= cond-token-var +TESTS+= cond-undef-lint +TESTS+= cond1 +TESTS+= counter +TESTS+= counter-append +TESTS+= dep +TESTS+= dep-colon +TESTS+= dep-colon-bug-cross-file +TESTS+= dep-double-colon +TESTS+= dep-double-colon-indep +TESTS+= dep-exclam +TESTS+= dep-none +TESTS+= dep-percent +TESTS+= dep-var +TESTS+= dep-wildcards +TESTS+= depsrc +TESTS+= depsrc-end +TESTS+= depsrc-exec +TESTS+= depsrc-ignore +TESTS+= depsrc-made +TESTS+= depsrc-make +TESTS+= depsrc-meta +TESTS+= depsrc-nometa +TESTS+= depsrc-nometa_cmp +TESTS+= depsrc-nopath +TESTS+= depsrc-notmain +TESTS+= depsrc-optional +TESTS+= depsrc-phony +TESTS+= depsrc-precious +TESTS+= depsrc-recursive +TESTS+= depsrc-silent +TESTS+= depsrc-use +TESTS+= depsrc-usebefore +TESTS+= depsrc-usebefore-double-colon +TESTS+= depsrc-wait +TESTS+= deptgt +TESTS+= deptgt-begin +TESTS+= deptgt-default +TESTS+= deptgt-delete_on_error +TESTS+= deptgt-end +TESTS+= deptgt-end-jobs +TESTS+= deptgt-error +TESTS+= deptgt-ignore +TESTS+= deptgt-interrupt +TESTS+= deptgt-main +TESTS+= deptgt-makeflags +TESTS+= deptgt-no_parallel +TESTS+= deptgt-nopath +TESTS+= deptgt-notparallel +TESTS+= deptgt-objdir +TESTS+= deptgt-order +TESTS+= deptgt-path +TESTS+= deptgt-path-suffix +TESTS+= deptgt-phony +TESTS+= deptgt-precious +TESTS+= deptgt-shell +TESTS+= deptgt-silent +TESTS+= deptgt-stale +TESTS+= deptgt-suffixes +TESTS+= dir +TESTS+= dir-expand-path +TESTS+= directive +TESTS+= directive-dinclude +TESTS+= directive-elif +TESTS+= directive-elifdef +TESTS+= directive-elifmake +TESTS+= directive-elifndef +TESTS+= directive-elifnmake +TESTS+= directive-else +TESTS+= directive-endif +TESTS+= directive-error +TESTS+= directive-export +TESTS+= directive-export-env +TESTS+= directive-export-gmake +TESTS+= directive-export-literal +TESTS+= directive-for +TESTS+= directive-for-generating-endif +TESTS+= directive-hyphen-include +TESTS+= directive-if +TESTS+= directive-ifdef +TESTS+= directive-ifmake +TESTS+= directive-ifndef +TESTS+= directive-ifnmake +TESTS+= directive-include +TESTS+= directive-include-fatal +TESTS+= directive-info +TESTS+= directive-sinclude +TESTS+= directive-undef +TESTS+= directive-unexport +TESTS+= directive-unexport-env +TESTS+= directive-warning +TESTS+= directives +TESTS+= dollar +TESTS+= doterror +TESTS+= dotwait +TESTS+= envfirst +TESTS+= error +TESTS+= # escape # broken by reverting POSIX changes +TESTS+= export +TESTS+= export-all +TESTS+= export-env +TESTS+= export-variants +TESTS+= forloop +TESTS+= forsubst +TESTS+= hanoi-include +TESTS+= impsrc +TESTS+= include-main +#TESTS+= job-output-long-lines +TESTS+= lint +TESTS+= make-exported +TESTS+= moderrs +TESTS+= modmatch +TESTS+= modmisc +TESTS+= modts +TESTS+= modword +TESTS+= opt +TESTS+= opt-backwards +TESTS+= opt-chdir +TESTS+= opt-debug +TESTS+= opt-debug-all +TESTS+= opt-debug-archive +TESTS+= opt-debug-curdir +TESTS+= opt-debug-cond +TESTS+= opt-debug-dir +TESTS+= opt-debug-errors +TESTS+= opt-debug-file +TESTS+= opt-debug-for +TESTS+= opt-debug-graph1 +TESTS+= opt-debug-graph2 +TESTS+= opt-debug-graph3 +TESTS+= opt-debug-hash +#TESTS+= opt-debug-jobs +TESTS+= opt-debug-lint +TESTS+= opt-debug-loud +TESTS+= opt-debug-meta +TESTS+= opt-debug-making +TESTS+= opt-debug-no-rm +TESTS+= opt-debug-parse +TESTS+= opt-debug-suff +TESTS+= opt-debug-targets +TESTS+= opt-debug-varraw +TESTS+= opt-debug-var +TESTS+= opt-debug-x-trace +TESTS+= opt-define +TESTS+= opt-env +TESTS+= opt-file +TESTS+= opt-ignore +TESTS+= opt-include-dir +TESTS+= opt-jobs +TESTS+= opt-jobs-internal +TESTS+= opt-keep-going +TESTS+= opt-m-include-dir +TESTS+= opt-no-action +TESTS+= opt-no-action-at-all +TESTS+= opt-query +TESTS+= opt-raw +TESTS+= opt-silent +TESTS+= opt-touch +TESTS+= opt-tracefile +TESTS+= opt-var-expanded +TESTS+= opt-var-literal +TESTS+= opt-warnings-as-errors +TESTS+= opt-where-am-i +TESTS+= opt-x-reduce-exported +TESTS+= order +TESTS+= parse-var +TESTS+= phony-end +TESTS+= posix +TESTS+= # posix1 # broken by reverting POSIX changes +TESTS+= qequals +TESTS+= recursive +TESTS+= sh +TESTS+= sh-dots +TESTS+= sh-jobs +TESTS+= sh-jobs-error +TESTS+= sh-leading-at +TESTS+= sh-leading-hyphen +TESTS+= sh-leading-plus +TESTS+= sh-meta-chars +TESTS+= sh-multi-line +TESTS+= sh-single-line +TESTS+= shell-csh +TESTS+= shell-custom +TESTS+= shell-ksh +TESTS+= shell-sh +TESTS+= suff-add-later +TESTS+= suff-clear-regular +TESTS+= suff-clear-single +TESTS+= suff-lookup +TESTS+= suff-main +TESTS+= suff-rebuild +TESTS+= suff-transform-endless +TESTS+= suff-transform-expand +TESTS+= suff-transform-select +TESTS+= sunshcmd +TESTS+= ternary +TESTS+= unexport +TESTS+= unexport-env +TESTS+= use-inference +TESTS+= var-class +TESTS+= var-class-cmdline +TESTS+= var-class-env +TESTS+= var-class-global +TESTS+= var-class-local +TESTS+= var-class-local-legacy +TESTS+= var-op +TESTS+= var-op-append +TESTS+= var-op-assign +TESTS+= var-op-default +TESTS+= var-op-expand +TESTS+= var-op-shell +TESTS+= var-op-sunsh +TESTS+= var-recursive +TESTS+= varcmd +TESTS+= vardebug +TESTS+= varfind +TESTS+= varmisc +TESTS+= varmod +TESTS+= varmod-assign +TESTS+= varmod-defined +TESTS+= varmod-edge +TESTS+= varmod-exclam-shell +TESTS+= varmod-extension +TESTS+= varmod-gmtime +TESTS+= varmod-hash +TESTS+= varmod-head +TESTS+= varmod-ifelse +TESTS+= varmod-l-name-to-value +TESTS+= varmod-localtime +TESTS+= varmod-loop +TESTS+= varmod-match +TESTS+= varmod-match-escape +TESTS+= varmod-no-match +TESTS+= varmod-order +TESTS+= varmod-order-reverse +TESTS+= varmod-order-shuffle +TESTS+= varmod-path +TESTS+= varmod-quote +TESTS+= varmod-quote-dollar +TESTS+= varmod-range +TESTS+= varmod-remember +TESTS+= varmod-root +TESTS+= varmod-select-words +TESTS+= varmod-shell +TESTS+= varmod-subst +TESTS+= varmod-subst-regex +TESTS+= varmod-sysv +TESTS+= varmod-tail +TESTS+= varmod-to-abs +TESTS+= varmod-to-lower +TESTS+= varmod-to-many-words +TESTS+= varmod-to-one-word +TESTS+= varmod-to-separator +TESTS+= varmod-to-upper +TESTS+= varmod-undefined +TESTS+= varmod-unique +TESTS+= varname +TESTS+= varname-dollar +TESTS+= varname-dot-alltargets +TESTS+= varname-dot-curdir +TESTS+= varname-dot-includes +TESTS+= varname-dot-includedfromdir +TESTS+= varname-dot-includedfromfile +TESTS+= varname-dot-libs +TESTS+= varname-dot-make-dependfile +TESTS+= varname-dot-make-expand_variables +TESTS+= varname-dot-make-exported +TESTS+= varname-dot-make-jobs +TESTS+= varname-dot-make-jobs-prefix +TESTS+= varname-dot-make-level +TESTS+= varname-dot-make-makefile_preference +TESTS+= varname-dot-make-makefiles +TESTS+= varname-dot-make-meta-bailiwick +TESTS+= varname-dot-make-meta-created +TESTS+= varname-dot-make-meta-files +TESTS+= varname-dot-make-meta-ignore_filter +TESTS+= varname-dot-make-meta-ignore_paths +TESTS+= varname-dot-make-meta-ignore_patterns +TESTS+= varname-dot-make-meta-prefix +TESTS+= varname-dot-make-mode +TESTS+= varname-dot-make-path_filemon +TESTS+= varname-dot-make-pid +TESTS+= varname-dot-make-ppid +TESTS+= varname-dot-make-save_dollars +TESTS+= varname-dot-makeoverrides +TESTS+= varname-dot-newline +TESTS+= varname-dot-objdir +TESTS+= varname-dot-parsedir +TESTS+= varname-dot-parsefile +TESTS+= varname-dot-path +TESTS+= varname-dot-shell +TESTS+= varname-dot-targets +TESTS+= varname-empty +TESTS+= varname-make +TESTS+= varname-make_print_var_on_error +TESTS+= varname-make_print_var_on_error-jobs +TESTS+= varname-makefile +TESTS+= varname-makeflags +TESTS+= varname-pwd +TESTS+= varname-vpath +TESTS+= varparse-dynamic +TESTS+= varparse-mod +TESTS+= varparse-undef-partial +TESTS+= varquote +TESTS+= varshell + +# Additional environment variables for some of the tests. +# The base environment is -i PATH="$PATH". +ENV.envfirst= FROM_ENV=value-from-env +ENV.varmisc= FROM_ENV=env +ENV.varmisc+= FROM_ENV_BEFORE=env +ENV.varmisc+= FROM_ENV_AFTER=env +ENV.varmod-localtime+= TZ=Europe/Berlin + +# Override make flags for some of the tests; default is -k. +# If possible, write ".MAKEFLAGS: -dv" in the test .mk file instead of +# settings FLAGS.test=-dv here, since that is closer to the test code. +FLAGS.cond-func-make= via-cmdline +FLAGS.directive-ifmake= first second +FLAGS.doterror= # none +FLAGS.envfirst= -e +FLAGS.export= # none +FLAGS.opt-ignore= -i +FLAGS.opt-keep-going= -k +FLAGS.opt-no-action= -n +FLAGS.opt-query= -q +FLAGS.opt-var-expanded= -v VAR -v VALUE +FLAGS.opt-var-literal= -V VAR -V VALUE +FLAGS.opt-warnings-as-errors= -W +FLAGS.order= -j1 +FLAGS.recursive= -dL +FLAGS.sh-leading-plus= -n +FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmline-plain' + +# Some tests need extra postprocessing. +SED_CMDS.export= \ + -e '/^[^=_A-Za-z0-9]*=/d' +# these all share the same requirement +.for t in export-all export-env +SED_CMDS.$t= ${SED_CMDS.export} +.endfor +SED_CMDS.job-output-long-lines= \ + ${:D Job separators on their own line are ok. } \ + -e '/^--- job-[ab] ---$$/d' \ + ${:D Plain output lines are ok as well. } \ + ${:D They may come in multiples of 1024 or as 10000. } \ + -e '/^aa*$$/d' \ + -e '/^bb*$$/d' \ + ${:D The following lines should rather not occur since the job } \ + ${:D marker should always be at the beginning of the line. } \ + -e '/^aa*--- job-b ---$$/d' \ + -e '/^bb*--- job-a ---$$/d' +SED_CMDS.opt-debug-graph1= \ + -e 's,${.CURDIR},CURDIR,' +SED_CMDS.opt-debug-graph1+= \ + -e '/Global Variables:/,/Suffixes:/d' +SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,,' +SED_CMDS.opt-debug-jobs= -e 's,([0-9][0-9]*),(),' +SED_CMDS.opt-debug-jobs+= -e 's,pid [0-9][0-9]*,pid ,' +SED_CMDS.opt-debug-jobs+= -e 's,Process [0-9][0-9]*,Process ,' +SED_CMDS.opt-debug-jobs+= -e 's,JobFinish: [0-9][0-9]*,JobFinish: ,' +# The "-q" may be there or not, see jobs.c, variable shells. +SED_CMDS.opt-debug-jobs+= -e 's,^\(.Command: sh\) -q,\1,' +SED_CMDS.varmod-subst-regex+= \ + -e 's,\(Regex compilation error:\).*,\1 (details omitted),' +SED_CMDS.varmod-edge+= -e 's, line [0-9]*:, line omitted:,' +SED_CMDS.varshell+= -e 's,^${.SHELL:T}: ,,' +SED_CMDS.varshell+= -e '/command/s,No such.*,not found,' +SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: ",' +SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: ",' +SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g' +SED_CMDS.varname-dot-shell+= -e 's,"/[^" ]*","(details omitted)",g' +SED_CMDS.varname-dot-shell+= -e 's,\[/[^] ]*\],[(details omitted)],g' + +# Some tests need an additional round of postprocessing. +POSTPROC.deptgt-suffixes= \ + ${TOOL_SED} -n -e '/^\#\*\*\* Suffixes/,/^\#\*/p' +POSTPROC.varname= ${TOOL_SED} -n -e '/^MAGIC/p' -e '/^ORDER_/p' +POSTPROC.varname-empty= ${TOOL_SED} -n -e '/^Var_Set/p' -e '/^out:/p' + +# Some tests reuse other tests, which makes them unnecessarily fragile. +export-all.rawout: export.mk +unexport.rawout: export.mk +unexport-env.rawout: export.mk + +# End of the configuration section. + +.MAIN: all + +.-include "Makefile.inc" +.-include "Makefile.config" + +UNIT_TESTS:= ${.PARSEDIR} +.PATH: ${UNIT_TESTS} + +.if ${USE_ABSOLUTE_TESTNAMES:Uno} == yes +OUTFILES= ${TESTS:@test@${.CURDIR:tA}/${test}.out@} +.else +OUTFILES= ${TESTS:=.out} +.endif + +all: ${OUTFILES} + +CLEANFILES= *.rawout *.out *.status *.tmp *.core *.tmp +CLEANFILES+= obj*.[och] lib*.a # posix1.mk +CLEANFILES+= issue* .[ab]* # suffixes.mk +CLEANDIRS= dir dummy # posix1.mk + +clean: + rm -f ${CLEANFILES} + rm -rf ${CLEANDIRS} + +TEST_MAKE?= ${.MAKE} +TOOL_SED?= sed +TOOL_TR?= tr +TOOL_DIFF?= diff +DIFF_FLAGS?= -u + +.if defined(.PARSEDIR) +# ensure consistent results from sort(1) +LC_ALL= C +LANG= C +.export LANG LC_ALL +.endif + +.if ${.MAKE.MODE:Unormal:Mmeta} != "" +# we don't need the noise +_MKMSG_TEST= : +.endif + +MAKE_TEST_ENV?= MALLOC_OPTIONS="JA" # for jemalloc + +# Each test is run in a sub-make, to keep the tests for interfering with +# each other, and because they use different environment variables and +# command line options. +.SUFFIXES: .mk .rawout .out +.mk.rawout: + @${_MKMSG_TEST:Uecho '# test '} ${.PREFIX} + @set -eu; \ + cd ${.OBJDIR}; \ + env -i PATH="$$PATH" ${MAKE_TEST_ENV} ${ENV.${.PREFIX:T}} \ + ${TEST_MAKE} \ + -r -C ${.CURDIR} -f ${.IMPSRC} \ + ${FLAGS.${.PREFIX:T}:U-k} \ + > ${.TARGET}.tmp 2>&1 \ + && status=$$? || status=$$?; \ + echo $$status > ${.TARGET:R}.status + @mv ${.TARGET}.tmp ${.TARGET} + +# Postprocess the test output so that the results can be compared. +# +# always pretend .MAKE was called 'make' +_SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,' +_SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,' +# replace anything after 'stopped in' with unit-tests +_SED_CMDS+= -e '/stopped/s, /.*, unit-tests,' +# strip ${.CURDIR}/ from the output +_SED_CMDS+= -e 's,${.CURDIR:S,.,\\.,g}/,,g' +_SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g' + +.rawout.out: + @${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} \ + < ${.IMPSRC} > ${.TARGET}.tmp1 + @${POSTPROC.${.PREFIX:T}:Ucat} < ${.TARGET}.tmp1 > ${.TARGET}.tmp2 + @rm ${.TARGET}.tmp1 + @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp2 + @mv ${.TARGET}.tmp2 ${.TARGET} + +# Compare all output files +test: ${OUTFILES} .PHONY + @failed= ; \ + for test in ${TESTS}; do \ + ${TOOL_DIFF} ${DIFF_FLAGS} ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || failed="$${failed}$${failed:+ }$${test}" ; \ + done ; \ + if [ -n "$${failed}" ]; then \ + echo "Failed tests: $${failed}" ; false ; \ + else \ + echo "All tests passed" ; \ + fi + +accept: + @for test in ${TESTS}; do \ + cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \ + || { echo "Replacing $${test}.exp" ; \ + cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \ + done + +.if exists(${TEST_MAKE}) +${TESTS:=.rawout}: ${TEST_MAKE} +# in meta mode, we *know* if a target script is impacted +# by a makefile change. +.if ${.MAKE.MODE:Unormal:Mmeta} == "" +${TESTS:=.rawout}: ${.PARSEDIR}/Makefile +.endif +.endif + +.-include Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/archive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/archive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/archive.exp (revision 367461) @@ -0,0 +1,28 @@ +Making remove-archive +rm -f libprog.a + +Making libprog.a out-of-date archive.mk modmisc.mk varmisc.mk +ar cru libprog.a archive.mk modmisc.mk varmisc.mk +ranlib libprog.a + +Making create-archive out-of-date libprog.a + +Making list-archive out-of-date libprog.a +ar t libprog.a +archive.mk +modmisc.mk +varmisc.mk + +Making list-archive-wildcard out-of-date archive-suffix.mk archive.mk ternary.mk +list-archive-wildcard: archive-suffix.mk +list-archive-wildcard: archive.mk +list-archive-wildcard: ternary.mk + +Making depend-on-existing-member out-of-date archive.mk +depend-on-existing-member + +`depend-on-nonexistent-member' is up to date. +Making remove-archive +rm -f libprog.a + +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/archive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/archive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/archive.mk (revision 367461) @@ -0,0 +1,62 @@ +# $NetBSD: archive.mk,v 1.10 2020/10/09 06:44:42 rillig Exp $ +# +# Very basic demonstration of handling archives, based on the description +# in PSD.doc/tutorial.ms. +# +# This test aims at covering the code, not at being an introduction to +# archive handling. That's why it is more complicated and detailed than +# strictly necessary. + +ARCHIVE= libprog.a +FILES= archive.mk modmisc.mk varmisc.mk + +MAKE_CMD= ${.MAKE} -f ${MAKEFILE} +RUN?= @set -eu; + +all: +.if ${.PARSEDIR:tA} != ${.CURDIR:tA} + @cd ${MAKEFILE:H} && cp ${FILES} [at]*.mk ${.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 +# targets is run in its separate sub-make. + ${RUN} ${MAKE_CMD} remove-archive + ${RUN} ${MAKE_CMD} create-archive + ${RUN} ${MAKE_CMD} list-archive + ${RUN} ${MAKE_CMD} list-archive-wildcard + ${RUN} ${MAKE_CMD} depend-on-existing-member + ${RUN} ${MAKE_CMD} depend-on-nonexistent-member + ${RUN} ${MAKE_CMD} remove-archive + +create-archive: ${ARCHIVE} pre post + +# The indirect references with the $$ cover the code in Arch_ParseArchive +# that calls Var_Parse. It's an esoteric scenario since at the point where +# Arch_ParseArchive is called, the dependency line is already fully expanded. +# +${ARCHIVE}: $${:Ulibprog.a}(archive.mk modmisc.mk $${:Uvarmisc.mk}) pre post + ar cru ${.TARGET} ${.OODATE:O} + ranlib ${.TARGET} + +list-archive: ${ARCHIVE} pre post + ar t ${.ALLSRC} + +# XXX: I had expected that this dependency would select all *.mk files from +# the archive. Instead, the globbing is done in the current directory. +# To prevent an overly long file list, the pattern is restricted to [at]*.mk. +list-archive-wildcard: ${ARCHIVE}([at]*.mk) pre post + ${RUN} printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@} + +depend-on-existing-member: ${ARCHIVE}(archive.mk) pre post + ${RUN} echo $@ + +depend-on-nonexistent-member: ${ARCHIVE}(nonexistent.mk) pre post + ${RUN} echo $@ + +remove-archive: pre post + rm -f ${ARCHIVE} + +pre: .USEBEFORE + @echo Making ${.TARGET} ${.OODATE:C,.+,out-of-date,W} ${.OODATE:O} +post: .USE + @echo Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/archive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/comment.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/comment.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/comment.exp (revision 367461) @@ -0,0 +1,6 @@ +echo This is a shell comment: # comment +This is a shell comment: +echo This is not a shell comment: '# comment' +This is not a shell comment: # comment +A shell comment can#not start in the middle of a word. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/comment.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/comment.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/comment.mk (revision 367461) @@ -0,0 +1,74 @@ +# $NetBSD: comment.mk,v 1.2 2020/09/07 19:17:36 rillig Exp $ +# +# Demonstrate how comments are written in makefiles. + +# This is a comment. + +#\ +This is a multiline comment. + +# Another multiline comment \ +that \ +goes \ +on and on. + + # Comments can be indented, but that is rather unusual. + + # Comments can be indented with a tab. + # These are not shell commands, they are just makefile comments. + +.if 1 # There can be comments after conditions. +.endif # And after the closing directive. + +VAR= # This comment makes the variable value empty. +.if ${VAR} != "" +. error +.endif + +# The comment does not need to start at the beginning of a word (as in the +# shell), it can start anywhere. +VAR=# defined but empty + +# The space before the comment is always trimmed. +VAR= value +.if ${VAR} != "value" +. error +.endif + +# This is NOT an escaped comment due to the double backslashes \\ +VAR= not part of the comment +.if ${VAR} != "not part of the comment" +. error +.endif + +# To escape a comment sign, precede it with a backslash. +VAR= \# # Both in the assignment. +.if ${VAR} != "\#" # And in the comparison. +. error +.endif + +# Since 2012-03-24 the variable modifier :[#] does not need to be escaped. +# To keep the parsing code simple, any "[#" does not start a comment, even +# outside of a variable expression. +WORDS= ${VAR:[#]} [# +.if ${WORDS} != "1 [#" +. error +.endif + +# An odd number of comment signs makes a line continuation, \\\ +no matter if it is 3 or 5 \\\\\ +or 9 backslashes. \\\\\\\\\ +This is the last line of the comment. +VAR= no comment anymore +.if ${VAR} != "no comment anymore" +. error +.endif + +all: +# In the commands associated with a target, the '#' does not start a makefile +# comment. The '#' is just passed to the shell, like any ordinary character. + echo This is a shell comment: # comment +# If the '#' were to start a makefile comment, the following shell command +# would have unbalanced quotes. + echo This is not a shell comment: '# comment' + @echo A shell comment can#not start in the middle of a word. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/comment.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.exp (revision 367461) @@ -0,0 +1,6 @@ +make: "cond-cmp-numeric-eq.mk" line 54: warning: Unknown operator +make: "cond-cmp-numeric-eq.mk" line 54: Malformed conditional (!(12345 = 12345)) +make: "cond-cmp-numeric-eq.mk" line 61: Malformed conditional (!(12345 === 12345)) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.mk (revision 367461) @@ -0,0 +1,68 @@ +# $NetBSD: cond-cmp-numeric-eq.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the == operator in .if conditions. + +# This comparison yields the same result, whether numeric or character-based. +.if 1 == 1 +.else +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 == 2 +. error +.endif + +.if 2 == 1 +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 == 2000e4 +.else +. error +.endif + +.if 2000e4 == 2e7 +.else +. error +.endif + +# Trailing zeroes after the decimal point are irrelevant for the numeric +# value. +.if 3.30000 == 3.3 +.else +. error +.endif + +.if 3.3 == 3.30000 +.else +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 == 1.000000000000000002 +.else +. error +.endif + + +# There is no = operator for numbers. +.if !(12345 = 12345) +. error +.else +. error +.endif + +# There is no === operator for numbers either. +.if !(12345 === 12345) +. error +.else +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-eq.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.mk (revision 367461) @@ -0,0 +1,75 @@ +# $NetBSD: cond-cmp-numeric-ge.mk,v 1.2 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the >= operator in .if conditions. + +# When both sides are equal, the >= operator always yields true. +.if 1 >= 1 +.else +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 >= 2 +. error +.endif + +.if 2 >= 1 +.else +. error +.endif + +# If this comparison were character-based instead of numerical, the +# 5 would be >= 14 since its first digit is greater. +.if 5 >= 14 +. error +.endif + +.if 14 >= 5 +.else +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 >= 1e8 +. error +.endif + +.if 1e8 >= 2e7 +.else +. error +.endif + +# Floating pointer numbers can be compared as well. +# This might be tempting to use for version numbers, but there are a few pitfalls. +.if 3.141 >= 111.222 +. error +.endif + +.if 111.222 >= 3.141 +.else +. error +.endif + +# When parsed as a version number, 3.30 is greater than 3.7. +# Since make parses numbers as plain numbers, that leads to wrong results. +# Numeric comparisons are not suited for comparing version number. +.if 3.30 >= 3.7 +. error +.endif + +.if 3.7 >= 3.30 +.else +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 >= 1.000000000000000002 +.else +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.mk (revision 367461) @@ -0,0 +1,73 @@ +# $NetBSD: cond-cmp-numeric-gt.mk,v 1.2 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the > operator in .if conditions. + +# When both sides are equal, the > operator always yields false. +.if 1 > 1 +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 > 2 +. error +.endif + +.if 2 > 1 +.else +. error +.endif + +# If this comparison were character-based instead of numerical, the +# 5 would be > 14 since its first digit is greater. +.if 5 > 14 +. error +.endif + +.if 14 > 5 +.else +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 > 1e8 +. error +.endif + +.if 1e8 > 2e7 +.else +. error +.endif + +# Floating pointer numbers can be compared as well. +# This might be tempting to use for version numbers, but there are a few pitfalls. +.if 3.141 > 111.222 +. error +.endif + +.if 111.222 > 3.141 +.else +. error +.endif + +# When parsed as a version number, 3.30 is greater than 3.7. +# Since make parses numbers as plain numbers, that leads to wrong results. +# Numeric comparisons are not suited for comparing version number. +.if 3.30 > 3.7 +. error +.endif + +.if 3.7 > 3.30 +.else +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 > 1.000000000000000002 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.mk (revision 367461) @@ -0,0 +1,75 @@ +# $NetBSD: cond-cmp-numeric-le.mk,v 1.2 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the <= operator in .if conditions. + +# When both sides are equal, the <= operator always yields true. +.if 1 <= 1 +.else +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 <= 2 +.else +. error +.endif + +.if 2 <= 1 +. error +.endif + +# If this comparison were character-based instead of numerical, the +# 5 would be >= 14 since its first digit is greater. +.if 5 <= 14 +.else +. error +.endif + +.if 14 <= 5 +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 <= 1e8 +.else +. error +.endif + +.if 1e8 <= 2e7 +. error +.endif + +# Floating pointer numbers can be compared as well. +# This might be tempting to use for version numbers, but there are a few pitfalls. +.if 3.141 <= 111.222 +.else +. error +.endif + +.if 111.222 <= 3.141 +. error +.endif + +# When parsed as a version number, 3.30 is greater than 3.7. +# Since make parses numbers as plain numbers, that leads to wrong results. +# Numeric comparisons are not suited for comparing version number. +.if 3.30 <= 3.7 +.else +. error +.endif + +.if 3.7 <= 3.30 +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 <= 1.000000000000000002 +.else +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.mk (revision 367461) @@ -0,0 +1,73 @@ +# $NetBSD: cond-cmp-numeric-lt.mk,v 1.2 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the < operator in .if conditions. + +# When both sides are equal, the < operator always yields false. +.if 1 < 1 +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 < 2 +.else +. error +.endif + +.if 2 < 1 +. error +.endif + +# If this comparison were character-based instead of numerical, the +# 5 would be > 14 since its first digit is greater. +.if 5 < 14 +.else +. error +.endif + +.if 14 < 5 +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 < 1e8 +.else +. error +.endif + +.if 1e8 < 2e7 +. error +.endif + +# Floating pointer numbers can be compared as well. +# This might be tempting to use for version numbers, but there are a few pitfalls. +.if 3.141 < 111.222 +.else +. error +.endif + +.if 111.222 < 3.141 +. error +.endif + +# When parsed as a version number, 3.30 is greater than 3.7. +# Since make parses numbers as plain numbers, that leads to wrong results. +# Numeric comparisons are not suited for comparing version number. +.if 3.30 < 3.7 +.else +. error +.endif + +.if 3.7 < 3.30 +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 < 1.000000000000000002 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.mk (revision 367461) @@ -0,0 +1,49 @@ +# $NetBSD: cond-cmp-numeric-ne.mk,v 1.2 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for numeric comparisons with the != operator in .if conditions. + +# When both sides are equal, the != operator always yields false. +.if 1 != 1 +. error +.endif + +# This comparison yields the same result, whether numeric or character-based. +.if 1 != 2 +.else +. error +.endif + +.if 2 != 1 +.else +. error +.endif + +# Scientific notation is supported, as per strtod. +.if 2e7 != 2000e4 +. error +.endif + +.if 2000e4 != 2e7 +. error +.endif + +# Trailing zeroes after the decimal point are irrelevant for the numeric +# value. +.if 3.30000 != 3.3 +. error +.endif + +.if 3.3 != 3.30000 +. error +.endif + +# As of 2020-08-23, numeric comparison is implemented as parsing both sides +# as double, and then performing a normal comparison. The range of double is +# typically 16 or 17 significant digits, therefore these two numbers seem to +# be equal. +.if 1.000000000000000001 != 1.000000000000000002 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.exp (revision 367461) @@ -0,0 +1,11 @@ +CondParser_Eval: !(${:UINF} > 1e100) +make: "cond-cmp-numeric.mk" line 11: warning: String comparison operator must be either == or != +make: "cond-cmp-numeric.mk" line 11: Malformed conditional (!(${:UINF} > 1e100)) +CondParser_Eval: ${:UNaN} > NaN +make: "cond-cmp-numeric.mk" line 16: warning: String comparison operator must be either == or != +make: "cond-cmp-numeric.mk" line 16: Malformed conditional (${:UNaN} > NaN) +CondParser_Eval: !(${:UNaN} == NaN) +lhs = "NaN", rhs = "NaN", op = == +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.mk (revision 367461) @@ -0,0 +1,29 @@ +# $NetBSD: cond-cmp-numeric.mk,v 1.3 2020/09/12 18:01:51 rillig Exp $ +# +# Tests for numeric comparisons in .if conditions. + +.MAKEFLAGS: -dc + +# The ${:U...} on the left-hand side is necessary for the parser. + +# Even if strtod(3) parses "INF" as +Infinity, make does not accept this +# since it is not really a number; see TryParseNumber. +.if !(${:UINF} > 1e100) +. error +.endif + +# Neither is NaN a number; see TryParseNumber. +.if ${:UNaN} > NaN +. error +.endif + +# Since NaN is not parsed as a number, both operands are interpreted +# as strings and are therefore equal. If they were parsed as numbers, +# they would compare unequal, since NaN is unequal to any and everything, +# including itself. +.if !(${:UNaN} == NaN) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.exp (revision 367461) @@ -0,0 +1,8 @@ +make: "cond-cmp-string.mk" line 18: Malformed conditional (str != str) +make: "cond-cmp-string.mk" line 37: Malformed conditional ("string" != "str""ing") +make: "cond-cmp-string.mk" line 42: warning: String comparison operator must be either == or != +make: "cond-cmp-string.mk" line 42: Malformed conditional (!("value" = "value")) +make: "cond-cmp-string.mk" line 49: Malformed conditional (!("value" === "value")) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.mk (revision 367461) @@ -0,0 +1,90 @@ +# $NetBSD: cond-cmp-string.mk,v 1.11 2020/10/30 14:53:31 rillig Exp $ +# +# Tests for string comparisons in .if conditions. + +# This is a simple comparison of string literals. +# Nothing surprising here. +.if "str" != "str" +. error +.endif + +# The right-hand side of the comparison may be written without quotes. +.if "str" != str +. error +.endif + +# The left-hand side of the comparison must be enclosed in quotes. +# This one is not enclosed in quotes and thus generates an error message. +.if str != str +. error +.endif + +# The left-hand side of the comparison requires a defined variable. +# The variable named "" is not defined, but applying the :U modifier to it +# makes it "kind of defined" (see VAR_KEEP). Therefore it is ok here. +.if ${:Ustr} != "str" +. error +.endif + +# Any character in a string literal may be escaped using a backslash. +# This means that "\n" does not mean a newline but a simple "n". +.if "string" != "\s\t\r\i\n\g" +. error +.endif + +# It is not possible to concatenate two string literals to form a single +# string. +.if "string" != "str""ing" +. error +.endif + +# There is no = operator for strings. +.if !("value" = "value") +. error +.else +. error +.endif + +# There is no === operator for strings either. +.if !("value" === "value") +. error +.else +. error +.endif + +# A variable expression can be enclosed in double quotes. +.if ${:Uword} != "${:Uword}" +. error +.endif + +# Between 2003-01-01 (maybe even earlier) and 2020-10-30, adding one of the +# characters " \t!=><" directly after a variable expression resulted in a +# "Malformed conditional", even though the string was well-formed. +.if ${:Uword } != "${:Uword} " +. error +.endif +# Some other characters worked though, and some didn't. +# Those that are mentioned in is_separator didn't work. +.if ${:Uword0} != "${:Uword}0" +. error +.endif +.if ${:Uword&} != "${:Uword}&" +. error +.endif +.if ${:Uword!} != "${:Uword}!" +. error +.endif +.if ${:Uword<} != "${:Uword}<" +. error +.endif + +# Adding another variable expression to the string literal works though. +.if ${:Uword} != "${:Uwo}${:Urd}" +. error +.endif + +# Adding a space at the beginning of the quoted variable expression works +# though. +.if ${:U word } != " ${:Uword} " +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-string.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.mk (revision 367461) @@ -0,0 +1,43 @@ +# $NetBSD: cond-cmp-unary.mk,v 1.1 2020/09/14 06:22:59 rillig Exp $ +# +# Tests for unary comparisons in .if conditions, that is, comparisons with +# a single operand. If the operand is a number, it is compared to zero, +# if it is a string, it is tested for emptiness. + +# The number 0 evaluates to false. +.if 0 +. error +.endif + +# Any other number evaluates to true. +.if !12345 +. error +.endif + +# The empty string evaluates to false. +.if "" +. error +.endif + +# Any other string evaluates to true. +.if !"0" +. error +.endif + +# The empty string may come from a variable expression. +.if ${:U} +. error +.endif + +# A variable expression that is not surrounded by quotes is interpreted +# as a number if possible, otherwise as a string. +.if ${:U0} +. error +.endif + +# A non-zero number from a variable expression evaluates to true. +.if !${:U12345} +. error +.endif + +all: # nothing Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-unary.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.mk (revision 367461) @@ -0,0 +1,36 @@ +# $NetBSD: cond-func-commands.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the commands() function in .if conditions. + +.MAIN: all + +# The target "target" does not exist yet, therefore it cannot have commands. +.if commands(target) +. error +.endif + +target: + +# Now the target exists, but it still has no commands. +.if commands(target) +. error +.endif + +target: + # not a command + +# Even after the comment, the target still has no commands. +.if commands(target) +. error +.endif + +target: + @:; + +# Finally the target has commands. +.if !commands(target) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.mk (revision 367461) @@ -0,0 +1,33 @@ +# $NetBSD: cond-func-defined.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the defined() function in .if conditions. + +DEF= defined +${:UA B}= variable name with spaces + +.if !defined(DEF) +. error +.endif + +# Horizontal whitespace (space tab) after the opening parenthesis is ignored. +.if !defined( DEF) +. error +.endif + +# Horizontal whitespace (space tab) before the closing parenthesis is ignored. +.if !defined(DEF ) +. error +.endif + +# The argument of a function must not directly contain whitespace. +.if !defined(A B) +. error +.endif + +# If necessary, the whitespace can be generated by a variable expression. +.if !defined(${:UA B}) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.mk (revision 367461) @@ -0,0 +1,150 @@ +# $NetBSD: cond-func-empty.mk,v 1.8 2020/09/23 08:11:28 rillig Exp $ +# +# Tests for the empty() function in .if conditions, which tests a variable +# expression for emptiness. +# +# Note that the argument in the parentheses is indeed a variable name, +# optionally followed by variable modifiers. This is like the defined() +# function. +# + +.undef UNDEF +EMPTY= # empty +SPACE= ${:U } +WORD= word + +# An undefined variable is empty. +.if !empty(UNDEF) +. error +.endif + +# An undefined variable has the empty string as the value, and the :M +# variable modifier does not change that. +# +.if !empty(UNDEF:M*) +. error +.endif + +# The :S modifier replaces the empty value with an actual word, and +# after that the expression is no longer empty. Because the variable +# was undefined in the first place, the expression has the flag VAR_JUNK +# but not VAR_KEEP, therefore it is still considered undefined. +# Only very few variable modifiers turn an undefined variable expression +# into a defined variable expression. The :U and :D modifiers belong to +# that group, but :S doesn't (see VAR_KEEP). +# +# XXX: This is hard to explain to someone who doesn't know these +# implementation details. +# +.if !empty(UNDEF:S,^$,value,W) +. error +.endif + +# The :U modifier modifies expressions based on undefined variables +# (VAR_JUNK) by adding the VAR_KEEP flag, which marks the expression +# as "being interesting enough to be further processed". +# +.if empty(UNDEF:S,^$,value,W:Ufallback) +. error +.endif + +# And now to the surprising part. Applying the following :S modifier to the +# undefined variable makes it non-empty, but the marker VAR_JUNK is preserved +# nevertheless. The :U modifier that follows only looks at VAR_JUNK to decide +# whether the variable is defined or not. This kind of makes sense since the +# :U modifier tests the _variable_, not the _expression_. +# +# But since the variable was undefined to begin with, the fallback value is +# used in this expression. +# +.if ${UNDEF:S,^$,value,W:Ufallback} != "fallback" +. error +.endif + +# The variable EMPTY is completely empty (0 characters). +.if !empty(EMPTY) +. error +.endif + +# The variable SPACE has a single space, which counts as being empty. +.if !empty(SPACE) +. error +.endif + +# The variable .newline has a single newline, which counts as being empty. +.if !empty(.newline) +. error +.endif + +# The empty variable named "" gets a fallback value of " ", which counts as +# empty. +# +# Contrary to the other functions in conditionals, the trailing space is not +# stripped off, as can be seen in the -dv debug log. If the space had been +# stripped, it wouldn't make a difference in this case. +# +.if !empty(:U ) +. error +.endif + +# Now the variable named " " gets a non-empty value, which demonstrates that +# 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. +${:U }= space +.if empty( ) +. error +.endif + +# The value of the following expression is " word", which is not empty. +.if empty(:U word) +. error +.endif + +# The :L modifier creates a variable expression that has the same value as +# its name, which both are "VAR" in this case. The value is therefore not +# empty. +.if empty(VAR:L) +. error +.endif + +# The variable WORD has the value "word", which does not count as empty. +.if empty(WORD) +. error +.endif + +# The expression ${} for a variable with the empty name always evaluates +# to an empty string (see Var_Parse, varUndefined). +.if !empty() +. error +.endif + +# Ensure that variable expressions that appear as part of the argument are +# properly parsed. Typical use cases for this are .for loops, which are +# expanded to exactly these ${:U} expressions. +# +# If everything goes well, the argument expands to "WORD", and that variable +# is defined at the beginning of this file. The surrounding 'W' and 'D' +# ensure that the parser in ParseEmptyArg has the correct position, both +# before and after the call to Var_ParsePP. +.if empty(W${:UOR}D) +. error +.endif + +# There may be spaces at the outside of the parentheses. +# Spaces inside the parentheses are interpreted as part of the variable name. +.if ! empty ( WORD ) +. error +.endif + +${:U WORD }= variable name with spaces + +# Now there is a variable named " WORD ", and it is not empty. +.if empty ( WORD ) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.mk (revision 367461) @@ -0,0 +1,42 @@ +# $NetBSD: cond-func-exists.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the exists() function in .if conditions. + +.if !exists(.) +. error +.endif + +# The argument to the function must not be enclosed in quotes. +# Neither double quotes nor single quotes are allowed. +.if exists(".") +. error +.endif + +.if exists('.') +. error +.endif + +# The only way to escape characters that would otherwise influence the parser +# is to enclose them in a variable expression. For function arguments, +# neither the backslash nor the dollar sign act as escape character. +.if exists(\.) +. error +.endif + +.if !exists(${:U.}) +. error +.endif + +# The argument to the function can have several variable expressions. +# See cond-func.mk for the characters that cannot be used directly. +.if !exists(${.PARSEDIR}/${.PARSEFILE}) +. error +.endif + +# Whitespace is trimmed on both sides of the function argument. +.if !exists( . ) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.exp (revision 367461) @@ -0,0 +1,3 @@ +: via-cmdline +: via-dot-makeflags +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: cond-func-make.mk,v 1.3 2020/09/25 20:11:06 rillig Exp $ +# +# Tests for the make() function in .if conditions, which tests whether +# the argument has been passed as a target via the command line or later +# via the .MAKEFLAGS special dependency target. + +.if !make(via-cmdline) +. error +.endif +.if make(via-dot-makeflags) +. error +.endif + +.MAKEFLAGS: via-dot-makeflags + +.if !make(via-cmdline) +. error +.endif +.if !make(via-dot-makeflags) +. error +.endif + +via-cmdline via-dot-makeflags: + : $@ Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-make.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.mk (revision 367461) @@ -0,0 +1,38 @@ +# $NetBSD: cond-func-target.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the target() function in .if conditions. + +.MAIN: all + +# The target "target" does not exist yet. +.if target(target) +. error +.endif + +target: + +# The target exists, even though it does not have any commands. +.if !target(target) +. error +.endif + +target: + # not a command + +# Adding a comment to an existing target does not change whether the target +# is defined or not. +.if !target(target) +. error +.endif + +target: + @:; + +# Adding a command to an existing target does not change whether the target +# is defined or not. +.if !target(target) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func.mk (revision 367461) @@ -0,0 +1,71 @@ +# $NetBSD: cond-func.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for those parts of the functions in .if conditions that are common +# among several functions. +# +# The below test uses the function defined(...) since it has no side-effects, +# the other functions (except empty(...)) would work equally well. + +DEF= defined +${:UA B}= variable name with spaces +${:UVAR(value)}= variable name with parentheses +${:UVAR{value}}= variable name with braces + +.if !defined(DEF) +. error +.endif + +# Horizontal whitespace (space tab) after the opening parenthesis is ignored. +.if !defined( DEF) +. error +.endif + +# Horizontal whitespace (space tab) before the closing parenthesis is ignored. +.if !defined(DEF ) +. error +.endif + +# The argument of a function must not directly contain whitespace. +.if !defined(A B) +. error +.endif + +# If necessary, the whitespace can be generated by a variable expression. +.if !defined(${:UA B}) +. error +.endif + +# Characters that could be mistaken for operators must not appear directly +# in a function argument. As with whitespace, these can be generated +# indirectly. +# +# It's not entirely clear why these characters are forbidden. +# The most plausible reason seems to be typo detection. +.if !defined(A&B) +. error +.endif +.if !defined(A|B) +. error +.endif + +# Even parentheses may appear in variable names. +# They must be balanced though. +.if !defined(VAR(value)) +. error +.endif + +# Braces do not have any special meaning when parsing arguments. +.if !defined(VAR{value}) +. error +.endif + +# There may be spaces around the operators and parentheses, and even +# inside the parentheses. The spaces inside the parentheses are not +# allowed for the empty() function (see cond-func-empty.mk), therefore +# they are typically omitted for the other functions as well. +.if ! defined ( DEF ) +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-func.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "cond-op-and.mk" line 43: Malformed conditional (0 &&& 0) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.mk (revision 367461) @@ -0,0 +1,48 @@ +# $NetBSD: cond-op-and.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the && operator in .if conditions. + +.if 0 && 0 +. error +.endif + +.if 1 && 0 +. error +.endif + +.if 0 && 1 +. error +.endif + +.if !(1 && 1) +. error +.endif + +# The right-hand side is not evaluated since the left-hand side is already +# false. +.if 0 && ${UNDEF} +.endif + +# The && operator may be abbreviated as &. This is not widely known though +# and is also not documented in the manual page. + +.if 0 & 0 +. error +.endif +.if 1 & 0 +. error +.endif +.if 0 & 1 +. error +.endif +.if !(1 & 1) +. error +.endif + +# There is no operator &&&. +.if 0 &&& 0 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-and.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.mk (revision 367461) @@ -0,0 +1,22 @@ +# $NetBSD: cond-op-not.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the ! operator in .if conditions. + +# The exclamation mark negates its operand. +.if !1 +. error +.endif + +# Exclamation marks can be chained. +# This doesn't happen in practice though. +.if !!!1 +. error +.endif + +# The ! binds more tightly than the &&. +.if !!0 && 1 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "cond-op-or.mk" line 43: Malformed conditional (0 ||| 0) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.mk (revision 367461) @@ -0,0 +1,48 @@ +# $NetBSD: cond-op-or.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the || operator in .if conditions. + +.if 0 || 0 +. error +.endif + +.if !(1 || 0) +. error +.endif + +.if !(0 || 1) +. error +.endif + +.if !(1 || 1) +. error +.endif + +# The right-hand side is not evaluated since the left-hand side is already +# true. +.if 1 || ${UNDEF} +.endif + +# The || operator may be abbreviated as |. This is not widely known though +# and is also not documented in the manual page. + +.if 0 | 0 +. error +.endif +.if !(1 | 0) +. error +.endif +.if !(0 | 1) +. error +.endif +.if !(1 | 1) +. error +.endif + +# There is no operator |||. +.if 0 ||| 0 +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-or.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op.exp (revision 367461) @@ -0,0 +1,7 @@ +make: "cond-op.mk" line 45: Malformed conditional ("!word" == !word) +make: "cond-op.mk" line 70: Malformed conditional (0 ${ERR::=evaluated}) +make: "cond-op.mk" line 74: warning: After detecting a parse error, the rest is evaluated. +make: "cond-op.mk" line 78: Parsing continues until here. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op.mk (revision 367461) @@ -0,0 +1,81 @@ +# $NetBSD: cond-op.mk,v 1.8 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for operators like &&, ||, ! in .if conditions. +# +# See also: +# cond-op-and.mk +# cond-op-not.mk +# cond-op-or.mk +# cond-op-parentheses.mk + +# In make, && binds more tightly than ||, like in C. +# If make had the same precedence for both && and ||, the result would be +# different. +# If || were to bind more tightly than &&, the result would be different +# as well. +.if !(1 || 1 && 0) +. error +.endif + +# If make were to interpret the && and || operators like the shell, the +# implicit binding would be this: +.if (1 || 1) && 0 +. error +.endif + +# The precedence of the ! operator is different from C though. It has a +# lower precedence than the comparison operators. +.if !"word" == "word" +. error +.endif + +# This is how the above condition is actually interpreted. +.if !("word" == "word") +. error +.endif + +# TODO: Demonstrate that the precedence of the ! and == operators actually +# makes a difference. There is a simple example for sure, I just cannot +# wrap my head around it. + +# This condition is malformed because the '!' on the right-hand side must not +# appear unquoted. If any, it must be enclosed in quotes. +# In any case, it is not interpreted as a negation of an unquoted string. +# See CondParser_String. +.if "!word" == !word +. error +.endif + +# Surprisingly, the ampersand and pipe are allowed in bare strings. +# That's another opportunity for writing confusing code. +# See CondParser_String, which only has '!' in the list of stop characters. +.if "a&&b||c" != a&&b||c +. error +.endif + +# As soon as the parser sees the '$', it knows that the condition will +# be malformed. Therefore there is no point in evaluating it. +# +# As of 2020-09-11, that part of the condition is evaluated nevertheless, +# since CondParser_Expr just requests the next token, without restricting +# the token to the expected tokens. If the parser were to restrict the +# valid follow tokens for the token "0" to those that can actually produce +# a correct condition (which in this case would be comparison operators, +# TOK_AND, TOK_OR or TOK_RPAREN), the variable expression would not have +# to be evaluated. +# +# This would add a good deal of complexity to the code though, for almost +# no benefit, especially since most expressions and conditions are side +# effect free. +.if 0 ${ERR::=evaluated} +. error +.endif +.if ${ERR:Uundefined} == evaluated +. warning After detecting a parse error, the rest is evaluated. +.endif + +# Just in case that parsing should ever stop on the first error. +.info Parsing continues until here. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-op.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-short.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-short.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-short.mk (revision 367461) @@ -0,0 +1,171 @@ +# $NetBSD: cond-short.mk,v 1.11 2020/10/24 08:50:17 rillig Exp $ +# +# Demonstrates that in conditions, the right-hand side of an && or || +# is only evaluated if it can actually influence the result. +# +# Between 2015-10-11 and 2020-06-28, the right-hand side of an && or || +# operator was always evaluated, which was wrong. +# + +# The && operator. + +.if 0 && ${echo "unexpected and" 1>&2 :L:sh} +.endif + +.if 1 && ${echo "expected and" 1>&2 :L:sh} +.endif + +.if 0 && exists(nonexistent${echo "unexpected and exists" 1>&2 :L:sh}) +.endif + +.if 1 && exists(nonexistent${echo "expected and exists" 1>&2 :L:sh}) +.endif + +.if 0 && empty(${echo "unexpected and empty" 1>&2 :L:sh}) +.endif + +.if 1 && empty(${echo "expected and empty" 1>&2 :L:sh}) +.endif + +# "VAR U11" is not evaluated; it was evaluated before 2020-07-02. +# The whole !empty condition is only parsed and then discarded. +VAR= ${VAR${:U11${echo "unexpected VAR U11" 1>&2 :L:sh}}} +VAR13= ${VAR${:U12${echo "unexpected VAR13" 1>&2 :L:sh}}} +.if 0 && !empty(VAR${:U13${echo "unexpected U13 condition" 1>&2 :L:sh}}) +.endif + +VAR= ${VAR${:U21${echo "unexpected VAR U21" 1>&2 :L:sh}}} +VAR23= ${VAR${:U22${echo "expected VAR23" 1>&2 :L:sh}}} +.if 1 && !empty(VAR${:U23${echo "expected U23 condition" 1>&2 :L:sh}}) +.endif +VAR= # empty again, for the following tests + +# The :M modifier is only parsed, not evaluated. +# Before 2020-07-02, it was wrongly evaluated. +.if 0 && !empty(VAR:M${:U${echo "unexpected M pattern" 1>&2 :L:sh}}) +.endif + +.if 1 && !empty(VAR:M${:U${echo "expected M pattern" 1>&2 :L:sh}}) +.endif + +.if 0 && !empty(VAR:S,from,${:U${echo "unexpected S modifier" 1>&2 :L:sh}},) +.endif + +.if 0 && !empty(VAR:C,from,${:U${echo "unexpected C modifier" 1>&2 :L:sh}},) +.endif + +.if 0 && !empty("" == "" :? ${:U${echo "unexpected ? modifier" 1>&2 :L:sh}} :) +.endif + +.if 0 && !empty(VAR:old=${:U${echo "unexpected = modifier" 1>&2 :L:sh}}) +.endif + +.if 0 && !empty(1 2 3:L:@var@${:U${echo "unexpected @ modifier" 1>&2 :L:sh}}@) +.endif + +.if 0 && !empty(:U${:!echo "unexpected exclam modifier" 1>&2 !}) +.endif + +# Irrelevant assignment modifiers are skipped as well. +.if 0 && ${1 2 3:L:@i@${FIRST::?=$i}@} +.endif +.if 0 && ${1 2 3:L:@i@${LAST::=$i}@} +.endif +.if 0 && ${1 2 3:L:@i@${APPENDED::+=$i}@} +.endif +.if 0 && ${echo.1 echo.2 echo.3:L:@i@${RAN::!=${i:C,.*,&; & 1>\&2,:S,., ,g}}@} +.endif +.if defined(FIRST) || defined(LAST) || defined(APPENDED) || defined(RAN) +. warning first=${FIRST} last=${LAST} appended=${APPENDED} ran=${RAN} +.endif + +# The || operator. + +.if 1 || ${echo "unexpected or" 1>&2 :L:sh} +.endif + +.if 0 || ${echo "expected or" 1>&2 :L:sh} +.endif + +.if 1 || exists(nonexistent${echo "unexpected or exists" 1>&2 :L:sh}) +.endif + +.if 0 || exists(nonexistent${echo "expected or exists" 1>&2 :L:sh}) +.endif + +.if 1 || empty(${echo "unexpected or empty" 1>&2 :L:sh}) +.endif + +.if 0 || empty(${echo "expected or empty" 1>&2 :L:sh}) +.endif + +# Unreachable nested conditions are skipped completely as well. + +.if 0 +. if ${echo "unexpected nested and" 1>&2 :L:sh} +. endif +.endif + +.if 1 +.elif ${echo "unexpected nested or" 1>&2 :L:sh} +.endif + +# make sure these do not cause complaint +#.MAKEFLAGS: -dc + +V42= 42 +iV1= ${V42} +iV2= ${V66} + +.if defined(V42) && ${V42} > 0 +x= Ok +.else +x= Fail +.endif +x!= echo 'defined(V42) && ${V42} > 0: $x' >&2; echo + +# this one throws both String comparison operator and +# Malformed conditional with cond.c 1.78 +# indirect iV2 would expand to "" and treated as 0 +.if defined(V66) && ( ${iV2} < ${V42} ) +x= Fail +.else +x= Ok +.endif +x!= echo 'defined(V66) && ( "${iV2}" < ${V42} ): $x' >&2; echo + +# next two thow String comparison operator with cond.c 1.78 +# indirect iV1 would expand to 42 +.if 1 || ${iV1} < ${V42} +x= Ok +.else +x= Fail +.endif +x!= echo '1 || ${iV1} < ${V42}: $x' >&2; echo + +.if 1 || ${iV2:U2} < ${V42} +x= Ok +.else +x= Fail +.endif +x!= echo '1 || ${iV2:U2} < ${V42}: $x' >&2; echo + +# the same expressions are fine when the lhs is expanded +# ${iV1} expands to 42 +.if 0 || ${iV1} <= ${V42} +x= Ok +.else +x= Fail +.endif +x!= echo '0 || ${iV1} <= ${V42}: $x' >&2; echo + +# ${iV2:U2} expands to 2 +.if 0 || ${iV2:U2} < ${V42} +x= Ok +.else +x= Fail +.endif +x!= echo '0 || ${iV2:U2} < ${V42}: $x' >&2; echo + +all: + @:;: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-short.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.exp (revision 367461) @@ -0,0 +1,8 @@ +make: "cond-token-number.mk" line 13: Malformed conditional (-0) +make: "cond-token-number.mk" line 21: Malformed conditional (+0) +make: "cond-token-number.mk" line 29: Malformed conditional (!-1) +make: "cond-token-number.mk" line 37: Malformed conditional (!+1) +make: "cond-token-number.mk" line 54: End of the tests. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.mk (revision 367461) @@ -0,0 +1,56 @@ +# $NetBSD: cond-token-number.mk,v 1.3 2020/09/14 06:22:59 rillig Exp $ +# +# Tests for number tokens in .if conditions. + +.if 0 +. error +.endif + +# Even though -0 is a number and would be accepted by strtod, it is not +# accepted by the condition parser. +# +# See the ch_isdigit call in CondParser_String. +.if -0 +. error +.endif + +# Even though +0 is a number and would be accepted by strtod, it is not +# accepted by the condition parser. +# +# See the ch_isdigit call in CondParser_String. +.if +0 +. error +.endif + +# Even though -1 is a number and would be accepted by strtod, it is not +# accepted by the condition parser. +# +# See the ch_isdigit call in CondParser_String. +.if !-1 +. error +.endif + +# Even though +1 is a number and would be accepted by strtod, it is not +# accepted by the condition parser. +# +# See the ch_isdigit call in CondParser_String. +.if !+1 +. error +.endif + +# When the number comes from a variable expression though, it may be signed. +# XXX: This is inconsistent. +.if ${:U+0} +. error +.endif + +# When the number comes from a variable expression though, it may be signed. +# XXX: This is inconsistent. +.if !${:U+1} +. error +.endif + +# Ensure that parsing continues until here. +.info End of the tests. + +all: # nothing Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-number.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.exp (revision 367461) @@ -0,0 +1,29 @@ +CondParser_Eval: ${:Uvalue} != value +lhs = "value", rhs = "value", op = != +CondParser_Eval: ${:U} != " +lhs = "", rhs = "", op = != +CondParser_Eval: ${:U#hash} != "#hash" +lhs = "#hash", rhs = "#hash", op = != +CondParser_Eval: ${:U\\} != "\\ +lhs = "\", rhs = "\", op = != +CondParser_Eval: ${:U#hash} != #hash +lhs = "#hash", rhs = "#hash", op = != +CondParser_Eval: 0 # This is treated as a comment, but why? +CondParser_Eval: ${0 # comment :?yes:no} != no +CondParser_Eval: 0 # comment +lhs = "no", rhs = "no", op = != +CondParser_Eval: ${1 # comment :?yes:no} != yes +CondParser_Eval: 1 # comment +lhs = "yes", rhs = "yes", op = != +CondParser_Eval: ${UNDEF:Uundefined}!=undefined +lhs = "undefined", rhs = "undefined", op = != +CondParser_Eval: ${UNDEF:U12345}>12345 +lhs = 12345.000000, rhs = 12345.000000, op = >1 +CondParser_Eval: ${UNDEF:U12345}<12345 +lhs = 12345.000000, rhs = 12345.000000, op = <1 +CondParser_Eval: (${UNDEF:U0})||0 +CondParser_Eval: ${:Uvar}&&name != "var&&name" +lhs = "var&&name", rhs = "var&&name", op = != +CondParser_Eval: ${:Uvar}||name != "var||name" +lhs = "var||name", rhs = "var||name", op = != +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.mk (revision 367461) @@ -0,0 +1,94 @@ +# $NetBSD: cond-token-plain.mk,v 1.4 2020/09/12 17:47:24 rillig Exp $ +# +# Tests for plain tokens (that is, string literals without quotes) +# in .if conditions. + +.MAKEFLAGS: -dc + +.if ${:Uvalue} != value +. error +.endif + +# Malformed condition since comment parsing is done in an early phase +# and removes the '#' and everything behind it long before the condition +# parser gets to see it. +# +# XXX: The error message is missing for this malformed condition. +# The right-hand side of the comparison is just a '"'. +.if ${:U} != "#hash" +. error +.endif + +# To get a '#' into a condition, it has to be escaped using a backslash. +# This prevents the comment parser from removing it, and in turn, it becomes +# visible to CondParser_String. +.if ${:U\#hash} != "\#hash" +. error +.endif + +# Since 2002-12-30, and still as of 2020-09-11, CondParser_Token handles +# the '#' specially, even though at this point, there should be no need for +# comment handling anymore. The comments are supposed to be stripped off +# in a very early parsing phase. +# +# XXX: Missing error message for the malformed condition. The right-hand +# side is double-quotes, backslash, backslash. +# XXX: It is unexpected that the right-hand side evaluates to a single +# backslash. +.if ${:U\\} != "\\#hash" +. error +.endif + +# The right-hand side of a comparison is not parsed as a token, therefore +# the code from CondParser_Token does not apply to it. +.if ${:U\#hash} != \#hash +. error +.endif + +# XXX: What is the purpose of treating an escaped '#' in the following +# condition as a comment? And why only at the beginning of a token, +# just as in the shell? +.if 0 \# This is treated as a comment, but why? +. error +.endif + +# Ah, ok, this can be used to add an end-of-condition comment. But does +# anybody really use this? This is neither documented nor obvious since +# the '#' is escaped. It's much clearer to write a comment in the line +# above the condition. +.if ${0 \# comment :?yes:no} != no +. error +.endif +.if ${1 \# comment :?yes:no} != yes +. error +.endif + +# Usually there is whitespace around the comparison operator, but this is +# not required. +.if ${UNDEF:Uundefined}!=undefined +. error +.endif +.if ${UNDEF:U12345}>12345 +. error +.endif +.if ${UNDEF:U12345}<12345 +. error +.endif +.if (${UNDEF:U0})||0 +. error +.endif + +# Only the comparison operator terminates the comparison operand, and it's +# a coincidence that the '!' is both used in the '!=' comparison operator +# as well as for negating a comparison result. +# +# The boolean operators '&' and '|' don't terminate a comparison operand. +.if ${:Uvar}&&name != "var&&name" +. error +.endif +.if ${:Uvar}||name != "var||name" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-plain.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.mk (revision 367461) @@ -0,0 +1,34 @@ +# $NetBSD: cond-token-var.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for variables in .if conditions. + +DEF= defined + +# A defined variable may appear on either side of the comparison. +.if ${DEF} == ${DEF} +. info ok +.else +. error +.endif + +# A variable that appears on the left-hand side must be defined. +.if ${UNDEF} == ${DEF} +. error +.endif + +# A variable that appears on the right-hand side must be defined. +.if ${DEF} == ${UNDEF} +. error +.endif + +# A defined variable may appear as an expression of its own. +.if ${DEF} +.endif + +# An undefined variable generates a warning. +.if ${UNDEF} +.endif + +# The :U modifier turns an undefined variable into an ordinary expression. +.if ${UNDEF:U} +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.exp (revision 367461) @@ -0,0 +1,7 @@ +make: "cond-undef-lint.mk" line 23: Variable "UNDEF" is undefined +make: "cond-undef-lint.mk" line 38: Variable "UNDEF" is undefined +make: "cond-undef-lint.mk" line 38: Variable "VAR." is undefined +make: "cond-undef-lint.mk" line 45: Variable "VAR.defined" is undefined +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.mk (revision 367461) @@ -0,0 +1,69 @@ +# $NetBSD: cond-undef-lint.mk,v 1.2 2020/09/14 07:13:29 rillig Exp $ +# +# Tests for defined and undefined variables in .if conditions, in lint mode. +# +# As of 2020-09-14, lint mode contains experimental code for printing +# accurate error messages in case of undefined variables, instead of the +# wrong "Malformed condition". +# +# See also: +# opt-debug-lint.mk + +.MAKEFLAGS: -dL + +# DEF is defined, UNDEF is not. +DEF= defined + +# An expression based on a defined variable is fine. +.if !${DEF} +. error +.endif + +# Since the condition fails to evaluate, neither of the branches is taken. +.if ${UNDEF} +. error +.else +. error +.endif + +# The variable name depends on the undefined variable, which is probably a +# mistake. The variable UNDEF, as used here, can be easily turned into +# an expression that is always defined, using the :U modifier. +# +# The outer expression does not generate an error message since there was +# already an error evaluating this variable's name. +# +# TODO: Suppress the error message "Variable VAR. is undefined". That part +# of the expression must not be evaluated at all. +.if ${VAR.${UNDEF}} +. error +.else +. error +.endif + +# The variable VAR.defined is not defined and thus generates an error message. +.if ${VAR.${DEF}} +. error +.else +. error +.endif + + +# Variables that are referenced indirectly may be undefined in a condition. +# +# A practical example for this is CFLAGS, which consists of CWARNS, COPTS +# and a few others. Just because these nested variables are not defined, +# this does not make the condition invalid. +# +# The crucial point is that at the point where the variable appears in the +# condition, there is no way to influence the definedness of the nested +# variables. In particular, there is no modifier that would turn undefined +# nested variables into empty strings, as an equivalent to the :U modifier. +INDIRECT= ${NESTED_UNDEF} ${NESTED_DEF} +NESTED_DEF= nested-defined + +# Since NESTED_UNDEF is not controllable at this point, it must not generate +# an error message, and it doesn't do so, since 2020-09-14. +.if !${INDIRECT} +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-undef-lint.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond1.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond1.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond1.exp (revision 367461) @@ -0,0 +1,23 @@ +make: "cond1.mk" line 75: warning: extra else +make: "cond1.mk" line 85: warning: extra else +2 is prime +A='other' B='unknown' C='clever' o='no,no' +Passed: + var + ("var") + (var != var) + var != var + !((var != var) && defined(name)) + var == quoted + +1 is not prime +2 is prime +3 is prime +4 is not prime +5 is prime + +make: warning: String comparison operator must be either == or != +make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No + +OK +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond1.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond1.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond1.mk (revision 367461) @@ -0,0 +1,109 @@ +# $NetBSD: cond1.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +# hard code these! +TEST_UNAME_S= NetBSD +TEST_UNAME_M= sparc +TEST_MACHINE= i386 + +.if ${TEST_UNAME_S} +Ok=var, +.endif +.if ("${TEST_UNAME_S}") +Ok+=(\"var\"), +.endif +.if (${TEST_UNAME_M} != ${TEST_MACHINE}) +Ok+=(var != var), +.endif +.if ${TEST_UNAME_M} != ${TEST_MACHINE} +Ok+= var != var, +.endif +.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X)) +Ok+= !((var != var) && defined(name)), +.endif +# from bsd.obj.mk +MKOBJ?=no +.if ${MKOBJ} == "no" +o= no +Ok+= var == "quoted", +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o=${MAKEOBJDIRPREFIX}${__curdir} +.else +o= ${MAKEOBJDIR} +.endif +.endif +o= o +.endif + +# repeat the above to check we get the same result +.if ${MKOBJ} == "no" +o2= no +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o2=${MAKEOBJDIRPREFIX}${__curdir} +.else +o2= ${MAKEOBJDIR} +.endif +.endif +o2= o +.endif + +PRIMES=2 3 5 7 11 +NUMBERS=1 2 3 4 5 + +n=2 +.if ${PRIMES:M$n} == "" +X=not +.else +X= +.endif + +.if ${MACHINE_ARCH} == no-such +A=one +.else +.if ${MACHINE_ARCH} == not-this +.if ${MACHINE_ARCH} == something-else +A=unlikely +.else +A=no +.endif +.endif +A=other +# We expect an extra else warning - we're not skipping here +.else +A=this should be an error +.endif + +.if $X != "" +.if $X == not +B=one +.else +B=other +# We expect an extra else warning - we are skipping here +.else +B=this should be an error +.endif +.else +B=unknown +.endif + +.if "quoted" == quoted +C=clever +.else +C=dim +.endif + +.if defined(nosuch) && ${nosuch:Mx} != "" +# this should not happen +.info nosuch is x +.endif + +all: + @echo "$n is $X prime" + @echo "A='$A' B='$B' C='$C' o='$o,${o2}'" + @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}" + @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}" + @echo "${"${DoNotQuoteHere:U0}" > 0:?OK:No}" + @echo "${${NoSuchNumber:U42} > 0:?OK:No}" Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond1.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/counter-append.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/counter-append.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/counter-append.exp (revision 367461) @@ -0,0 +1,2 @@ +A=1 B=2 C=3 COUNTER=3 +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/counter-append.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/counter-append.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/counter-append.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/counter-append.mk (revision 367461) @@ -0,0 +1,28 @@ +# $NetBSD: counter-append.mk,v 1.4 2020/10/17 16:57:17 rillig Exp $ +# +# Demonstrates how to let make count the number of times a variable +# is actually accessed, using the ::+= variable modifier. +# +# This works since 2020-09-23. Before that, the counter ended up at having +# 6 words, even though the NEXT variable was only accessed 3 times. +# The cause for this surprising behavior was that the ::= variable modifiers +# returned an error marker instead of a simple empty string. + +RELEVANT= yes (load-time part) # just to filter the output + +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". +A:= ${NEXT} +B:= ${NEXT} +C:= ${NEXT} + +RELEVANT= no + +all: + @: ${RELEVANT::=yes (run-time part)} + @echo A=${A:Q} B=${B:Q} C=${C:Q} COUNTER=${COUNTER:[#]:Q} + @: ${RELEVANT::=no} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/counter-append.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/counter.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/counter.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/counter.exp (revision 367461) @@ -0,0 +1,2 @@ +A=1 B=2 C=3 COUNTER=3 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/counter.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/counter.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/counter.mk (revision 367461) @@ -0,0 +1,28 @@ +# $NetBSD: counter.mk,v 1.5 2020/10/17 16:57:17 rillig Exp $ +# +# Demonstrates how to let make count the number of times a variable +# is actually accessed, using the ::= variable modifier. +# +# This works since 2020-09-23. Before that, the counter ended up at having +# 4 words, even though the NEXT variable was only accessed 3 times. +# The cause for this surprising behavior was that the ::= variable modifiers +# returned an error marker instead of a simple empty string. + +RELEVANT= yes (load-time part) # just to filter the output + +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". +A:= ${NEXT} +B:= ${NEXT} +C:= ${NEXT} + +RELEVANT= no + +all: + @: ${RELEVANT::=yes (run-time part)} + @echo A=${A:Q} B=${B:Q} C=${C:Q} COUNTER=${COUNTER:[#]:Q} + @: ${RELEVANT::=no} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/counter.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "dep-colon-bug-cross-file.mk" line 31: warning: duplicate script for target "all" ignored +make: "dep-colon-bug-cross-file.mk" line 40: warning: using previous script for "all" defined here +: pass 1 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.mk (revision 367461) @@ -0,0 +1,41 @@ +# $NetBSD: dep-colon-bug-cross-file.mk,v 1.4 2020/09/27 09:53:41 rillig Exp $ +# +# Until 2020-09-25, the very last dependency group of a top-level makefile +# was not finished properly. This made it possible to add further commands +# to that target. +# +# In pass 1, there is a dependency group at the bottom of the file. +# This dependency group is not finished properly. Finishing the dependency +# group would add the OP_HAS_COMMANDS flag to the "all" target, thereby +# preventing any commands from being added later. +# +# After the file has been parsed completely, it is parsed again in pass 2. +# In this pass, another command is added to the "current dependency group", +# which was still the one from pass 1, which means it was possible to later +# add commands to an existing target, even across file boundaries. +# +# Oops, even worse. Running this test in a make from 2020-09-25 or earlier +# on NetBSD 8.0 x86_64 with MALLOC_OPTIONS=JA produces this or a similar +# output: +# +# make: cannot open ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ. +# +# The 'Z' means access to already freed memory; see jemalloc(3). The cause +# for this is that in MainParseArgs, the command line arguments were not +# properly copied before storing them in global variables. + +PASS?= 1 + +.if ${PASS} == 2 +all: + : pass 2 +.endif + +.if ${PASS} == 1 + +PASS= 2 +.MAKEFLAGS: -f ${.PARSEDIR:q}/${.PARSEFILE:q} + +all: + : pass 1 +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon-bug-cross-file.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.exp (revision 367461) @@ -0,0 +1,3 @@ +making target1 from source1 +making target2 from source2 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: dep-colon.mk,v 1.3 2020/10/17 20:10:04 rillig Exp $ +# +# Tests for the : operator in dependency declarations. + +# TODO: Implementation + +# In a dependency declaration line, there may be a shell command after the +# sources. It is separated by a semicolon. This "feature" is required by +# POSIX. It is seldom used, if at all. +all: target1 +target1: source1; @echo making ${.TARGET} from ${.ALLSRC} +source1: .PHONY + +# The semicolon for separating the sources from the creation commands must +# appear at the top-level. The semicolons inside the :S;1;2; modifier are +# skipped when looking for the semicolon that separates the sources from +# the commands. +all: target2 +target2: source${:U1:S;1;2;}; @echo making ${.TARGET} from ${.ALLSRC} +source2: .PHONY Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-colon.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.exp (revision 367461) @@ -0,0 +1,3 @@ +: 'Making 1400 dep-double-colon-1300 from dep-double-colon-1400 oodate dep-double-colon-1400' +: 'Making 1500 dep-double-colon-1300 from dep-double-colon-1500 oodate dep-double-colon-1500' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.mk (revision 367461) @@ -0,0 +1,32 @@ +# $NetBSD: dep-double-colon-indep.mk,v 1.1 2020/10/23 19:11:30 rillig Exp $ +# +# Tests for the :: operator in dependency declarations, which allows multiple +# dependency groups with the same target. Each group is evaluated on its own, +# independent of the other groups. +# +# This is useful for targets that are updatable, such as a database or a log +# file. Be careful with parallel mode though, to avoid lost updates and +# other inconsistencies. +# +# The target 1300 depends on 1200, 1400 and 1500. The target 1200 is older +# than 1300, therefore nothing is done for it. The other targets are newer +# than 1300, therefore each of them is made, independently from the other. + +.END: + @rm -f dep-double-colon-1??? + +_!= touch -t 202001011200 dep-double-colon-1200 +_!= touch -t 202001011300 dep-double-colon-1300 +_!= touch -t 202001011400 dep-double-colon-1400 +_!= touch -t 202001011500 dep-double-colon-1500 + +all: dep-double-colon-1300 + +dep-double-colon-1300:: dep-double-colon-1200 + : 'Making 1200 ${.TARGET} from ${.ALLSRC} oodate ${.OODATE}' + +dep-double-colon-1300:: dep-double-colon-1400 + : 'Making 1400 ${.TARGET} from ${.ALLSRC} oodate ${.OODATE}' + +dep-double-colon-1300:: dep-double-colon-1500 + : 'Making 1500 ${.TARGET} from ${.ALLSRC} oodate ${.OODATE}' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon-indep.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: dep-double-colon.mk,v 1.4 2020/09/26 15:41:53 rillig Exp $ +# +# Tests for the :: operator in dependency declarations. + +all:: + @echo 'command 1a' + @echo 'command 1b' + +all:: + @echo 'command 2a' + @echo 'command 2b' + +# When there are multiple command groups for a '::' target, each of these +# groups is added separately to the .ALLTARGETS variable. +# +# XXX: What is this good for? +# XXX: Where does the leading space come from? +.if ${.ALLTARGETS} != " all all" +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.exp (revision 367461) @@ -0,0 +1,3 @@ +make: don't know how to make dep-percent.o (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.mk (revision 367461) @@ -0,0 +1,14 @@ +# $NetBSD: dep-percent.mk,v 1.1 2020/10/23 19:54:35 rillig Exp $ +# +# Test for transformation rules of the form '%.o: %.c', which are supported +# by GNU make but not this make. + +.SUFFIXES: .c .o + +all: dep-percent.o + +%.o: %.c + : 'Making ${.TARGET} from ${.IMPSRC} or ${.ALLSRC}.' + +dep-percent.c: + : 'Making ${.TARGET} out of nothing.' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-percent.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-var.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-var.exp (revision 367461) @@ -0,0 +1,6 @@ +make: Malformed variable expression at "$)" +def2 +a-def2-b +1-2-NDIRECT_2-2-1 +) +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-var.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-var.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-var.mk (revision 367461) @@ -0,0 +1,88 @@ +# $NetBSD: dep-var.mk,v 1.5 2020/09/13 20:04:26 rillig Exp $ +# +# Tests for variable references in dependency declarations. +# +# Uh oh, this feels so strange that probably nobody uses it. But it seems to +# be the only way to reach the lower half of SuffExpandChildren. + +# XXX: The -dv log says: +# Var_Parse: ${UNDEF1} with VARE_UNDEFERR|VARE_WANTRES +# but no error message is generated for this line. +# The variable expression ${UNDEF1} simply expands to an empty string. +all: ${UNDEF1} + +# Using a double dollar in order to circumvent immediate variable expansion +# feels like unintended behavior. At least the manual page says nothing at +# all about defined or undefined variables in dependency lines. +# +# At the point where the expression ${DEF2} is expanded, the variable DEF2 +# is defined, so everything's fine. +all: $${DEF2} a-$${DEF2}-b + +# This variable is not defined at all. +# XXX: The -dv log says: +# Var_Parse: ${UNDEF3} with VARE_UNDEFERR|VARE_WANTRES +# but no error message is generated for this line, just like for UNDEF1. +# The variable expression ${UNDEF3} simply expands to an empty string. +all: $${UNDEF3} + +# Try out how many levels of indirection are really expanded in dependency +# lines. +# +# The first level of indirection is the $$ in the dependency line. +# When the dependency line is parsed, it is resolved to the string +# "${INDIRECT_1}". At this point, the dollar is just an ordinary character, +# waiting to be expanded at some later point. +# +# Later, in SuffExpandChildren, that expression is expanded again by calling +# Var_Parse, and this time, the result is the string "1-2-${INDIRECT_2}-2-1". +# +# This string is not expanded anymore by Var_Parse. But there is another +# effect. Now DirExpandCurly comes into play and expands the curly braces +# in this filename pattern, resulting in the string "1-2-$INDIRECT_2-2-1". +# As of 2020-09-03, the test dir.mk contains further details on this topic. +# +# Finally, this string is assigned to the local ${.TARGET} variable. This +# variable is expanded when the shell command is generated. At that point, +# the $I is expanded. Since the variable I is not defined, it expands to +# the empty string. This way, the final output is the string +# "1-2-NDIRECT_2-2-1", which differs from the actual name of the target. +# For exactly this reason, it is not recommended to use dollar signs in +# target names. +# +# The number of actual expansions is way more than one might expect, +# therefore this feature is probably not widely used. +# +all: 1-$${INDIRECT_1}-1 +INDIRECT_1= 2-$${INDIRECT_2}-2 +INDIRECT_2= 3-$${INDIRECT_3}-3 +INDIRECT_3= indirect + +UNDEF1= undef1 +DEF2= def2 + +# Cover the code in SuffExpandChildren that deals with malformed variable +# expressions. +# +# This seems to be an edge case that never happens in practice, and it would +# probably be appropriate to just error out in such a case. +# +# To trigger this piece of code, the variable name must contain "$)" or "$:" +# or "$)" or "$$". Using "$:" does not work since the dependency line is +# fully expanded before parsing, therefore any ':' in a target or source name +# would be interpreted as a dependency operator instead. +all: $$$$) + +# The $$INDIRECT in the following line is treated like the dependency of the +# "all" target, that is, the "$$I" is first expanded to "$I", and in a second +# round of expansion, the "$I" expands to nothing since the variable "I" is +# 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 +# calling Var_Parse. +undef1 def2 a-def2-b 1-2-$$INDIRECT_2-2-1 ${:U\$)}: + @echo ${.TARGET:Q} + +# XXX: Why is the exit status still 0, even though Parse_Error is called +# with PARSE_FATAL in SuffExpandChildren? Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-var.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.exp (revision 367461) @@ -0,0 +1,10 @@ +dep-colon-bug-cross-file.mk +dep-colon.mk +dep-double-colon-indep.mk +dep-double-colon.mk +dep-exclam.mk +dep-none.mk +dep-percent.mk +dep-var.mk +dep-wildcards.mk +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: dep-wildcards.mk,v 1.3 2020/09/08 05:33:05 rillig Exp $ +# +# Tests for wildcards such as *.c in dependency declarations. + +all: ${.PARSEDIR}/dep-*.mk + # The :T is necessary to run this test from another directory. + # The :O is necessary since the result of the dependency resolution + # does not order the directory entries itself. + @printf '%s\n' ${.ALLSRC:T:O} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-wildcards.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.exp (revision 367461) @@ -0,0 +1,4 @@ +: 'Making .END.' +: 'Making .BEGIN.' +: 'Making all.' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.mk (revision 367461) @@ -0,0 +1,14 @@ +# $NetBSD: depsrc-end.mk,v 1.1 2020/10/23 19:23:01 rillig Exp $ +# +# Demonstrate the edge case that .BEGIN depends on .END, which sounds a bit +# paradox but works since these special nodes are not in the dependency +# hierarchy where the cycles are detected. + +.BEGIN: + : 'Making ${.TARGET}.' +.END: + : 'Making ${.TARGET}.' +all: + : 'Making ${.TARGET}.' + +.BEGIN: .END Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-end.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.exp (revision 367461) @@ -0,0 +1,2 @@ +: depsrc-exec.mk: This is always executed. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.mk (revision 367461) @@ -0,0 +1,16 @@ +# $NetBSD: depsrc-exec.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .EXEC in dependency declarations, +# which always executes the commands, even if the target is up to date. +# The target itself is considered up to date. +# +# TODO: Describe possible use cases for .EXEC. + +all: ${MAKEFILE} ${MAKEFILE:H}/depsrc.mk + +${MAKEFILE}: .EXEC + : ${.TARGET:T}: This is always executed. + +${MAKEFILE:H}/depsrc.mk: + : This is not executed. + +: ${.TARGET:T}: This is not executed as well. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-exec.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.exp (revision 367461) @@ -0,0 +1,3 @@ +: Making chapter21 +: Making chapter22 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.mk (revision 367461) @@ -0,0 +1,15 @@ +# $NetBSD: depsrc-made.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .MADE in dependency declarations, +# which marks all its dependencies as already made, so their commands +# don't need to be executed. +# +# TODO: Describe a possible use case for .MADE. + +all: part1 part2 + +part1: chapter11 chapter12 .MADE +part2: chapter21 chapter22 + +chapter11 chapter12 chapter21 chapter22: + : Making ${.TARGET} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-made.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.exp (revision 367461) @@ -0,0 +1,3 @@ +this-is-made is made. +echo this-is-not-made is just echoed. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.mk (revision 367461) @@ -0,0 +1,16 @@ +# $NetBSD: depsrc-make.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .MAKE in dependency declarations, which +# executes the commands of the target even if the -n or -t command line +# options are given. + +.MAKEFLAGS: -n + +all: this-is-made +all: this-is-not-made + +this-is-made: .MAKE + @echo ${.TARGET} is made. + +this-is-not-made: + @echo ${.TARGET} is just echoed. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-make.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.exp (revision 367461) @@ -0,0 +1,2 @@ +: all +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: depsrc-notmain.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .NOTMAIN in dependency declarations, +# which prevents the associated target from becoming the default target +# to be made. + +ignored: .NOTMAIN + : ${.TARGET} + +all: + : ${.TARGET} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-notmain.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.exp (revision 367461) @@ -0,0 +1,2 @@ +`all' is up to date. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.mk (revision 367461) @@ -0,0 +1,18 @@ +# $NetBSD: depsrc-optional.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .OPTIONAL in dependency declarations, +# which ignores the target if make cannot find out how to create it. +# +# TODO: Describe practical use cases for this feature. + +# TODO: Explain why the commands for "important" are not executed. +# I had thought that only the "optional" commands were skipped. + +all: important + : ${.TARGET} is made. + +important: optional + : ${.TARGET} is made. + +optional: .OPTIONAL + : This is not executed. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-optional.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.exp (revision 367461) @@ -0,0 +1,2 @@ +: depsrc-phony.mk is made. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: depsrc-phony.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .PHONY in dependency declarations, +# which executes the commands for the target even if a file of the same +# name exists and would be considered up to date. + +# Without the .PHONY, this target would be "up to date". +${MAKEFILE}: .PHONY + : ${.TARGET:T} is made. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-phony.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.exp (revision 367461) @@ -0,0 +1,3 @@ +this-is-made is made. +echo this-is-not-made is just echoed. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.mk (revision 367461) @@ -0,0 +1,16 @@ +# $NetBSD: depsrc-recursive.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# +# Tests for the special source .RECURSIVE in dependency declarations, +# which executes the commands of the target even if the -n or -t command +# line options are given. + +.MAKEFLAGS: -n + +all: this-is-made +all: this-is-not-made + +this-is-made: .RECURSIVE + @echo ${.TARGET} is made. + +this-is-not-made: + @echo ${.TARGET} is just echoed. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-recursive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.exp (revision 367461) @@ -0,0 +1,13 @@ +--- a --- +echo a +a +--- b1 --- +echo b1 +b1 +--- b --- +echo b +b +--- x --- +echo x +x +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.mk (revision 367461) @@ -0,0 +1,21 @@ +# $NetBSD: depsrc-wait.mk,v 1.3 2020/09/07 18:40:32 rillig Exp $ +# +# Tests for the special source .WAIT in dependency declarations, +# which adds a sequence point between the nodes to its left and the nodes +# to its right. + +# Even though the build could run massively parallel, the .WAIT imposes a +# strict ordering in this example, which forces the targets to be made in +# exactly this order. +.MAKEFLAGS: -j8 + +# This is the example from the manual page. +.PHONY: x a b b1 +x: a .WAIT b + echo x +a: + echo a +b: b1 + echo b +b1: + echo b1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-wait.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.exp (revision 367461) @@ -0,0 +1,51 @@ +Compatibility mode +> deptgt-delete_on_error-regular; false +*** Error code 1 (continuing) +make: *** deptgt-delete_on_error-regular removed +> deptgt-delete_on_error-regular-delete; false +*** Error code 1 (continuing) +make: *** deptgt-delete_on_error-regular-delete removed +> deptgt-delete_on_error-phony; false +*** Error code 1 (continuing) +make: *** deptgt-delete_on_error-phony removed +> deptgt-delete_on_error-phony-delete; false +*** Error code 1 (continuing) +make: *** deptgt-delete_on_error-phony-delete removed +> deptgt-delete_on_error-precious; false +*** Error code 1 (continuing) +> deptgt-delete_on_error-precious-delete; false +*** Error code 1 (continuing) + +Stop. +make: stopped in unit-tests + +Parallel mode +> deptgt-delete_on_error-regular; false +*** [deptgt-delete_on_error-regular] Error code 1 +make: *** deptgt-delete_on_error-regular removed + +make: stopped in unit-tests +> deptgt-delete_on_error-regular-delete; false +*** [deptgt-delete_on_error-regular-delete] Error code 1 +make: *** deptgt-delete_on_error-regular-delete removed + +make: stopped in unit-tests +> deptgt-delete_on_error-phony; false +*** [deptgt-delete_on_error-phony] Error code 1 + +make: stopped in unit-tests +> deptgt-delete_on_error-phony-delete; false +*** [deptgt-delete_on_error-phony-delete] Error code 1 + +make: stopped in unit-tests +> deptgt-delete_on_error-precious; false +*** [deptgt-delete_on_error-precious] Error code 1 + +make: stopped in unit-tests +> deptgt-delete_on_error-precious-delete; false +*** [deptgt-delete_on_error-precious-delete] Error code 1 + +make: stopped in unit-tests +*** Error code 1 (ignored) +*** Error code 1 (ignored) +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.mk (revision 367461) @@ -0,0 +1,45 @@ + # $NetBSD: deptgt-delete_on_error.mk,v 1.3 2020/10/25 21:31:00 rillig Exp $ +# +# Tests for the special target .DELETE_ON_ERROR in dependency declarations, +# which controls whether the target is deleted if a shell command fails or +# is interrupted. +# +# In compatibility mode, regular and phony targets are deleted, but precious +# targets are preserved. +# +# In parallel mode, regular targets are deleted, while phony and precious +# targets are preserved. +# +# See also: +# CompatDeleteTarget +# JobDeleteTarget + +THIS= deptgt-delete_on_error +TARGETS= ${THIS}-regular ${THIS}-regular-delete +TARGETS+= ${THIS}-phony ${THIS}-phony-delete +TARGETS+= ${THIS}-precious ${THIS}-precious-delete + +all: + @rm -f ${TARGETS} + @echo 'Compatibility mode' + @-${.MAKE} -f ${MAKEFILE} -k ${TARGETS} + @rm -f ${TARGETS} + @echo + @echo 'Parallel mode' + @-${.MAKE} -f ${MAKEFILE} -k -j1 ${TARGETS} + @rm -f ${TARGETS} + +${THIS}-regular{,-delete}: + > ${.TARGET}; false + +${THIS}-phony{,-delete}: .PHONY + > ${.TARGET}; false + +${THIS}-precious{,-delete}: .PRECIOUS + > ${.TARGET}; false + +# The special target .DELETE_ON_ERROR is a global setting. +# It does not apply to single targets. +# The following line is therefore misleading but does not generate any +# warning or even an error message. +.DELETE_ON_ERROR: ${TARGETS:M*-delete} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-delete_on_error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.exp (revision 367461) @@ -0,0 +1,8 @@ +: .BEGIN '${VAR}' +--- all --- +: all '${VAR}' +: .END '${VAR}' +: .END '${VAR}' deferred +: .BEGIN 'Should not be expanded.' deferred +: all 'Should not be expanded.' deferred +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.mk (revision 367461) @@ -0,0 +1,46 @@ +# $NetBSD: deptgt-end-jobs.mk,v 1.1 2020/09/23 03:06:38 rillig Exp $ +# +# Tests for the special target .END in dependency declarations, +# which is run after making the desired targets. +# +# This test is very similar to deptgt-end.mk, except for the -j option. +# This option enables parallel mode, in which the code from job.c partially +# replaces the code from compat.c. +# +# Before 2020-08-22, this test crashed with a null pointer dereference. +# Before 2020-09-23, this test crashed with an assertion failure. +.MAKEFLAGS: -j 8 + +VAR= Should not be expanded. + +.BEGIN: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred +# Oops: The deferred command must not be expanded twice. +# The Var_Subst in Compat_RunCommand looks suspicious. +# The Var_Subst in JobSaveCommand looks suspicious. + +.END: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred + +all: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred +# Oops: The deferred command must not be expanded twice. +# The Var_Subst in Compat_RunCommand looks suspicious. +# The Var_Subst in JobSaveCommand looks suspicious. + +# The deferred commands are run in the order '.END .BEGIN all'. +# This may be unexpected at first since the natural order would be +# '.BEGIN all .END', but it is implemented correctly. +# +# At the point where the commands of a node with deferred commands are run, +# the deferred commands are appended to the commands of the .END node. +# This happens in Compat_RunCommand, and to prevent an endless loop, the +# deferred commands of the .END node itself are not appended to itself. +# Instead, the deferred commands of the .END node are run as if they were +# immediate commands. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.exp (revision 367461) @@ -0,0 +1,9 @@ +: .BEGIN '${VAR}' +: all '${VAR}' +: end-action '${VAR}' +: .END '${VAR}' +: .END '${VAR}' deferred +: .BEGIN 'Should not be expanded.' deferred +: all 'Should not be expanded.' deferred +: end-action 'Should not be expanded.' deferred +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.mk (revision 367461) @@ -0,0 +1,45 @@ +# $NetBSD: deptgt-end.mk,v 1.6 2020/10/23 19:28:17 rillig Exp $ +# +# Tests for the special target .END in dependency declarations, +# which is run after making the desired targets. + +VAR= Should not be expanded. + +.BEGIN: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred +# Oops: The deferred command must not be expanded twice. +# The Var_Subst in Compat_RunCommand looks suspicious. +# The Var_Subst in JobSaveCommand looks suspicious. + +.END: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred + +# The .END node can define dependencies, just like a regular target. +.END: end-action +end-action: .NOTMAIN + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred + +all: + : $@ '$${VAR}' + ... + : $@ '$${VAR}' deferred +# Oops: The deferred command must not be expanded twice. +# The Var_Subst in Compat_RunCommand looks suspicious. +# The Var_Subst in JobSaveCommand looks suspicious. + +# The deferred commands are run in the order '.END .BEGIN all'. +# This may be unexpected at first since the natural order would be +# '.BEGIN all .END', but it is implemented correctly. +# +# At the point where the commands of a node with deferred commands are run, +# the deferred commands are appended to the commands of the .END node. +# This happens in Compat_RunCommand, and to prevent an endless loop, the +# deferred commands of the .END node itself are not appended to itself. +# Instead, the deferred commands of the .END node are run as if they were +# immediate commands. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-end.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.exp (revision 367461) @@ -0,0 +1,9 @@ +Global:delete DOLLAR (not found) +Command:DOLLAR = $$$$ +Global:.MAKEOVERRIDES = VAR DOLLAR +CondParser_Eval: ${DOLLAR} != "\$\$" +Var_Parse: ${DOLLAR} != "\$\$" with VARE_UNDEFERR|VARE_WANTRES +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 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.mk (revision 367461) @@ -0,0 +1,51 @@ +# $NetBSD: deptgt-makeflags.mk,v 1.4 2020/10/23 14:48:49 rillig Exp $ +# +# Tests for the special target .MAKEFLAGS in dependency declarations, +# which adds command line options later, at parse time. + +# The -D option sets a variable in the "Global" scope and thus can be +# undefined later. +.MAKEFLAGS: -D VAR + +.if ${VAR} != 1 +. error +.endif + +.undef VAR + +.if defined(VAR) +. error +.endif + +.MAKEFLAGS: -D VAR + +.if ${VAR} != 1 +. error +.endif + +.MAKEFLAGS: VAR="value"' with'\ spaces + +.if ${VAR} != "value with spaces" +. error +.endif + +# Variables set on the command line as VAR=value are placed in the +# "Command" scope and thus cannot be undefined. +.undef VAR + +.if ${VAR} != "value with spaces" +. error +.endif + +# When parsing this line, each '$$' becomes '$', resulting in '$$$$'. +# This is assigned to the variable DOLLAR. +# In the condition, that variable is expanded, and at that point, each '$$' +# becomes '$' again, the final expression is thus '$$'. +.MAKEFLAGS: -dcv +.MAKEFLAGS: DOLLAR=$$$$$$$$ +.if ${DOLLAR} != "\$\$" +.endif +.MAKEFLAGS: -d0 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-makeflags.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.exp (revision 367461) @@ -0,0 +1,3 @@ +This is not echoed because of the @. +This is not echoed because of the .SILENT. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: deptgt-silent.mk,v 1.3 2020/09/10 21:40:50 rillig Exp $ +# +# Tests for the special target .SILENT in dependency declarations. + +.SILENT: all + +all: + @echo 'This is not echoed because of the @.' + # Without the .SILENT, the following command would be echoed. + echo 'This is not echoed because of the .SILENT.' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-silent.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.exp (revision 367461) @@ -0,0 +1,7 @@ +#*** Suffixes: +# ".custom-null" (num 1, ref 1) (SUFF_NULL) +# To: +# From: +# Search Path: . .. +#*** Transformations: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "deptgt.mk" line 10: warning: Extra target ignored +make: "deptgt.mk" line 28: Unassociated shell command ": command3 # parse error, since targets == NULL" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt.mk (revision 367461) @@ -0,0 +1,31 @@ +# $NetBSD: deptgt.mk,v 1.8 2020/10/18 13:02:10 rillig Exp $ +# +# Tests for special targets like .BEGIN or .SUFFIXES in dependency +# declarations. + +# TODO: Implementation + +# Just in case anyone tries to compile several special targets in a single +# dependency line: That doesn't work, and make immediately rejects it. +.SUFFIXES .PHONY: .c.o + +# 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 +# FinishDependencyGroup at "targets = NULL" +# Parse_File at "Lst_Free(targets)" +# Parse_File at "targets = Lst_New()" +# ParseLine_ShellCommand at "targets == NULL" +# +# Keywords: +# parse.c:targets + +target1 target2: sources # targets := [target1, target2] + : command1 # targets == [target1, target2] + : command2 # targets == [target1, target2] +VAR=value # targets := NULL + : command3 # parse error, since targets == NULL + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dir.exp (revision 367461) @@ -0,0 +1,50 @@ +Searching for .depend ... + failed. +Searching for .depend ... + / ... + failed. +Expanding "{one,two,three}"... one two three +Expanding "f{our,ive}"... four five +Expanding "{{thi,fou}r,fif}teen"... Expanding "{thi,fou}rteen"... thirteen fourteen +thirteen fourteen fifteen +Expanding "{pre-,}{patch,configure}"... Expanding "pre-{patch,configure}"... pre-patch pre-configure +Expanding "{patch,configure}"... pre-patch pre-configure patch configure +pre-patch pre-configure patch configure +Expanding "{fetch,extract}{,-post}"... Expanding "fetch{,-post}"... fetch fetch-post +Expanding "extract{,-post}"... fetch fetch-post extract extract-post +fetch fetch-post extract extract-post +Expanding "dup-{1,1,1,1,1,1,1}"... dup-1 dup-1 dup-1 dup-1 dup-1 dup-1 dup-1 +Expanding "{{{{{{{{{{single-word}}}}}}}}}}"... Expanding "{{{{{{{{{single-word}}}}}}}}}"... Expanding "{{{{{{{{single-word}}}}}}}}"... Expanding "{{{{{{{single-word}}}}}}}"... Expanding "{{{{{{single-word}}}}}}"... Expanding "{{{{{single-word}}}}}"... Expanding "{{{{single-word}}}}"... Expanding "{{{single-word}}}"... Expanding "{{single-word}}"... Expanding "{single-word}"... single-word +single-word +single-word +single-word +single-word +single-word +single-word +single-word +single-word +single-word +: 1 +: 2 +: 3 +: 4 +: 5 +: 13 +: 14 +: 15 +: pre-patch +: pre-configure +: patch +: configure +: fetch +: fetch-post +: extract +: extract-post +: dup-1 +: single-word +Searching for .END ... + failed. +Searching for .END ... + failed. +Found '.END' as '(not found)' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dir.mk (revision 367461) @@ -0,0 +1,93 @@ +# $NetBSD: dir.mk,v 1.7 2020/10/31 21:30:03 rillig Exp $ +# +# Tests for dir.c. + +.MAKEFLAGS: -m / # hide /usr/share/mk from the debug log + +# Dependency lines may use braces for expansion. +# See DirExpandCurly for the implementation. +all: {one,two,three} + +# XXX: The above dependency line is parsed as a single node named +# "{one,two,three}". There are no individual targets "one", "two", "three" +# yet. The node exists but is not a target since it never appeared +# on the left-hand side of a dependency operator. However, it is listed +# in .ALLTARGETS (which lists all nodes, not only targets). +.if target(one) +. error +.endif +.if target({one,two,three}) +. error +.endif +.if ${.ALLTARGETS:M{one,two,three}} != "{one,two,three}" +. error +.endif + +one: + : 1 +two: + : 2 +three: + : 3 + +# The braces may start in the middle of a word. +all: f{our,ive} + +four: + : 4 +five: + : 5 +six: + : 6 + +# Nested braces work as expected since 2020-07-31 19:06 UTC. +# They had been broken at least since 2003-01-01, probably even longer. +all: {{thi,fou}r,fif}teen + +thirteen: + : 13 +fourteen: + : 14 +fifteen: + : 15 + +# There may be multiple brace groups side by side. +all: {pre-,}{patch,configure} + +pre-patch patch pre-configure configure: + : $@ + +# Empty pieces are allowed in the braces. +all: {fetch,extract}{,-post} + +fetch fetch-post extract extract-post: + : $@ + +# The expansions may have duplicates. +# These are merged together because of the dependency line. +all: dup-{1,1,1,1,1,1,1} + +dup-1: + : $@ + +# Other than in Bash, the braces are also expanded if there is no comma. +all: {{{{{{{{{{single-word}}}}}}}}}} + +single-word: + : $@ + +# Demonstrate debug logging for filename expansion, especially curly braces. +.MAKEFLAGS: -dd +# The below line does not call Dir_Expand yet. +# It is expanded only when necessary, that is, when the 'debug' target is +# indeed made. +debug: {{thi,fou}r,fif}twen +# Therefore, keep the debug logging active. + +.PHONY: one two three four five six +.PHONY: thirteen fourteen fifteen +.PHONY: single-word +.PHONY: pre-patch patch pre-configure configure +.PHONY: fetch fetch-post extract extract-post +.PHONY: dup-1 single-word +.PHONY: all Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: directive-dinclude.mk,v 1.1 2020/09/13 09:20:23 rillig Exp $ +# +# Tests for the .dinclude directive, which includes another file, +# typically named .depend. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-dinclude.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-else.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-else.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-else.mk (revision 367461) @@ -0,0 +1,32 @@ +# $NetBSD: directive-else.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the .else directive. + +# The .else directive does not take any arguments. +# As of 2020-08-29, make doesn't warn about this. +.if 0 +. warning must not be reached +.else 123 +. info ok +.endif + +.if 1 +. info ok +.else 123 +. warning must not be reached +.endif + +# An .else without a corresponding .if is an error. +.else + +# Accidental extra .else directives are detected too. +.if 0 +. warning must not be reached +.else +. info ok +.else +. info After an extra .else, everything is skipped. +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-else.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.mk (revision 367461) @@ -0,0 +1,64 @@ +# $NetBSD: directive-export-gmake.mk,v 1.2 2020/10/19 18:59:53 rillig Exp $ +# +# Tests for the export directive (without leading dot), as in GNU make. + +# The "export" directive only affects the environment of the make process +# and its child processes. It does not affect the global variables or any +# other variables. +VAR= before +export VAR=exported +.if ${VAR} != "before" +. error +.endif + +# Ensure that the name-value pair is actually exported. +.if ${:!echo "\$VAR"!} != "exported" +. error +.endif + +# This line looks like it would export 2 variables, but it doesn't. +# It only exports VAR and appends everything else as the variable value. +export VAR=exported VAR2=exported-as-well +.if ${:!echo "\$VAR"!} != "exported VAR2=exported-as-well" +. error ${:!echo "\$VAR"!} +.endif + +# Contrary to the usual variable assignments, spaces are significant +# after the '=' sign and are prepended to the value of the environment +# variable. +export VAR= leading spaces +.if ${:!echo "\$VAR"!} != " leading spaces" +. error +.endif + +# Contrary to the usual variable assignments, spaces are significant +# before the '=' sign and are appended to the name of the environment +# variable. +# +# Depending on the shell, environment variables with such exotic names +# may be silently discarded. One such shell is dash, which is the default +# shell on Ubuntu and Debian. +export VAR =trailing space in varname +.if ${:!env | grep trailing!} != "VAR =trailing space in varname" +. if ${:!env | grep trailing!} != "" # for dash +. error +. endif +.endif + +# The right-hand side of the exported variable is expanded exactly once. +TWICE= expanded twice +ONCE= expanded once, leaving $${TWICE} as-is +export VAR=${ONCE} +.if ${:!echo "\$VAR"!} != "expanded once, leaving \${TWICE} as-is" +. error +.endif + +# Undefined variables are allowed on the right-hand side, they expand +# to an empty string, as usual. +export VAR=an ${UNDEF} variable +.if ${:!echo "\$VAR"!} != "an variable" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-gmake.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.exp (revision 367461) @@ -0,0 +1,2 @@ +value with ${UNEXPANDED} expression +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: directive-export-literal.mk,v 1.5 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the .export-literal directive, which exports a variable value +# without expanding it. + +UT_VAR= value with ${UNEXPANDED} expression + +.export-literal UT_VAR + +all: + @echo "$$UT_VAR" Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-literal.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: directive-export.mk,v 1.3 2020/10/29 17:27:12 rillig Exp $ +# +# Tests for the .export directive. + +# TODO: Implementation + +INDIRECT= indirect +VAR= value $$ ${INDIRECT} + +# A variable is exported using the .export directive. +# During that, its value is expanded, just like almost everywhere else. +.export VAR +.if ${:!env | grep '^VAR'!} != "VAR=value \$ indirect" +. error +.endif + +# Undefining a variable that has been exported implicitly removes it from +# the environment of all child processes. +.undef VAR +.if ${:!env | grep '^VAR' || true!} != "" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-export.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-for.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-for.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-for.exp (revision 367461) @@ -0,0 +1,19 @@ +make: "directive-for.mk" line 100: outer +make: "directive-for.mk" line 125: a:\ a:\file.txt +make: "directive-for.mk" line 125: d:\\ +make: "directive-for.mk" line 125: d:\\file.txt +make: "directive-for.mk" line 132: ( ( ( +make: "directive-for.mk" line 132: [ [ [ +make: "directive-for.mk" line 132: { { { +make: "directive-for.mk" line 132: ) ) ) +make: "directive-for.mk" line 132: ] ] ] +make: "directive-for.mk" line 132: } } } +make: "directive-for.mk" line 132: (()) (()) (()) +make: "directive-for.mk" line 132: [[]] [[]] [[]] +make: "directive-for.mk" line 132: {{}} {{}} {{}} +make: "directive-for.mk" line 132: )( )( )( +make: "directive-for.mk" line 132: ][ ][ ][ +make: "directive-for.mk" line 132: }{ }{ }{ +make: "directive-for.mk" line 140: outer value value +make: "directive-for.mk" line 140: outer "quoted" \"quoted\" +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-for.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-for.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-for.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-for.mk (revision 367461) @@ -0,0 +1,144 @@ +# $NetBSD: directive-for.mk,v 1.8 2020/10/25 15:49:03 rillig Exp $ +# +# Tests for the .for directive. + +# Using the .for loop, lists of values can be produced. +# In simple cases, the :@var@${var}@ variable modifier can be used to +# reach the same effects. +# +.undef NUMBERS +.for num in 1 2 3 +NUMBERS+= ${num} +.endfor +.if ${NUMBERS} != "1 2 3" +. error +.endif + +# The .for loop also works for multiple iteration variables. +.for name value in VARNAME value NAME2 value2 +${name}= ${value} +.endfor +.if ${VARNAME} != "value" || ${NAME2} != "value2" +. error +.endif + +# The .for loop splits the items at whitespace, taking quotes into account, +# just like the :M or :S variable modifiers. +# +# Until 2012-06-03, it had split the items exactly at whitespace, without +# taking the quotes into account. +# +.undef WORDS +.for var in one t\ w\ o "three three" 'four four' `five six` +WORDS+= counted +.endfor +.if ${WORDS:[#]} != 6 +. error +.endif + +# In the body of the .for loop, the iteration variables can be accessed +# like normal variables, even though they are not really variables. +# +# Instead, the expression ${var} is transformed into ${:U1}, ${:U2} and so +# on, before the loop body is evaluated. +# +# A notable effect of this implementation technique is that the .for +# iteration variables and the normal global variables live in separate +# namespaces and do not influence each other. +# +var= value before +var2= value before +.for var var2 in 1 2 3 4 +.endfor +.if ${var} != "value before" +. warning After the .for loop, var must still have its original value. +.endif +.if ${var2} != "value before" +. warning After the .for loop, var2 must still have its original value. +.endif + +# Everything from the paragraph above also applies if the loop body is +# empty, even if there is no actual iteration since the loop items are +# also empty. +# +var= value before +var2= value before +.for var var2 in ${:U} +.endfor +.if ${var} != "value before" +. warning After the .for loop, var must still have its original value. +.endif +.if ${var2} != "value before" +. warning After the .for loop, var2 must still have its original value. +.endif + +# Until 2008-12-21, the values of the iteration variables were simply +# inserted as plain text and then parsed as usual, which made it possible +# to achieve all kinds of strange effects. +# +# Before that date, the .for loop expanded to: +# EXPANSION+= value +# Since that date, the .for loop expands to: +# EXPANSION${:U+}= value +# +EXPANSION= before +EXPANSION+ = before +.for plus in + +EXPANSION${plus}= value +.endfor +.if ${EXPANSION} != "before" +. error This must be a make from before 2009. +.endif +.if ${EXPANSION+} != "value" +. error This must be a make from before 2009. +.endif + +# When the outer .for loop is expanded, it sees the expression ${i} and +# expands it. The inner loop then has nothing more to expand. +.for i in outer +. for i in inner +. info ${i} +. endfor +.endfor + +# From https://gnats.netbsd.org/29985. +# +# Until 2008-12-21, the .for loop was expanded by replacing the variable +# value literally in the body. This could lead to situations where the +# characters from the variable value were interpreted as markup rather than +# plain text. +# +# Until 2012-06-03, the .for loop had split the words at whitespace, without +# taking quotes into account. This made it possible to have variable values +# like "a:\ a:\file.txt" that ended in a single backslash. Since then, the +# variable values have been replaced with expressions of the form ${:U...}, +# which are not interpreted as code anymore. +# +# As of 2020-09-22, a comment in for.c says that it may be possible to +# produce an "unwanted substitution", but there is no demonstration code yet. +# +# The above changes prevent a backslash at the end of a word from being +# interpreted as part of the code. Because of this, the trailingBackslash +# hack in Var_Subst is no longer needed and as of 2020-09-22, has been +# removed. +.for path in a:\ a:\file.txt d:\\ d:\\file.txt +. info ${path} +.endfor + +# Ensure that braces and parentheses are properly escaped by the .for loop. +# Each line must print the same word 3 times. +# See GetEscapes. +.for v in ( [ { ) ] } (()) [[]] {{}} )( ][ }{ +. info $v ${v} $(v) +.endfor + +# As of 2020-10-25, the variable names may contain arbitrary characters, +# except for whitespace. This allows for creative side effects. Hopefully +# nobody is misusing this "feature". +var= outer +.for var:Q in value "quoted" +. info ${var} ${var:Q} ${var:Q:Q} +.endfor + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-for.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: directive-hyphen-include.mk,v 1.1 2020/09/13 09:20:23 rillig Exp $ +# +# Tests for the .-include directive, which includes another file, +# silently skipping it if it cannot be opened. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-hyphen-include.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.exp (revision 367461) @@ -0,0 +1,2 @@ +make: "directive-ifndef.mk" line 10: guarded section +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: directive-ifndef.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the .ifndef directive, which can be used for multiple-inclusion +# guards. In contrast to C, where #ifndef and #define nicely line up the +# macro name, there is no such syntax in make. Therefore, it is more +# common to use .if !defined(GUARD) instead. + +.ifndef GUARD +GUARD= # defined +. info guarded section +.endif + +.ifndef GUARD +GUARD= # defined +. info guarded section +.endif + +.if !defined(GUARD) +GUARD= # defined +. info guarded section +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifndef.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.exp (revision 367461) @@ -0,0 +1,3 @@ +Don't forget to run the tests (1) +Running the tests +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.mk (revision 367461) @@ -0,0 +1,22 @@ +# $NetBSD: directive-ifnmake.mk,v 1.5 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the .ifnmake directive, which evaluates to true if its argument +# is _not_ listed in the command-line targets to be created. + +all: + @:; + +.ifnmake(test) +.BEGIN: + @echo "Don't forget to run the tests (1)" +.endif + +.MAKEFLAGS: test + +.ifnmake(test) +.BEGIN: + @echo "Don't forget to run the tests (2)" +.endif + +test: + @echo "Running the tests" Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifnmake.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "directive-include-fatal.mk" line 13: Malformed conditional (${UNDEF}) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.mk (revision 367461) @@ -0,0 +1,27 @@ +# $NetBSD: directive-include-fatal.mk,v 1.2 2020/09/13 10:20:11 rillig Exp $ +# +# Test for the .include directive combined with fatal errors. +# +# At 2020-09-13, the code in Parse_File that sets "fatals = 0" looked +# suspicious, as if it were possible to suppress fatal errors by including +# another file. It was a false alarm though, since Parse_File only handles +# the top-level makefiles from the command line. Any included files are +# handled by Parse_include_file instead, and that function does not reset +# the "fatals" counter. + +# Using an undefined variable in a condition generates a fatal error. +.if ${UNDEF} +.endif + +# Including another file does not reset the global variable "fatals". +# The exit status will be 1. +.include "/dev/null" + +# Adding another file to be included has no effect either. +# When the command line is parsed, the additional file is only enqueued +# in the global "makefiles" variable, but not immediately run through +# Parse_File. +.MAKEFLAGS: -f "/dev/null" + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-include-fatal.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-include.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-include.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-include.exp (revision 367461) @@ -0,0 +1,5 @@ +CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" +lhs = "directive-include.mk null", rhs = "directive-include.mk null", op = != +CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" +lhs = "directive-include.mk null", rhs = "directive-include.mk null", op = != +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-include.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-include.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-include.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-include.mk (revision 367461) @@ -0,0 +1,26 @@ +# $NetBSD: directive-include.mk,v 1.3 2020/10/31 23:01:23 rillig Exp $ +# +# Tests for the .include directive, which includes another file. + +# TODO: Implementation + +.MAKEFLAGS: -dc + +# All included files are recorded in the variable .MAKE.MAKEFILES. +# In this test, only the basenames of the files are compared since +# the directories can differ. +.include "/dev/null" +.if ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" +. error +.endif + +# Each file is recorded only once in the variable .MAKE.MAKEFILES. +# Between 2015-11-26 and 2020-10-31, the very last file could be repeated, +# due to an off-by-one bug in ParseTrackInput. +.include "/dev/null" +.if ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-include.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: directive-sinclude.mk,v 1.1 2020/09/13 09:20:23 rillig Exp $ +# +# Tests for the .sinclude directive, which includes another file, +# silently skipping it if it cannot be opened. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-sinclude.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.mk (revision 367461) @@ -0,0 +1,17 @@ +# $NetBSD: directive-undef.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the .undef directive. + +# As of 2020-07-28, .undef only undefines the first variable. +# All further variable names are silently ignored. +# See parse.c, string literal "undef". +1= 1 +2= 2 +3= 3 +.undef 1 2 3 +.if ${1:U_}${2:U_}${3:U_} != _23 +. warning $1$2$3 +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "directive-unexport.mk" line 14: UT_A=a UT_B=b UT_C=c +make: "directive-unexport.mk" line 15: UT_A UT_B UT_C +make: "directive-unexport.mk" line 23: UT_A=a UT_B=b UT_C=c +make: "directive-unexport.mk" line 24: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.mk (revision 367461) @@ -0,0 +1,27 @@ +# $NetBSD: directive-unexport.mk,v 1.4 2020/10/30 23:54:42 sjg Exp $ +# +# Tests for the .unexport directive. + +# TODO: Implementation + +# First, export 3 variables. +UT_A= a +UT_B= b +UT_C= c +.export UT_A UT_B UT_C + +# Show the exported variables and their values. +.info ${:!env|sort|grep '^UT_'!} +.info ${.MAKE.EXPORTED} + +# XXX: Now try to unexport all of them. The variables are still exported +# but not mentioned in .MAKE.EXPORTED anymore. +# See the ":N" in Var_UnExport for the implementation. +*= asterisk +.unexport * + +.info ${:!env|sort|grep '^UT_'!} +.info ${.MAKE.EXPORTED} + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directives.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directives.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directives.mk (revision 367461) @@ -0,0 +1,163 @@ +# $NetBSD: directives.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for parsing directives, in the same order as in the manual page. +# +# Each test group has 10 lines, to keep the line numbers in directives.exp +# stable. +# +# no tests for .error since it exits immediately, see ParseMessage. + +.info begin .export tests +.expor # misspelled +.export # oops: missing argument +.export VARNAME +.exporting works # oops: misspelled + + + + + +.info begin .export-env tests +.export-en # oops: misspelled +.export-env +.export-environment # oops: misspelled + + + + + + +.info begin .export-literal tests +.export-litera # oops: misspelled +.export-literal # oops: missing argument +.export-literal VARNAME +.export-literally # oops: misspelled + + + + + +.info begin .info tests +.inf # misspelled +.info # oops: message should be "missing parameter" +.info message +.info indented message +.information +.information message # oops: misspelled +.info.man: # not a message, but a suffix rule + + +.info begin .undef tests +.unde # misspelled +.undef # oops: missing argument +.undefined # oops: misspelled +.undef VARNAME + + + + + +.info begin .unexport tests +.unexpor # misspelled +.unexport # oops: missing argument +.unexport VARNAME # ok +.unexporting works # oops: misspelled + + + + + +.info begin .unexport-env tests +.unexport-en # misspelled +.unexport-env # ok +.unexport-environment # oops: misspelled + + + + + + +.info begin .warning tests +.warn # misspelled +.warnin # misspelled +.warning # oops: should be "missing argument" +.warning message # ok +.warnings # misspelled +.warnings messages # oops + + + +.info begin .elif misspellings tests, part 1 +.if 1 +.elif 1 # ok +.elsif 1 # oops: misspelled +.elseif 1 # oops: misspelled +.endif + + + + +.info begin .elif misspellings tests, part 2 +.if 0 +.elif 0 # ok +.elsif 0 # oops: misspelled +.elseif 0 # oops: misspelled +.endif + + + + +.info begin .elif misspellings tests, part 3 +.if 0 +.elsif 0 # oops: misspelled +.endif +.if 0 +.elseif 0 # oops: misspelled +.endif + + + +.info which branch is taken on misspelling after false? +.if 0 +.elsif 1 +. info 1 taken +.elsif 2 +. info 2 taken +.else +. info else taken +.endif + +.info which branch is taken on misspelling after true? +.if 1 +.elsif 1 +. info 1 taken +.elsif 2 +. info 2 taken +.else +. info else taken +.endif + +.indented none +. indented 2 spaces +. indented tab +.${:Uinfo} directives cannot be indirect + + + + + + +.include "nonexistent.mk" +.include "/dev/null" # size 0 +# including a directory technically succeeds, but shouldn't. +#.include "." # directory + + + + + + +.info end of the tests + +all: + @: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directives.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/doterror.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/doterror.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/doterror.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: doterror.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + + +.BEGIN: + @echo At first, I am + +.END: + @echo not reached + +.ERROR: + @echo "$@: Looks like '${.ERROR_TARGET}' is upset." + +all: happy sad + +happy: + @echo $@ + +sad: + @echo and now: $@; exit 1 + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/doterror.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dotwait.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dotwait.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dotwait.mk (revision 367461) @@ -0,0 +1,61 @@ +# $NetBSD: dotwait.mk,v 1.3 2020/10/24 08:50:17 rillig Exp $ + +THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE} + +TESTS= simple recursive shared cycle +PAUSE= sleep 1 + +# Use a .for loop rather than dependencies here, to ensure +# that the tests are run one by one, with parallelism +# only within tests. +# Ignore "--- target ---" lines printed by parallel make. +all: +.for t in ${TESTS} + @${.MAKE} -f ${THISMAKEFILE} -j4 $t 2>&1 | grep -v "^--- " +.endfor + +# +# Within each test, the names of the sub-targets follow these +# conventions: +# * If it's expected that two or more targets may be made in parallel, +# then the target names will differ only in an alphabetic component +# such as ".a" or ".b". +# * If it's expected that two or more targets should be made in sequence +# then the target names will differ in numeric components, such that +# lexical ordering of the target names matches the expected order +# in which the targets should be made. +# +# Targets may echo ${PARALLEL_TARG} to print a modified version +# of their own name, in which alphabetic components like ".a" or ".b" +# are converted to ".*". Two targets that are expected to +# be made in parallel will thus print the same strings, so that the +# output is independent of the order in which these targets are made. +# +PARALLEL_TARG= ${.TARGET:C/\.[a-z]/.*/g:Q} +.DEFAULT: + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} +_ECHOUSE: .USE + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} + +# simple: no recursion, no cycles +simple: simple.1 .WAIT simple.2 + +# recursive: all children of the left hand side of the .WAIT +# must be made before any child of the right hand side. +recursive: recursive.1.99 .WAIT recursive.2.99 +recursive.1.99: recursive.1.1.a recursive.1.1.b _ECHOUSE +recursive.2.99: recursive.2.1.a recursive.2.1.b _ECHOUSE + +# shared: both shared.1.99 and shared.2.99 depend on shared.0. +# shared.0 must be made first, even though it is a child of +# the right hand side of the .WAIT. +shared: shared.1.99 .WAIT shared.2.99 +shared.1.99: shared.0 _ECHOUSE +shared.2.99: shared.2.1 shared.0 _ECHOUSE + +# cycle: the cyclic dependency must not cause infinite recursion +# leading to stack overflow and a crash. +cycle: cycle.1.99 .WAIT cycle.2.99 +cycle.2.99: cycle.2.98 _ECHOUSE +cycle.2.98: cycle.2.97 _ECHOUSE +cycle.2.97: cycle.2.99 _ECHOUSE Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dotwait.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/envfirst.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/envfirst.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/envfirst.mk (revision 367461) @@ -0,0 +1,42 @@ +# $NetBSD: envfirst.mk,v 1.3 2020/10/24 08:46:08 rillig Exp $ +# +# The -e option makes environment variables stronger than global variables. + +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +# Try to override the variable; this does not have any effect. +FROM_ENV= value-from-mk +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +# Try to append to the variable; this also doesn't have any effect. +FROM_ENV+= appended +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +# The default assignment also cannot change the variable. +FROM_ENV?= default +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +# Neither can the assignment modifiers. +.if ${FROM_ENV::=from-condition} +.endif +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +# Even .undef doesn't work since it only affects the global context, +# which is independent from the environment variables. +.undef FROM_ENV +.if ${FROM_ENV} != value-from-env +. error ${FROM_ENV} +.endif + +all: + @: nothing Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/envfirst.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/error.exp (revision 367461) @@ -0,0 +1,6 @@ +make: "error.mk" line 3: just FYI +make: "error.mk" line 4: warning: this could be serious +make: "error.mk" line 5: this is fatal + +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/error.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: error.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +.info just FYI +.warning this could be serious +.error this is fatal + +all: + +.info.html: + @echo this should be ignored Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/escape.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/escape.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/escape.mk (revision 367461) @@ -0,0 +1,246 @@ +# $NetBSD: escape.mk,v 1.13 2020/10/24 08:50:17 rillig Exp $ +# +# Test backslash escaping. + +# Extracts from the POSIX 2008 specification +# : +# +# Comments start with a ( '#' ) and continue until an +# unescaped is reached. +# +# When an escaped (one preceded by a ) is found +# anywhere in the makefile except in a command line, an include +# line, or a line immediately preceding an include line, it shall +# be replaced, along with any leading white space on the following +# line, with a single . +# +# When an escaped is found in a command line in a +# makefile, the command line shall contain the , the +# , and the next line, except that the first character of +# the next line shall not be included if it is a . +# +# When an escaped is found in an include line or in a +# line immediately preceding an include line, the behavior is +# unspecified. +# +# Notice that the behaviour of or +# is not mentioned. I think +# this implies that should be taken literally everywhere +# except before . +# +# Our practice, despite what POSIX might say, is that "\#" +# in a variable assignment stores "#" as part of the value. +# The "\" is not taken literally, and the "#" does not begin a comment. +# +# Also, our practice is that an even number of backslashes before a +# newline in a variable assignment simply stores the backslashes as part +# of the value, and treats the newline as though it was not escaped. +# Similarly, an even number of backslashes before a newline in a +# command simply uses the backslashes as part of the command, but +# does not escape the newline. This is compatible with GNU make. + +all: .PHONY +# We will add dependencies like "all: yet-another-test" later. + +# Some variables to be expanded in tests +# +a= aaa +A= ${a} + +# Backslash at end of line in a comment\ +should continue the comment. \ +# This is also tested in comment.mk. + +__printvars: .USE .MADE + @echo ${.TARGET} + ${.ALLSRC:@v@ printf "%s=:%s:\n" ${v:Q} ${${v}:Q}; @} + +# Embedded backslash in variable should be taken literally. +# +VAR1BS= 111\111 +VAR1BSa= 111\${a} +VAR1BSA= 111\${A} +VAR1BSda= 111\$${a} +VAR1BSdA= 111\$${A} +VAR1BSc= 111\# backslash escapes comment char, so this is part of the value +VAR1BSsc= 111\ # This is a comment. Value ends with + +all: var-1bs +var-1bs: .PHONY __printvars VAR1BS VAR1BSa VAR1BSA VAR1BSda VAR1BSdA \ + VAR1BSc VAR1BSsc + +# Double backslash in variable should be taken as two literal backslashes. +# +VAR2BS= 222\\222 +VAR2BSa= 222\\${a} +VAR2BSA= 222\\${A} +VAR2BSda= 222\\$${a} +VAR2BSdA= 222\\$${A} +VAR2BSc= 222\\# backslash does not escape comment char, so this is a comment +VAR2BSsc= 222\\ # This is a comment. Value ends with + +all: var-2bs +var-2bs: .PHONY __printvars VAR2BS VAR2BSa VAR2BSA VAR2BSda VAR2BSdA \ + VAR2BSc VAR2BSsc + +# Backslash-newline in a variable setting is replaced by a single space. +# +VAR1BSNL= 111\ +111 +VAR1BSNLa= 111\ +${a} +VAR1BSNLA= 111\ +${A} +VAR1BSNLda= 111\ +$${a} +VAR1BSNLdA= 111\ +$${A} +VAR1BSNLc= 111\ +# this should be processed as a comment +VAR1BSNLsc= 111\ + # this should be processed as a comment + +all: var-1bsnl +var-1bsnl: .PHONY +var-1bsnl: .PHONY __printvars \ + VAR1BSNL VAR1BSNLa VAR1BSNLA VAR1BSNLda VAR1BSNLdA \ + VAR1BSNLc VAR1BSNLsc + +# Double-backslash-newline in a variable setting. +# Both backslashes should be taken literally, and the newline is NOT escaped. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR2BSNL= 222\\ +222= +VAR2BSNLa= 222\\ +${a}= +VAR2BSNLA= 222\\ +${A}= +VAR2BSNLda= 222\\ +$${a}= +VAR2BSNLdA= 222\\ +$${A}= +VAR2BSNLc= 222\\ +# this should be processed as a comment +VAR2BSNLsc= 222\\ + # this should be processed as a comment + +all: var-2bsnl +var-2bsnl: .PHONY __printvars \ + VAR2BSNL VAR2BSNLa VAR2BSNLA VAR2BSNLda VAR2BSNLdA \ + VAR2BSNLc VAR2BSNLsc + +# Triple-backslash-newline in a variable setting. +# First two should be taken literally, and last should escape the newline. +# +# The second lines below each end with '=' so that they will not +# generate syntax errors regardless of whether or not they are +# treated as part of the value. +# +VAR3BSNL= 333\\\ +333= +VAR3BSNLa= 333\\\ +${a}= +VAR3BSNLA= 333\\\ +${A}= +VAR3BSNLda= 333\\\ +$${a}= +VAR3BSNLdA= 333\\\ +$${A}= +VAR3BSNLc= 333\\\ +# this should be processed as a comment +VAR3BSNLsc= 333\\\ + # this should be processed as a comment + +all: var-3bsnl +var-3bsnl: .PHONY __printvars \ + VAR3BSNL VAR3BSNLa VAR3BSNLA VAR3BSNLda VAR3BSNLdA \ + VAR3BSNLc VAR3BSNLsc + +# Backslash-newline in a variable setting, plus any amount of white space +# on the next line, is replaced by a single space. +# +VAR1BSNL00= first line\ + +# above line is entirely empty, and this is a comment +VAR1BSNL0= first line\ +no space on second line +VAR1BSNLs= first line\ + one space on second line +VAR1BSNLss= first line\ + two spaces on second line +VAR1BSNLt= first line\ + one tab on second line +VAR1BSNLtt= first line\ + two tabs on second line +VAR1BSNLxx= first line\ + many spaces and tabs [ ] on second line + +all: var-1bsnl-space +var-1bsnl-space: .PHONY __printvars \ + VAR1BSNL00 VAR1BSNL0 VAR1BSNLs VAR1BSNLss VAR1BSNLt VAR1BSNLtt \ + VAR1BSNLxx + +# Backslash-newline in a command is retained. +# +# The "#" in "# second line without space" makes it a comment instead +# of a syntax error if the preceding line is parsed incorretly. +# The ":" in "third line':" makes it look like the start of a +# target instead of a syntax error if the first line is parsed incorrectly. +# +all: cmd-1bsnl +cmd-1bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\ +#second line without space\ +third line': + echo :'first line\ + second line spaces should be retained': + echo :'first line\ + second line tab should be elided': + echo :'first line\ + only one tab should be elided, second tab remains' + +# When backslash-newline appears at the end of a command script, +# both the backslash and the newline should be passed to the shell. +# The shell should elide the backslash-newline. +# +all: cmd-1bsnl-eof +cmd-1bsnl-eof: + @echo ${.TARGET} + echo :'command ending with backslash-newline'; \ + +# above line must be blank + +# Double-backslash-newline in a command. +# Both backslashes are retained, but the newline is not escaped. +# XXX: This may differ from POSIX, but matches gmake. +# +# When make passes two backslashes to the shell, the shell will pass one +# backslash to the echo commant. +# +all: cmd-2bsnl +cmd-2bsnl: .PHONY + @echo ${.TARGET} + echo take one\\ +# this should be a comment + echo take two\\ + echo take three\\ + +# Triple-backslash-newline in a command is retained. +# +all: cmd-3bsnl +cmd-3bsnl: .PHONY + @echo ${.TARGET} + echo :'first line\\\ +#second line without space\\\ +third line': + echo :'first line\\\ + second line spaces should be retained': + echo :'first line\\\ + second line tab should be elided': + echo :'first line\\\ + only one tab should be elided, second tab remains' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/escape.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/export-all.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-all.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-all.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: export-all.mk,v 1.5 2020/10/24 08:50:17 rillig Exp $ + +UT_OK= good +UT_F= fine + +# the old way to do :tA +M_tAbad= C,.*,cd & \&\& 'pwd',:sh +# the new +M_tA= tA + +here := ${.PARSEDIR} + +# this will cause trouble (recursing if we let it) +UT_BADDIR= ${${here}/../${here:T}:L:${M_tAbad}:T} +# this will be ok +UT_OKDIR= ${${here}/../${here:T}:L:${M_tA}:T} + +.export + +FILTER_CMD= grep ^UT_ +.include "export.mk" + +UT_TEST= export-all +UT_ALL= even this gets exported Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/export-all.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/export-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-env.mk (revision 367461) @@ -0,0 +1,27 @@ +# $NetBSD: export-env.mk,v 1.4 2020/10/24 08:50:17 rillig Exp $ + +# our normal .export, subsequent changes affect the environment +UT_TEST= this +.export UT_TEST +UT_TEST:= ${.PARSEFILE} + +# not so with .export-env +UT_ENV= exported +.export-env UT_ENV +UT_ENV= not-exported + +# gmake style export goes further; affects nothing but the environment +UT_EXP=before-export +export UT_EXP=exported +UT_EXP=not-exported + +UT_LIT= literal ${UT_TEST} +.export-literal UT_LIT + +all: + @echo make:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=${$v};@} + @echo env:; ${UT_TEST UT_ENV UT_EXP UT_LIT:L:@v@echo $v=$${$v};@} + + + + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/export-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/export-variants.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-variants.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-variants.mk (revision 367461) @@ -0,0 +1,40 @@ +# $NetBSD: export-variants.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Test whether exported variables apply to each variant of running +# external commands: +# +# The != assignments. +# The :!cmd! modifier. +# The :sh modifier. + +SHVAR!= env | grep ^UT_ || true +.if ${SHVAR} != "" +. warning At this point, no variable should be exported. +.endif + +.if ${:!env | grep ^UT_ || true!} != "" +. warning At this point, no variable should be exported. +.endif + +.if ${env | grep ^UT_ || true:L:sh} != "" +. warning At this point, no variable should be exported. +.endif + +UT_VAR= value +.export UT_VAR + +SHVAR!= env | grep ^UT_ || true +.if ${SHVAR} != "UT_VAR=value" +. warning At this point, a single variable should be exported. +.endif + +.if ${:!env | grep ^UT_ || true!} != "UT_VAR=value" +. warning At this point, a single variable should be exported. +.endif + +.if ${env | grep ^UT_ || true:L:sh} != "UT_VAR=value" +. warning At this point, a single variable should be exported. +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/export-variants.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/export.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export.exp (revision 367461) @@ -0,0 +1,7 @@ +MAKELEVEL=1 +UT_DOLLAR=This is $UT_FU +UT_FOO=foobar is fubar +UT_FU=fubar +UT_TEST=export +UT_ZOO=hoopie +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/export.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export.mk (revision 367461) @@ -0,0 +1,46 @@ +# $NetBSD: export.mk,v 1.10 2020/10/24 08:50:17 rillig Exp $ + +UT_TEST= export +UT_FOO= foo${BAR} +UT_FU= fubar +UT_ZOO= hoopie +UT_NO= all +# believe it or not, we expect this one to come out with $UT_FU unexpanded. +UT_DOLLAR= This is $$UT_FU + +.export UT_FU UT_FOO +.export UT_DOLLAR + +.if !defined(.MAKE.PID) +. error .MAKE.PID must be defined +.endif +@= at +%= percent +*= asterisk +${:U!}= exclamation # A direct != would try to run "exclamation" + # as a shell command and assign its output + # to the empty variable. +&= ampersand + +# This is ignored because it is internal. +.export .MAKE.PID +# These are ignored because they are local to the target. +.export @ +.export % +.export * +.export ! +# This is exported (see the .rawout file) but not displayed since the dash +# shell filters it out. To reach consistent output for each shell, the +# ampersand is filtered out already by FILTER_CMD. +.export & +# This is ignored because it is undefined. +.export UNDEFINED + +BAR= bar is ${UT_FU} + +.MAKE.EXPORTED+= UT_ZOO UT_TEST + +FILTER_CMD?= egrep -v '^(MAKEFLAGS|MALLOC_OPTIONS|PATH|PWD|SHLVL|_|&)=' + +all: + @env | ${FILTER_CMD} | sort Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/export.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/forloop.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/forloop.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/forloop.exp (revision 367461) @@ -0,0 +1,20 @@ +x=one +x="two and three" +x=four +x="five" +x=-I/this +x=-I"This or that" +x=-Ithat +x="-DTHIS=\"this and that\"" +cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +newline-item=(a) +a=one b="two and three" +a=four b="five" +a=ONE b="TWO AND THREE" +a=FOUR b="FIVE" +We expect an error next: +make: "forloop.mk" line 46: Wrong number of words (9) in .for substitution list with 2 variables +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +OK +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/forloop.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/forloop.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/forloop.mk (revision 367461) @@ -0,0 +1,53 @@ +# $NetBSD: forloop.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ + +all: for-loop + +LIST= one "two and three" four "five" + +.if make(for-fail) +for-fail: + +XTRA_LIST= xtra +.else + +. for x in ${LIST} +X!= echo 'x=$x' >&2; echo +. endfor + +CFL= -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +cfl= +. for x in ${CFL} +X!= echo 'x=$x' >&2; echo +. if empty(cfl) +cfl= $x +. else +cfl+= $x +. endif +. endfor +X!= echo 'cfl=${cfl}' >&2; echo + +. if ${cfl} != ${CFL} +. error ${.newline}'${cfl}' != ${.newline}'${CFL}' +. endif + +. for a b in ${EMPTY} +X!= echo 'a=$a b=$b' >&2; echo +. endfor + +# Since at least 1993, iteration stops at the first newline. +# Back then, the .newline variable didn't exist, therefore it was unlikely +# that a newline ever occurred. +. for var in a${.newline}b${.newline}c +X!= echo 'newline-item=('${var:Q}')' 1>&2; echo +. endfor + +.endif # for-fail + +.for a b in ${LIST} ${LIST:tu} ${XTRA_LIST} +X!= echo 'a=$a b=$b' >&2; echo +.endfor + +for-loop: + @echo We expect an error next: + @(cd ${.CURDIR} && ${.MAKE} -f ${MAKEFILE} for-fail) && \ + { echo "Oops that should have failed!"; exit 1; } || echo OK Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/forloop.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/forsubst.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/forsubst.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/forsubst.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: forsubst.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +all: for-subst + +here := ${.PARSEDIR} +# this should not run foul of the parser +.for file in ${.PARSEFILE} +for-subst: ${file:S;^;${here}/;g} + @echo ".for with :S;... OK" +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/forsubst.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.exp (revision 367461) @@ -0,0 +1,32 @@ +Move the upper disk from stack A to stack C. +Move the upper disk from stack A to stack B. +Move the upper disk from stack C to stack B. +Move the upper disk from stack A to stack C. +Move the upper disk from stack B to stack A. +Move the upper disk from stack B to stack C. +Move the upper disk from stack A to stack C. +Move the upper disk from stack A to stack B. +Move the upper disk from stack C to stack B. +Move the upper disk from stack C to stack A. +Move the upper disk from stack B to stack A. +Move the upper disk from stack C to stack B. +Move the upper disk from stack A to stack C. +Move the upper disk from stack A to stack B. +Move the upper disk from stack C to stack B. +Move the upper disk from stack A to stack C. +Move the upper disk from stack B to stack A. +Move the upper disk from stack B to stack C. +Move the upper disk from stack A to stack C. +Move the upper disk from stack B to stack A. +Move the upper disk from stack C to stack B. +Move the upper disk from stack C to stack A. +Move the upper disk from stack B to stack A. +Move the upper disk from stack B to stack C. +Move the upper disk from stack A to stack C. +Move the upper disk from stack A to stack B. +Move the upper disk from stack C to stack B. +Move the upper disk from stack A to stack C. +Move the upper disk from stack B to stack A. +Move the upper disk from stack B to stack C. +Move the upper disk from stack A to stack C. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.mk (revision 367461) @@ -0,0 +1,41 @@ +# $NetBSD: hanoi-include.mk,v 1.1 2020/10/03 17:30:54 rillig Exp $ +# +# Implements the Towers of Hanoi puzzle, thereby demonstrating a bunch of +# useful programming techniques: +# +# * default assignment using the ?= assignment operator +# * including the same file recursively +# * extracting the current value of a variable using the .for loop +# * using shell commands for calculations since make is a text processor +# * using the :: dependency operator for adding commands to a target +# * on-the-fly variable assignment expressions using the ::= modifier +# +# usage: +# env N=3 make -f hanoi-include.mk +# endless loop: +# make -f hanoi-include.mk N=3 + +N?= 5 # Move this number of disks ... +FROM?= A # ... from this stack ... +VIA?= B # ... via this stack ... +TO?= C # ... to this stack. + +.if $N == 1 +. for from to in ${FROM} ${TO} +all:: + @echo "Move the upper disk from stack ${from} to stack ${to}." +. endfor +.else +_:= ${N::!=expr $N - 1} ${TMP::=${VIA}} ${VIA::=${TO}} ${TO::=${TMP}} +. include "${.PARSEDIR}/${.PARSEFILE}" +_:= ${N::!=expr $N + 1} ${TMP::=${VIA}} ${VIA::=${TO}} ${TO::=${TMP}} + +. for from to in ${FROM} ${TO} +all:: + @echo "Move the upper disk from stack ${from} to stack ${to}." +. endfor + +_:= ${N::!=expr $N - 1} ${TMP::=${VIA}} ${VIA::=${FROM}} ${FROM::=${TMP}} +. include "${.PARSEDIR}/${.PARSEFILE}" +_:= ${N::!=expr $N + 1} ${TMP::=${VIA}} ${VIA::=${FROM}} ${FROM::=${TMP}} +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/hanoi-include.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/include-main.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/include-main.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/include-main.exp (revision 367461) @@ -0,0 +1,10 @@ +make: "include-main.mk" line 14: main-before-ok +make: "include-main.mk" line 21: main-before-for-ok +make: "include-sub.mk" line 4: sub-before-ok +make: "include-sub.mk" line 14: sub-before-for-ok +make: "include-subsub.mk" line 4: subsub-ok +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 +make: "include-main.mk" line 37: main-after-for-ok +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/include-main.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/include-main.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/include-main.mk (revision 367461) @@ -0,0 +1,43 @@ +# $NetBSD: include-main.mk,v 1.5 2020/09/05 18:18:05 rillig Exp $ +# +# Until 2020-09-05, the .INCLUDEDFROMFILE magic variable did not behave +# as described in the manual page. +# +# The manual page says that it is the "filename of the file this Makefile +# was included from", while before 2020-09-05 it was the "filename in which +# the latest .include happened". See parse.c, function ParseSetIncludeFile. +# +# Since 2020-09-05, the .INCLUDEDFROMDIR and .INCLUDEDFROMFILE variables +# properly handle nested includes and even .for loops. + +.if !defined(.INCLUDEDFROMFILE) +. info main-before-ok +.else +. warning main-before-fail(${.INCLUDEDFROMFILE}) +.endif + +.for i in once +. if !defined(${.INCLUDEDFROMFILE}) +. info main-before-for-ok +. else +. warning main-before-for-fail(${.INCLUDEDFROMFILE}) +. endif +.endfor + +.include "include-sub.mk" + +.if !defined(.INCLUDEDFROMFILE) +. info main-after-ok +.else +. warning main-after-fail(${.INCLUDEDFROMFILE}) +.endif + +.for i in once +. if !defined(${.INCLUDEDFROMFILE}) +. info main-after-for-ok +. else +. warning main-after-for-fail(${.INCLUDEDFROMFILE}) +. endif +.endfor + +all: # nothing Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/include-main.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/include-sub.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/include-sub.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/include-sub.mk (revision 367461) @@ -0,0 +1,49 @@ +# $NetBSD: include-sub.mk,v 1.6 2020/10/25 12:08:53 rillig Exp $ + +.if ${.INCLUDEDFROMFILE} == "include-main.mk" +. info sub-before-ok +.else +. warning sub-before-fail(${.INCLUDEDFROMFILE}) +.endif + +# As of 2020-09-05, the .for loop is implemented as "including a file" +# with a custom buffer. Therefore this loop has side effects on these +# variables. +.for i in once +. if ${.INCLUDEDFROMFILE} == "include-main.mk" +. info sub-before-for-ok +. else +. warning sub-before-for-fail(${.INCLUDEDFROMFILE}) +. endif +.endfor + +# To see the variable 'includes' in action: +# +# Breakpoints: +# Parse_File at "PtrVector_Push(&includes, curFile)" +# ParseMessage at entry +# Watches: +# ((const IFile *[10])(*includes.items)) +# *curFile + +.for i in deeply +. for i in nested +. for i in include +.include "include-subsub.mk" +. endfor +. endfor +.endfor + +.if ${.INCLUDEDFROMFILE} == "include-main.mk" +. info sub-after-ok +.else +. warning sub-after-fail(${.INCLUDEDFROMFILE}) +.endif + +.for i in once +. if ${.INCLUDEDFROMFILE} == "include-main.mk" +. info sub-after-for-ok +. else +. warning sub-after-for-fail(${.INCLUDEDFROMFILE}) +. endif +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/include-sub.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/include-subsub.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/include-subsub.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/include-subsub.mk (revision 367461) @@ -0,0 +1,7 @@ +# $NetBSD: include-subsub.mk,v 1.3 2020/09/05 18:13:47 rillig Exp $ + +.if ${.INCLUDEDFROMFILE} == "include-sub.mk" +. info subsub-ok +.else +. warning subsub-fail(${.INCLUDEDFROMFILE}) +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/include-subsub.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.mk (revision 367461) @@ -0,0 +1,32 @@ +# $NetBSD: job-output-long-lines.mk,v 1.4 2020/11/01 17:29:13 rillig Exp $ +# +# The jobs may produce long lines of output. A practical case are the echoed +# command lines from compiler invocations, with their many -D options. +# +# Each of these lines must be written atomically to the actual output. +# The markers for switching jobs must always be written at the beginning of +# the line, to make them clearly visible in large log files. +# +# As of 2020-09-27, the default job buffer size is 1024. When a job produces +# output lines that are longer than this buffer size, these output pieces are +# not terminated by a newline. Because of this missing newline, the job +# markers "--- job-a ---" and "--- job-b ---" are not always written at the +# beginning of a line, even though this is expected by anyone reading the log +# files. + +.MAKEFLAGS: -j2 + +100:= ${:U1:S,1,2222222222,g:S,2,3333333333,g} +5000:= ${100:S,3,4444444444,g:S,4,xxxxx,g} + +all: job-a job-b + +job-a: +.for i in ${:U:range=20} + @echo ${5000:S,x,a,g} +.endfor + +job-b: +.for i in ${:U:range=20} + @echo ${5000:S,x,b,g} +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/job-output-long-lines.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/lint.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/lint.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/lint.exp (revision 367461) @@ -0,0 +1,4 @@ +make: In the :@ modifier of "VAR", the variable name "${:Ubar:S,b,v,}" must not contain a dollar. +y@:Q} +xvaluey +exit status 2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/lint.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/lint.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/lint.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/lint.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: lint.mk,v 1.3 2020/09/15 16:22:04 rillig Exp $ +# +# Demonstrates stricter checks that are only enabled in the lint mode, +# using the -dL option. + +# Ouch: as of 2020-08-03, make exits successfully even though the error +# message has been issued as PARSE_FATAL. + +# Ouch: as of 2020-08-03, the variable is malformed and parsing stops +# for a moment, but is continued after the wrongly-guessed end of the +# variable, which echoes "y@:Q}". + +.MAKEFLAGS: -dL + +all: mod-loop-varname + +mod-loop-varname: + @echo ${VAR:Uvalue:@${:Ubar:S,b,v,}@x${var}y@:Q} + @echo ${VAR:Uvalue:@!@x$!y@:Q} # surprisingly allowed Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/lint.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/make-exported.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/make-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/make-exported.exp (revision 367461) @@ -0,0 +1,2 @@ +UT_VAR= +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/make-exported.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/make-exported.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/make-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/make-exported.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: make-exported.mk,v 1.6 2020/10/05 19:27:48 rillig Exp $ +# +# As of 2020-08-09, the code in Var_Export is shared between the .export +# directive and the .MAKE.EXPORTED variable. This leads to non-obvious +# behavior for certain variable assignments. + +-env= make-exported-value-env +-literal= make-exported-value-literal +UT_VAR= ${UNEXPANDED} + +# Before 2020-10-03, the following line took the code path of .export-env, +# which was surprising behavior. Since 2020-10-03 this line tries to +# export the variable named "-env", but that is rejected because the +# variable name starts with a hyphen. +.MAKE.EXPORTED= -env + +# Before 2020-10-03, if the value of .MAKE.EXPORTED started with "-literal", +# make behaved like a mixture of .export-literal and a regular .export. +# +# Since 2020-10-03, the "variable" named "-literal" is not exported anymore, +# it is just ignored since its name starts with '-'. +.MAKE.EXPORTED= -literal UT_VAR + +all: + @env | sort | grep -E '^UT_|make-exported-value' || true Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/make-exported.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/moderrs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/moderrs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/moderrs.exp (revision 367461) @@ -0,0 +1,144 @@ +mod-unknown-direct: +want: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z=before--after + +mod-unknown-indirect: +want: 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 +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 +VAR:S,V,v,=Thevariable + +unfinished-indirect: +want: 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) + +want: 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 @ +1}... 2}... 3}... +1}... 2}... 3}... + +words: +want: Unfinished modifier for UNDEF (']' missing) +make: Unfinished modifier for UNDEF (']' missing) + +want: Unfinished modifier for UNDEF (']' missing) +make: Unfinished modifier for UNDEF (']' missing) + +13= +make: Bad modifier `:[123451234512345123451234512345]' for UNDEF +12345=S,^ok,:S,^3ok,} + +exclam: +want: Unfinished modifier for VARNAME ('!' missing) +make: Unfinished modifier for VARNAME ('!' missing) + +want: Unfinished modifier for ! ('!' missing) +make: Unfinished modifier for ! ('!' missing) + + +mod-subst-delimiter: +make: Missing delimiter for :S modifier +1: +make: Unfinished modifier for VAR (',' missing) +2: +make: Unfinished modifier for VAR (',' missing) +3: +make: Unfinished modifier for VAR (',' missing) +4: +make: Unfinished modifier for VAR (',' missing) +5: +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier S +6: TheVariable +7: TheVariable + +mod-regex-delimiter: +make: Missing delimiter for :C modifier +1: +make: Unfinished modifier for VAR (',' missing) +2: +make: Unfinished modifier for VAR (',' missing) +3: +make: Unfinished modifier for VAR (',' missing) +4: +make: Unfinished modifier for VAR (',' missing) +5: +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier C +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 +65oct} +make: Bad modifier `:tsxy' for FIB +xy} + +mod-t-parse: +make: Bad modifier `:t' for FIB + +make: Bad modifier `:txy' for FIB +y} +make: Bad modifier `:t' for FIB + +make: Bad modifier `:t' for 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) + +then + +mod-remember-parse: +1 1 2 3 5 8 13 21 34 +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 specification (expecting '}') for "FIB" (value "") modifier 3 + +make: Unknown modifier '3' +make: Unclosed variable specification (expecting '}') for "FIB" (value "") modifier 3 + +1 1 2 x3 5 8 1x3 21 34 + +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/moderrs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/moderrs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/moderrs.mk (revision 367461) @@ -0,0 +1,171 @@ +# $NetBSD: moderrs.mk,v 1.24 2020/11/01 14:36:25 rillig Exp $ +# +# various modifier error tests + +'= '\'' +VAR= TheVariable +# in case we have to change it ;-) +MOD_UNKN= Z +MOD_TERM= S,V,v +MOD_S:= ${MOD_TERM}, + +FIB= 1 1 2 3 5 8 13 21 34 + +all: mod-unknown-direct mod-unknown-indirect +all: unclosed-direct unclosed-indirect +all: unfinished-indirect unfinished-loop +all: loop-close +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 +all: mod-remember-parse +all: mod-sysv-parse + +mod-unknown-direct: print-header print-footer + @echo 'want: Unknown modifier $'Z$'' + @echo 'VAR:Z=before-${VAR:Z}-after' + +mod-unknown-indirect: print-header print-footer + @echo 'want: Unknown modifier $'Z$'' + @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 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 VAR:${MOD_TERM},=${VAR:${MOD_S} + +unfinished-indirect: print-header print-footer + @echo 'want: Unfinished modifier for VAR ($',$' missing)' + -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" + +unfinished-loop: print-header print-footer + @echo 'want: Unfinished modifier for UNDEF ($'@$' missing)' + @echo ${UNDEF:U1 2 3:@var} + @echo 'want: Unfinished modifier for UNDEF ($'@$' missing)' + @echo ${UNDEF:U1 2 3:@var@...} + @echo ${UNDEF:U1 2 3:@var@${var}@} + +# The closing brace after the ${var} is part of the replacement string. +# In ParseModifierPart, braces and parentheses don't have to be balanced. +# This is contrary to the :M, :N modifiers, where both parentheses and +# braces must be balanced. +# This is also contrary to the SysV modifier, where only the actually +# used delimiter (either braces or parentheses) must be balanced. +loop-close: print-header print-footer + @echo ${UNDEF:U1 2 3:@var@${var}}...@ + @echo ${UNDEF:U1 2 3:@var@${var}}...@} + +words: print-header print-footer + @echo 'want: Unfinished modifier for UNDEF ($']$' missing)' + @echo ${UNDEF:U1 2 3:[} + @echo 'want: Unfinished modifier for UNDEF ($']$' missing)' + @echo ${UNDEF:U1 2 3:[#} + + # out of bounds => empty + @echo 13=${UNDEF:U1 2 3:[13]} + + # Word index out of bounds. + # + # Until 2020-11-01, the behavior in this case depended upon the size + # of unsigned long. + # + # On LP64I32, strtol returns LONG_MAX, which was then truncated to + # int (undefined behavior), typically resulting in -1. This -1 was + # interpreted as "the last word". + # + # On ILP32, strtol returns LONG_MAX, which is a large number. This + # resulted in a range from LONG_MAX - 1 to 3, which was empty. + # + # Since 2020-11-01, the numeric overflow is detected and generates an + # error. In the remainder of the text, the '$,' is no longer parsed + # as part of a variable modifier, where it would have been interpreted + # as an anchor to the :S modifier, but as a normal variable named ','. + # That variable is undefined, resulting in an empty string. + @echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,} + +exclam: print-header print-footer + @echo 'want: Unfinished modifier for VARNAME ($'!$' missing)' + @echo ${VARNAME:!echo} + # When the final exclamation mark is missing, there is no + # fallback to the SysV substitution modifier. + # If there were a fallback, the output would be "exclam", + # and the above would have produced an "Unknown modifier '!'". + @echo 'want: Unfinished modifier for ! ($'!$' missing)' + @echo ${!:L:!=exclam} + +mod-subst-delimiter: print-header print-footer + @echo 1: ${VAR:S + @echo 2: ${VAR:S, + @echo 3: ${VAR:S,from + @echo 4: ${VAR:S,from, + @echo 5: ${VAR:S,from,to + @echo 6: ${VAR:S,from,to, + @echo 7: ${VAR:S,from,to,} + +mod-regex-delimiter: print-header print-footer + @echo 1: ${VAR:C + @echo 2: ${VAR:C, + @echo 3: ${VAR:C,from + @echo 4: ${VAR:C,from, + @echo 5: ${VAR:C,from,to + @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 not widely used. +# +# 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 ${FIB:tsxy} # modifier too long + +mod-t-parse: print-header print-footer + @echo ${FIB:t + @echo ${FIB:txy} + @echo ${FIB:t} + @echo ${FIB:t:M*} + +mod-ifelse-parse: print-header print-footer + @echo ${FIB:? + @echo ${FIB:?then + @echo ${FIB:?then: + @echo ${FIB:?then:else + @echo ${FIB:?then:else} + +mod-remember-parse: print-header print-footer + @echo ${FIB:_} # ok + @echo ${FIB:__} # modifier name too long + +mod-sysv-parse: print-header print-footer + @echo ${FIB:3 + @echo ${FIB:3= + @echo ${FIB:3=x3 + @echo ${FIB:3=x3} # ok + +print-header: .USEBEFORE + @echo $@: +print-footer: .USE + @echo Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/moderrs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/modmatch.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modmatch.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modmatch.mk (revision 367461) @@ -0,0 +1,30 @@ +# $NetBSD: modmatch.mk,v 1.9 2020/10/24 08:50:17 rillig Exp $ +# +# Tests for the :M and :S modifiers. + +X= a b c d e + +.for x in $X +LIB${x:tu}= /tmp/lib$x.a +.endfor + +X_LIBS= ${LIBA} ${LIBD} ${LIBE} + +LIB?= a + +var= head +res= no +.if !empty(var:M${:Uhead\:tail:C/:.*//}) +res= OK +.endif + +all: show-libs + +show-libs: + @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done + @echo "Mscanner=${res}" + +show: + @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/modmatch.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/modmisc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modmisc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modmisc.mk (revision 367461) @@ -0,0 +1,92 @@ +# $NetBSD: modmisc.mk,v 1.49 2020/10/24 08:50:17 rillig Exp $ +# +# miscellaneous modifier tests + +# do not put any dirs in this list which exist on some +# but not all target systems - an exists() check is below. +path= :/bin:/tmp::/:.:/no/such/dir:. +# strip cwd from path. +MOD_NODOT= S/:/ /g:N.:ts: +# and decorate, note that $'s need to be doubled. Also note that +# the modifier_variable can be used with other modifiers. +MOD_NODOTX= S/:/ /g:N.:@d@'$$d'@ +# another mod - pretend it is more interesting +MOD_HOMES= S,/home/,/homes/, +MOD_OPT= @d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ +MOD_SEP= S,:, ,g + +all: modvar modvarloop modsysv emptyvar undefvar +all: mod-quote +all: mod-break-many-words + +# See also sysv.mk. +modsysv: + @echo "The answer is ${libfoo.a:L:libfoo.a=42}" + +# Demonstrates modifiers that are given indirectly from a variable. +modvar: + @echo "path='${path}'" + @echo "path='${path:${MOD_NODOT}}'" + @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" + @echo "path=${path:${MOD_NODOTX}:ts:}" + @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" + +.for d in ${path:${MOD_SEP}:N.} /usr/xbin +path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ +paths+= ${d:${MOD_OPT}:${MOD_HOMES}} +.endfor + +modvarloop: + @echo "path_/usr/xbin=${path_/usr/xbin}" + @echo "paths=${paths}" + @echo "PATHS=${paths:tu}" + +# When a modifier is applied to the "" variable, the result is discarded. +emptyvar: + @echo S:${:S,^$,empty,} + @echo C:${:C,^$,empty,} + @echo @:${:@var@${var}@} + +# The :U modifier turns even the "" variable into something that has a value. +# The resulting variable is empty, but is still considered to contain a +# single empty word. This word can be accessed by the :S and :C modifiers, +# but not by the :@ modifier since it explicitly skips empty words. +undefvar: + @echo S:${:U:S,^$,empty,} + @echo C:${:U:C,^$,empty,} + @echo @:${:U:@var@empty@} + + +mod-quote: + @echo $@: new${.newline:Q}${.newline:Q}line + +# Cover the bmake_realloc in brk_string. +mod-break-many-words: + @echo $@: ${UNDEF:U:range=500:[#]} + +# To apply a modifier indirectly via another variable, the whole +# modifier must be put into a single variable. +.if ${value:L:${:US}${:U,value,replacement,}} != "S,value,replacement,}" +. warning unexpected +.endif + +# Adding another level of indirection (the 2 nested :U expressions) helps. +.if ${value:L:${:U${:US}${:U,value,replacement,}}} != "replacement" +. warning unexpected +.endif + +# Multiple indirect modifiers can be applied one after another as long as +# they are separated with colons. +.if ${value:L:${:US,a,A,}:${:US,e,E,}} != "vAluE" +. warning unexpected +.endif + +# An indirect variable that evaluates to the empty string is allowed though. +# This makes it possible to define conditional modifiers, like this: +# +# M.little-endian= S,1234,4321, +# M.big-endian= # none +.if ${value:L:${:Dempty}S,a,A,} != "vAlue" +. warning unexpected +.endif + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/modmisc.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/modts.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modts.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modts.mk (revision 367461) @@ -0,0 +1,48 @@ +# $NetBSD: modts.mk,v 1.7 2020/10/24 08:50:17 rillig Exp $ + +LIST= one two three +LIST+= four five six + +FU_mod-ts= a / b / cool + +AAA= a a a +B.aaa= Baaa + +all: mod-ts mod-ts-space + +# Use print or printf iff they are builtin. +# XXX note that this causes problems, when make decides +# there is no need to use a shell, so avoid where possible. +.if ${(type print) 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= print -r -- +.elif ${(type printf) 2> /dev/null || echo:L:sh:Mbuiltin} != "" +PRINT= printf '%s\n' +.else +PRINT= echo +.endif + +mod-ts: + @${PRINT} 'LIST:tx="${LIST:tx}"' + @${PRINT} 'LIST:ts/x:tu="${LIST:ts\X:tu}"' + @${PRINT} 'FU_$@="${FU_${@:ts}:ts}"' + @${PRINT} 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?' + @${PRINT} 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?' + +mod-ts-space: + # After the :ts modifier, the whole string is interpreted as a single + # word since all spaces have been replaced with x. + @${PRINT} ':ts :S => '${aa bb aa bb aa bb:L:tsx:S,b,B,:Q} + + # The :ts modifier also applies to word separators that are added + # afterwards. + @${PRINT} ':ts :S space => '${a ababa c:L:tsx:S,b, ,g:Q} + @${PRINT} ':ts :S space :M => '${a ababa c:L:tsx:S,b, ,g:M*:Q} + + # Not all modifiers behave this way though. Some of them always use + # a space as word separator instead of the :ts separator. + # This seems like an oversight during implementation. + @${PRINT} ':ts :S => '${a ababa c:L:tsx:S,b, ,g:Q} + @${PRINT} ':ts :S :@ => '${a ababa c:L:tsx:S,b, ,g:@v@${v}@:Q} + + # A final :M* modifier applies the :ts separator again, though. + @${PRINT} ':ts :S :@ :M => '${a ababa c:L:tsx:S,b, ,g:@v@${v}@:M*:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/modts.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/modword.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modword.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modword.exp (revision 367461) @@ -0,0 +1,124 @@ +make: Bad modifier `:[]' for LIST +LIST:[]="" is an error +LIST:[0]="one two three four five six" +LIST:[0x0]="one two three four five six" +LIST:[000]="one two three four five six" +LIST:[*]="one two three four five six" +LIST:[@]="one two three four five six" +LIST:[0]:C/ /,/="one,two three four five six" +LIST:[0]:C/ /,/g="one,two,three,four,five,six" +LIST:[0]:C/ /,/1g="one,two,three,four,five,six" +LIST:[*]:C/ /,/="one,two three four five six" +LIST:[*]:C/ /,/g="one,two,three,four,five,six" +LIST:[*]:C/ /,/1g="one,two,three,four,five,six" +LIST:[@]:C/ /,/="one two three four five six" +LIST:[@]:C/ /,/g="one two three four five six" +LIST:[@]:C/ /,/1g="one two three four five six" +LIST:[@]:[0]:C/ /,/="one,two three four five six" +LIST:[0]:[@]:C/ /,/="one two three four five six" +LIST:[@]:[*]:C/ /,/="one,two three four five six" +LIST:[*]:[@]:C/ /,/="one two three four five six" +EMPTY="" +EMPTY:[#]="1" == 1 ? +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[#]="1" == 1 ? +REALLYSPACE=" " +REALLYSPACE:[#]="1" == 1 ? +LIST:[#]="6" +LIST:[0]:[#]="1" == 1 ? +LIST:[*]:[#]="1" == 1 ? +LIST:[@]:[#]="6" +LIST:[1]:[#]="1" +LIST:[1..3]:[#]="3" +EMPTY:[1]="" +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[1]="\ " +REALLYSPACE=" " +REALLYSPACE:[1]="" == "" ? +REALLYSPACE:[*]:[1]=" " == " " ? +LIST:[1]="one" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1].' for LIST +LIST:[1].="}" is an error +LIST:[2]="two" +LIST:[6]="six" +LIST:[7]="" +LIST:[999]="" +make: Bad modifier `:[-]' for LIST +LIST:[-]="" is an error +make: Bad modifier `:[--]' for LIST +LIST:[--]="" is an error +LIST:[-1]="six" +LIST:[-2]="five" +LIST:[-6]="one" +LIST:[-7]="" +LIST:[-999]="" +LONGLIST:[17]="17" +LONGLIST:[0x11]="17" +LONGLIST:[021]="17" +LIST:[0]:[1]="one two three four five six" +LIST:[*]:[1]="one two three four five six" +LIST:[@]:[1]="one" +LIST:[0]:[2]="" +LIST:[*]:[2]="" +LIST:[@]:[2]="two" +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 +LIST:[1.]="" is an error +make: Bad modifier `:[1..]' for LIST +LIST:[1..]="" is an error +LIST:[1..1]="one" +make: Bad modifier `:[1..1.]' for 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 +LIST:[0..1]="" is an error +make: Bad modifier `:[-1..0]' for 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" +LIST:[3..99]="three four five six" +LIST:[-3..-99]="four three two one" +LIST:[-99..-3]="one two three four" +HASH="#" == "#" ? +LIST:[${HASH}]="6" +LIST:[${ZERO}]="one two three four five six" +LIST:[${ZERO}x${ONE}]="one" +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 +LIST:[${EMPTY}]="" is an error +LIST:[${LONGLIST:[21]:S/2//}]="one" +LIST:[${LIST:[#]}]="six" +LIST:[${LIST:[${HASH}]}]="six" +LIST:[ -1.. +3]="six five four three" +LIST:S/ /,/="one two three four five six" +LIST:S/ /,/W="one,two three four five six" +LIST:S/ /,/gW="one,two,three,four,five,six" +EMPTY:S/^/,/="," +EMPTY:S/^/,/W="," +LIST:C/ /,/="one two three four five six" +LIST:C/ /,/W="one,two three four five six" +LIST:C/ /,/gW="one,two,three,four,five,six" +EMPTY:C/^/,/="," +EMPTY:C/^/,/W="," +LIST:tW="one two three four five six" +LIST:tw="one two three four five six" +LIST:tW:C/ /,/="one,two three four five six" +LIST:tW:C/ /,/g="one,two,three,four,five,six" +LIST:tW:C/ /,/1g="one,two,three,four,five,six" +LIST:tw:C/ /,/="one two three four five six" +LIST:tw:C/ /,/g="one two three four five six" +LIST:tw:C/ /,/1g="one two three four five six" +LIST:tw:tW:C/ /,/="one,two three four five six" +LIST:tW:tw:C/ /,/="one two three four five six" +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/modword.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modword.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modword.mk (revision 367461) @@ -0,0 +1,159 @@ +# $NetBSD: modword.mk,v 1.4 2020/11/01 13:55:31 rillig Exp $ +# +# Test behaviour of new :[] modifier + +all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw + +LIST= one two three +LIST+= four five six +LONGLIST= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + +EMPTY= # the space should be ignored +ESCAPEDSPACE= \ # escaped space before the '#' +REALLYSPACE:= ${EMPTY:C/^/ /W} +HASH= \# +AT= @ +STAR= * +ZERO= 0 +ONE= 1 +MINUSONE= -1 + +mod-squarebrackets: mod-squarebrackets-0-star-at \ + mod-squarebrackets-hash \ + mod-squarebrackets-n \ + mod-squarebrackets-start-end \ + mod-squarebrackets-nested \ + mod-squarebrackets-space + +mod-squarebrackets-0-star-at: + @echo 'LIST:[]="${LIST:[]}" is an error' + @echo 'LIST:[0]="${LIST:[0]}"' + @echo 'LIST:[0x0]="${LIST:[0x0]}"' + @echo 'LIST:[000]="${LIST:[000]}"' + @echo 'LIST:[*]="${LIST:[*]}"' + @echo 'LIST:[@]="${LIST:[@]}"' + @echo 'LIST:[0]:C/ /,/="${LIST:[0]:C/ /,/}"' + @echo 'LIST:[0]:C/ /,/g="${LIST:[0]:C/ /,/g}"' + @echo 'LIST:[0]:C/ /,/1g="${LIST:[0]:C/ /,/1g}"' + @echo 'LIST:[*]:C/ /,/="${LIST:[*]:C/ /,/}"' + @echo 'LIST:[*]:C/ /,/g="${LIST:[*]:C/ /,/g}"' + @echo 'LIST:[*]:C/ /,/1g="${LIST:[*]:C/ /,/1g}"' + @echo 'LIST:[@]:C/ /,/="${LIST:[@]:C/ /,/}"' + @echo 'LIST:[@]:C/ /,/g="${LIST:[@]:C/ /,/g}"' + @echo 'LIST:[@]:C/ /,/1g="${LIST:[@]:C/ /,/1g}"' + @echo 'LIST:[@]:[0]:C/ /,/="${LIST:[@]:[0]:C/ /,/}"' + @echo 'LIST:[0]:[@]:C/ /,/="${LIST:[0]:[@]:C/ /,/}"' + @echo 'LIST:[@]:[*]:C/ /,/="${LIST:[@]:[*]:C/ /,/}"' + @echo 'LIST:[*]:[@]:C/ /,/="${LIST:[*]:[@]:C/ /,/}"' + +mod-squarebrackets-hash: + @echo 'EMPTY="${EMPTY}"' + @echo 'EMPTY:[#]="${EMPTY:[#]}" == 1 ?' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[#]="${ESCAPEDSPACE:[#]}" == 1 ?' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[#]="${REALLYSPACE:[#]}" == 1 ?' + @echo 'LIST:[#]="${LIST:[#]}"' + @echo 'LIST:[0]:[#]="${LIST:[0]:[#]}" == 1 ?' + @echo 'LIST:[*]:[#]="${LIST:[*]:[#]}" == 1 ?' + @echo 'LIST:[@]:[#]="${LIST:[@]:[#]}"' + @echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"' + @echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"' + +mod-squarebrackets-n: + @echo 'EMPTY:[1]="${EMPTY:[1]}"' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?' + @echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?' + @echo 'LIST:[1]="${LIST:[1]}"' + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1].="${LIST:[1].}" is an error' + @echo 'LIST:[2]="${LIST:[2]}"' + @echo 'LIST:[6]="${LIST:[6]}"' + @echo 'LIST:[7]="${LIST:[7]}"' + @echo 'LIST:[999]="${LIST:[999]}"' + @echo 'LIST:[-]="${LIST:[-]}" is an error' + @echo 'LIST:[--]="${LIST:[--]}" is an error' + @echo 'LIST:[-1]="${LIST:[-1]}"' + @echo 'LIST:[-2]="${LIST:[-2]}"' + @echo 'LIST:[-6]="${LIST:[-6]}"' + @echo 'LIST:[-7]="${LIST:[-7]}"' + @echo 'LIST:[-999]="${LIST:[-999]}"' + @echo 'LONGLIST:[17]="${LONGLIST:[17]}"' + @echo 'LONGLIST:[0x11]="${LONGLIST:[0x11]}"' + @echo 'LONGLIST:[021]="${LONGLIST:[021]}"' + @echo 'LIST:[0]:[1]="${LIST:[0]:[1]}"' + @echo 'LIST:[*]:[1]="${LIST:[*]:[1]}"' + @echo 'LIST:[@]:[1]="${LIST:[@]:[1]}"' + @echo 'LIST:[0]:[2]="${LIST:[0]:[2]}"' + @echo 'LIST:[*]:[2]="${LIST:[*]:[2]}"' + @echo 'LIST:[@]:[2]="${LIST:[@]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[2]="${LIST:[*]:C/ /,/:[2]}"' + @echo 'LIST:[*]:C/ /,/:[*]:[2]="${LIST:[*]:C/ /,/:[*]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"' + @echo 'LONGLIST:[012..0x12]="${LONGLIST:[012..0x12]}"' + +mod-squarebrackets-start-end: + @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]}"' + @echo 'LIST:[2..1]="${LIST:[2..1]}"' + @echo 'LIST:[3..-2]="${LIST:[3..-2]}"' + @echo 'LIST:[-4..4]="${LIST:[-4..4]}"' + @echo 'LIST:[0..1]="${LIST:[0..1]}" is an error' + @echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error' + @echo 'LIST:[-1..1]="${LIST:[-1..1]}"' + @echo 'LIST:[0..0]="${LIST:[0..0]}"' + @echo 'LIST:[3..99]="${LIST:[3..99]}"' + @echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"' + @echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"' + +mod-squarebrackets-nested: + @echo 'HASH="${HASH}" == "#" ?' + @echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"' + @echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"' + @echo 'LIST:[$${ZERO}x$${ONE}]="${LIST:[${ZERO}x${ONE}]}"' + @echo 'LIST:[$${ONE}]="${LIST:[${ONE}]}"' + @echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"' + @echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"' + @echo 'LIST:[$${AT}]="${LIST:[${AT}]}"' + @echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error' + @echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"' + @echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"' + @echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"' + +mod-squarebrackets-space: + # As of 2020-11-01, it is possible to have spaces before the numbers + # but not after them. This is an unintended side-effect of using + # strtol for parsing the numbers. + @echo 'LIST:[ -1.. +3]="${LIST:[ -1.. +3]}"' + +mod-C-W: + @echo 'LIST:C/ /,/="${LIST:C/ /,/}"' + @echo 'LIST:C/ /,/W="${LIST:C/ /,/W}"' + @echo 'LIST:C/ /,/gW="${LIST:C/ /,/gW}"' + @echo 'EMPTY:C/^/,/="${EMPTY:C/^/,/}"' + @echo 'EMPTY:C/^/,/W="${EMPTY:C/^/,/W}"' + +mod-S-W: + @echo 'LIST:S/ /,/="${LIST:S/ /,/}"' + @echo 'LIST:S/ /,/W="${LIST:S/ /,/W}"' + @echo 'LIST:S/ /,/gW="${LIST:S/ /,/gW}"' + @echo 'EMPTY:S/^/,/="${EMPTY:S/^/,/}"' + @echo 'EMPTY:S/^/,/W="${EMPTY:S/^/,/W}"' + +mod-tW-tw: + @echo 'LIST:tW="${LIST:tW}"' + @echo 'LIST:tw="${LIST:tw}"' + @echo 'LIST:tW:C/ /,/="${LIST:tW:C/ /,/}"' + @echo 'LIST:tW:C/ /,/g="${LIST:tW:C/ /,/g}"' + @echo 'LIST:tW:C/ /,/1g="${LIST:tW:C/ /,/1g}"' + @echo 'LIST:tw:C/ /,/="${LIST:tw:C/ /,/}"' + @echo 'LIST:tw:C/ /,/g="${LIST:tw:C/ /,/g}"' + @echo 'LIST:tw:C/ /,/1g="${LIST:tw:C/ /,/1g}"' + @echo 'LIST:tw:tW:C/ /,/="${LIST:tw:tW:C/ /,/}"' + @echo 'LIST:tW:tw:C/ /,/="${LIST:tW:tw:C/ /,/}"' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/modword.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: opt-debug-all.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dA command line option, which enables all debug options +# except for -dL (lint), since that option is not related to debug logging +# but to static analysis. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-all.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-archive.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -da command line option, which adds debug logging for the +# archive handling. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-archive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: opt-debug-cond.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dc command line option, which adds debug logging for the +# evaluation of conditional expressions, such as in .if directives and +# ${cond:?then:else} expressions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-cond.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-debug-curdir.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dC command line option, which does nothing, as of 2020-09-05. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-curdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-dir.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dd command line option, which adds debug logging for +# directory searching and caching. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-dir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.exp (revision 367461) @@ -0,0 +1,34 @@ +echo '3 spaces'; false +3 spaces + +*** Failed target: fail-spaces +*** Failed command: echo '3 spaces'; false +*** Error code 1 (continuing) +echo \ indented; false + indented + +*** Failed target: fail-escaped-space +*** Failed command: echo \ indented; false +*** Error code 1 (continuing) +echo 'line1 +line2'; false +line1 +line2 + +*** Failed target: fail-newline +*** Failed command: echo 'line1 line2'; false +*** Error code 1 (continuing) +echo 'line1 line2'; false +line1 line2 + +*** Failed target: fail-multiline +*** Failed command: echo 'line1 line2'; false +*** Error code 1 (continuing) +echo 'word1' 'word2'; false +word1 word2 + +*** Failed target: fail-multiline-intention +*** Failed command: echo 'word1' 'word2'; false +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.mk (revision 367461) @@ -0,0 +1,42 @@ +# $NetBSD: opt-debug-errors.mk,v 1.2 2020/09/06 04:35:03 rillig Exp $ +# +# Tests for the -de command line option, which adds debug logging for +# failed commands and targets. + +.MAKEFLAGS: -de + +all: fail-spaces +all: fail-escaped-space +all: fail-newline +all: fail-multiline +all: fail-multiline-intention + +# XXX: The debug output folds the spaces, showing '3 spaces' instead of +# the correct '3 spaces'. +fail-spaces: + echo '3 spaces'; false + +# XXX: The debug output folds the spaces, showing 'echo \ indented' instead +# of the correct 'echo \ indented'. +fail-escaped-space: + echo \ indented; false + +# XXX: A newline is turned into an ordinary space in the debug log. +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. Having these spaces collapsed makes sense to show the command +# in its condensed form. +# +fail-multiline-intention: + echo 'word1' \ + 'word2'; false Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-errors.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.mk (revision 367461) @@ -0,0 +1,37 @@ +# $NetBSD: opt-debug-file.mk,v 1.4 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the -dF command line option, which redirects the debug log +# to a file instead of writing it to stderr. + +# Enable debug logging for variable assignments and evaluation (-dv) +# and redirect the debug logging to the given file. +.MAKEFLAGS: -dvFopt-debug-file.debuglog + +# This output goes to the debug log file. +VAR= value ${:Uexpanded} + +# Hide the logging output for the remaining actions. +# As of 2020-10-03, it is not possible to disable debug logging again. +.MAKEFLAGS: -dF/dev/null + +# Make sure that the debug logging file contains some logging. +DEBUG_OUTPUT:= ${:!cat opt-debug-file.debuglog!} +# Grmbl. Because of the := operator in the above line, the variable +# value contains ${:Uexpanded}. This variable expression is expanded +# upon further processing. Therefore, don't read from untrusted input. +#.MAKEFLAGS: -dc -dFstderr +.if !${DEBUG_OUTPUT:tW:M*VAR = value expanded*} +. error ${DEBUG_OUTPUT} +.endif + +# To get the unexpanded text that was actually written to the debug log +# file, the content of that log file must not be stored in a variable. +# XXX: In the :M modifier, a dollar is escaped as '$$', not '\$'. +.if !${:!cat opt-debug-file.debuglog!:tW:M*VAR = value $${:Uexpanded}*} +. error +.endif + +_!= rm opt-debug-file.debuglog + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-file.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.exp (revision 367461) @@ -0,0 +1,22 @@ +For: new loop 2 +For: end for 2 +For: end for 1 +For: loop body: +. for inner in 1 2 +VAR.${:Ua}${inner}= value +. endfor +For: end for 1 +For: loop body: +VAR.${:Ua}${:U1}= value +For: loop body: +VAR.${:Ua}${:U2}= value +For: loop body: +. for inner in 1 2 +VAR.${:Ub}${inner}= value +. endfor +For: end for 1 +For: loop body: +VAR.${:Ub}${:U1}= value +For: loop body: +VAR.${:Ub}${:U2}= value +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.mk (revision 367461) @@ -0,0 +1,26 @@ +# $NetBSD: opt-debug-for.mk,v 1.4 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the -df command line option, which adds debug logging for +# parsing and evaluating .for loops. + +.MAKEFLAGS: -df + +# XXX: In the debug log, the "new loop 2" appears out of context. +# There should be a "begin loop 1" before, and all these messages should +# contain line number information. +# +# XXX: The "loop body" should print the nesting level as well. +# +# XXX: It is hard to extract any information from the debug log since +# the "begin" and "end" events are not balanced and the nesting level +# is not printed consistently. It would also be helpful to mention the +# actual substitutions, such as "For 1: outer=b". +# +.for outer in a b +. for inner in 1 2 +VAR.${outer}${inner}= value +. endfor +.endfor + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-for.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.exp (revision 367461) @@ -0,0 +1,17 @@ +#*** Input graph: +# all, made UNMADE, type OP_DEPENDS|OP_HAS_COMMANDS, flags none +# made-target, made UNMADE, type OP_DEPENDS, flags none +# made-target-no-sources, made UNMADE, type OP_DEPENDS, flags none +# made-source, made UNMADE, type OP_DEPENDS, flags none +# unmade-target, made UNMADE, type OP_DEPENDS, flags none +# unmade-sources, made UNMADE, type none, flags none +# unmade-silent-source, made UNMADE, type OP_SILENT, flags none +# unmade-target-no-sources, made UNMADE, type OP_DEPENDS, flags none + + +# +# Files that are only sources: +# unmade-sources [unmade-sources] +# unmade-silent-source [unmade-silent-source] .SILENT +#*** Transformations: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.mk (revision 367461) @@ -0,0 +1,23 @@ +# $NetBSD: opt-debug-graph1.mk,v 1.3 2020/09/05 06:46:12 rillig Exp $ +# +# Tests for the -dg1 command line option, which prints the input +# graph before making anything. + +.MAKEFLAGS: -dg1 + +all: made-target made-target-no-sources + +made-target: made-source + +made-source: + +made-target-no-sources: + +unmade-target: unmade-sources unmade-silent-source + +.SILENT: unmade-silent-source + +unmade-target-no-sources: + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph1.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-graph2.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dg2 command line option, which prints the input +# graph after making everything, or before exiting on error. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph2.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-graph3.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dg3 command line option, which prints the input +# graph before exiting on error. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-graph3.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: opt-debug-hash.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dh command line option, which adds debug logging for +# hash tables. Even more detailed logging is available by compiling +# make with -DDEBUG_HASH_LOOKUP. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-hash.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.exp (revision 367461) @@ -0,0 +1,25 @@ +job_pipe -1 -1, maxjobs 1, tokens 1, compat 0 +Job_TokenWithdraw(): aborting 0, running 0 +() withdrew token +echo ": expanded expression" +{ : expanded expression +} || exit $? +echo ": variable" +{ : variable +} || exit $? +echo ": 'single' and \"double\" quotes" +{ : 'single' and "double" quotes +} || exit $? +Running all locally + Command: sh +JobExec(all): pid added to jobs table +job table @ job started +job 0, status 3, flags 0, pid +: expanded expression +: variable +: 'single' and "double" quotes +Process exited/stopped status 0. +JobFinish: [all], status 0 +Job_TokenWithdraw(): aborting 0, running 0 +() withdrew token +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.mk (revision 367461) @@ -0,0 +1,26 @@ +# $NetBSD: opt-debug-jobs.mk,v 1.4 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the -dj command line option, which adds debug logging about +# running jobs in multiple shells. + +.MAKEFLAGS: -dj + +# Run in parallel mode since the debug logging is more interesting there +# than in compat mode. +.MAKEFLAGS: -j1 + +all: + # Only the actual command is logged. + # To see the evaluation of the variable expressions, use -dv. + : ${:Uexpanded} expression + + # Undefined variables expand to empty strings. + # Multiple spaces are preserved in the command, as they might be + # significant. + : ${UNDEF} variable + + # In the debug output, single quotes are not escaped, even though + # the whole command is enclosed in single quotes as well. + # This allows to copy and paste the whole command, without having + # to unescape anything. + : 'single' and "double" quotes Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.exp (revision 367461) @@ -0,0 +1,9 @@ +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 67: Missing delimiter ':' after indirect modifier "${:UL}" +make: Unknown modifier '$' +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.mk (revision 367461) @@ -0,0 +1,72 @@ +# $NetBSD: opt-debug-lint.mk,v 1.11 2020/10/24 08:50:17 rillig Exp $ +# +# Tests for the -dL command line option, which runs additional checks +# to catch common mistakes, such as unclosed variable expressions. + +.MAKEFLAGS: -dL + +# Since 2020-09-13, undefined variables that are used on the left-hand side +# of a condition at parse time get a proper error message. Before, the +# error message was "Malformed conditional" only, which was wrong and +# misleading. The form of the condition is totally fine, it's the evaluation +# that fails. +# +# Since 2020-09-13, the "Malformed conditional" error message is not printed +# anymore. +# +# See also: +# cond-undef-lint.mk +.if $X +. error +.endif + +# The dynamic variables like .TARGET are treated specially. It does not make +# sense to expand them in the global scope since they will never be defined +# there under normal circumstances. Therefore they expand to a string that +# will later be expanded correctly, when the variable is evaluated again in +# the scope of an actual target. +# +# Even though the "@" variable is not defined at this point, this is not an +# error. In all practical cases, this is no problem. This particular test +# case is made up and unrealistic. +.if $@ != "\$(.TARGET)" +. error +.endif + +# Since 2020-09-13, Var_Parse properly reports errors for undefined variables, +# but only in lint mode. Before, it had only silently returned var_Error, +# hoping for the caller to print an error message. This resulted in the +# well-known "Malformed conditional" error message, even though the +# conditional was well-formed and the only error was an undefined variable. +.if ${UNDEF} +. error +.endif + +# Since 2020-09-14, dependency lines may contain undefined variables. +# Before, undefined variables were forbidden, but this distinction was not +# observable from the outside of the function Var_Parse. +${UNDEF}: ${UNDEF} + +# In a condition that has a defined(UNDEF) guard, all guarded conditions +# may assume that the variable is defined since they will only be evaluated +# if the variable is indeed defined. Otherwise they are only parsed, and +# for parsing it doesn't make a difference whether the variable is defined +# or not. +.if defined(UNDEF) && exists(${UNDEF}) +. error +.endif + +# Since 2020-10-03, in lint mode the variable modifier must be separated +# by colons. See varparse-mod.mk. +.if ${value:LPL} != "value" +. error +.endif + +# Since 2020-10-03, in lint mode the variable modifier must be separated +# by colons. See varparse-mod.mk. +.if ${value:${:UL}PL} != "LPL}" # FIXME: "LPL}" is unexpected here. +. error ${value:${:UL}PL} +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-lint.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.exp (revision 367461) @@ -0,0 +1,3 @@ +echo all-word +all-word +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.mk (revision 367461) @@ -0,0 +1,22 @@ +# $NetBSD: opt-debug-loud.mk,v 1.4 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the -dl command line option, which prints the commands before +# running them, ignoring the command line option for silent mode (-s) as +# well as the .SILENT special source and target, as well as the '@' prefix +# for shell commands. + +.MAKEFLAGS: -dl -s +.SILENT: + +# The -dl command line option does not affect commands that are run during +# variable expansion, such as :!cmd! or :sh. +.if ${:!echo word!} != "word" +. error +.endif + +all: .SILENT + # Even though the command line option -s is given, .SILENT is set + # for all targets and for this target in particular, the command + # is still printed. The -dl debugging option is stronger than all + # of these. + @echo all-word Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-loud.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-making.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dm command line option, which adds debug logging about +# making targets, including modification dates. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-making.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-meta.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dM command line option, which adds debug logging about +# "meta" mode decisions about targets. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-meta.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.mk (revision 367461) @@ -0,0 +1,13 @@ +# $NetBSD: opt-debug-no-rm.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dn command line option, which prevents the temporary +# command scripts from being removed from the temporary directory. + +# TODO: Implementation + +# TODO: Does this apply to non-jobs mode? +# TODO: Does this apply to jobs mode? +# TODO: Are the generated filenames predictable? + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-no-rm.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-parse.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dp command line option, which adds debug logging about +# makefile parsing. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-parse.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: opt-debug-suff.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -ds command line option, which adds debug logging about +# suffix-transformation rules such as .c.o. + +# TODO: Implementation + +# TODO: What about %.o: %.c? + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-suff.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: opt-debug-targets.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dt command line option, which adds debug logging about +# target list maintenance. +# +# TODO: What exactly does "maintenance" mean? + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-targets.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: opt-debug-var.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dv command line option, which adds debug logging about +# variable assignment and evaluation. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-var.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: opt-debug-varraw.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dV command line option, which forces the -V option to +# print the raw values of variables. + +# TODO: Does this make -V and -v equivalent, or are there any other subtle +# differences? + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-varraw.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: opt-debug-x-trace.mk,v 1.1 2020/09/05 06:20:51 rillig Exp $ +# +# Tests for the -dx command line option, which runs shell commands with +# the -x option, thereby printing the actual commands as they are +# executed. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug-x-trace.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.exp (revision 367461) @@ -0,0 +1,4 @@ +Global:VAR = value +Global:.MAKEFLAGS = -r -k -d v -d +Global:.MAKEFLAGS = -r -k -d v -d 0 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.mk (revision 367461) @@ -0,0 +1,14 @@ +# $NetBSD: opt-debug.mk,v 1.5 2020/10/05 19:27:48 rillig Exp $ +# +# Tests for the -d command line option, which controls debug logging. + +# Enable debug logging for the variables (var.c). +.MAKEFLAGS: -dv + +VAR= value + +# Disable all debug logging again. +.MAKEFLAGS: -d0 # -d0 is available since 2020-10-03 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-debug.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.exp (revision 367461) @@ -0,0 +1,12 @@ +dependency 1 +*** Error code 1 (ignored) +dependency 2 +*** Error code 7 (ignored) +dependency 3 +other 1 +*** Error code 1 (ignored) +other 2 +main 1 +*** Error code 1 (ignored) +main 2 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.mk (revision 367461) @@ -0,0 +1,32 @@ +# $NetBSD: opt-ignore.mk,v 1.4 2020/10/18 18:12:42 rillig Exp $ +# +# Tests for the -i command line option, which ignores the exit status of the +# shell commands, and just continues with the next command, even from the same +# target. +# +# Is there a situation in which this option is useful? +# +# Why are the "Error code" lines all collected at the bottom of the output +# file, where they cannot be related to the individual shell commands that +# failed? + +.MAKEFLAGS: -d0 # switch stdout to being line-buffered + +all: dependency other + +dependency: + @echo dependency 1 + @false + @echo dependency 2 + @:; exit 7 + @echo dependency 3 + +other: + @echo other 1 + @false + @echo other 2 + +all: + @echo main 1 + @false + @echo main 2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-ignore.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.exp (revision 367461) @@ -0,0 +1,6 @@ +dependency 1 +*** Error code 1 (continuing) +other 1 +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.mk (revision 367461) @@ -0,0 +1,26 @@ +# $NetBSD: opt-keep-going.mk,v 1.4 2020/10/18 18:12:42 rillig Exp $ +# +# Tests for the -k command line option, which stops building a target as soon +# as an error is detected, but continues building the other, independent +# targets, as far as possible. + +.MAKEFLAGS: -d0 # switch stdout to being line-buffered + +all: dependency other + +dependency: + @echo dependency 1 + @false + @echo dependency 2 + @:; exit 7 + @echo dependency 3 + +other: + @echo other 1 + @false + @echo other 2 + +all: + @echo main 1 + @false + @echo main 2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-keep-going.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/parse-var.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/parse-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/parse-var.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/parse-var.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/parse-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/parse-var.mk (revision 367461) @@ -0,0 +1,13 @@ +# $NetBSD: parse-var.mk,v 1.1 2020/10/04 06:53:15 rillig Exp $ + +.MAKEFLAGS: -dL + +# In variable assignments, there may be spaces on the left-hand side of the +# assignment, but only if they occur inside variable expressions. +VAR.${:U param }= value +.if ${VAR.${:U param }} != "value" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/parse-var.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/phony-end.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/phony-end.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/phony-end.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: phony-end.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +all ok also.ok bug phony: + @echo '${.TARGET .PREFIX .IMPSRC:L:@v@$v="${$v}"@}' + +.END: ok also.ok bug + +phony bug: .PHONY +all: phony Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/phony-end.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/posix.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/posix.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/posix.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: posix.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +all: x plus subs err + +x: + @echo "Posix says we should execute the command as if run by system(3)" + @echo "Expect 'Hello,' and 'World!'" + @echo Hello,; false; echo "World!" + +plus: + @echo a command + +@echo "a command prefixed by '+' executes even with -n" + @echo another command + +subs: + @echo make -n + @${.MAKE} -f ${MAKEFILE} -n plus + @echo make -n -j1 + @${.MAKE} -f ${MAKEFILE} -n -j1 plus + +err: + @(echo Now we expect an error...; exit 1) + @echo "Oops! you shouldn't see this!" + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/posix.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/posix1.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/posix1.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/posix1.mk (revision 367461) @@ -0,0 +1,186 @@ +# $NetBSD: posix1.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ + +# Keep the default suffixes from interfering, just in case. +.SUFFIXES: + +all: line-continuations suffix-substitution localvars + +# we need to clean for repeatable results +.BEGIN: clean +clean: + @rm -f lib.a dir/* dummy obj* +.END: + @rm -f lib.a dir/* dummy obj* + +# +# Line continuations +# + +# Escaped newlines and leading whitespace from the next line are replaced +# with single space, except in commands, where the escape and the newline +# are retained, but a single leading tab (if any) from the next line is +# removed. (PR 49085) +# Expect: +# ${VAR} = "foo bar baz" +# a +# b +# c +VAR = foo\ +\ + bar\ + baz + +line-continuations: + @echo '$${VAR} = "${VAR}"' + @echo 'aXbXc' | sed -e 's/X/\ + /g' + + +# +# Suffix substitution +# + +# The only variable modifier accepted by POSIX. +# ${VAR:s1=s2}: replace s1, if found, with s2 at end of each word in +# ${VAR}. s1 and s2 may contain macro expansions. +# Expect: foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd +suffix-substitution: + @echo '${VAR:r=R}, ${VAR:foo=}, ${VAR:not_there=wrong}, ${VAR:=add}' + + +# +# Local variables: regular forms, D/F forms and suffix substitution. +# + +# In the past substitutions did not work with the D/F forms and those +# forms were not available for $?. (PR 49085) + +ARFLAGS= -rcv + +localvars: lib.a + +# $@ = target or archive name $< = implied source +# $* = target without suffix $? = sources newer than target +# $% = archive member name +LOCALS= \ + "Local variables\n\ + \$${@}=\"${@}\" \$${<}=\"${<}\"\n\ + \$${*}=\"${*}\" \$${?}=\"${?}\"\n\ + \$${%%}=\"${%}\"\n\n" + +# $XD = directory part of X $XF = file part of X +# X is one of the local variables. +LOCAL_ALTERNATIVES= \ + "Directory and filename parts of local variables\n\ + \$${@D}=\"${@D}\" \$${@F}=\"${@F}\"\n\ + \$${'${@}' + +dir/obj_1.h obj_2.h obj3.h dummy dir/dummy: + mkdir -p '${@D}' + touch '${@}' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/posix1.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/qequals.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/qequals.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/qequals.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: qequals.mk,v 1.3 2020/10/24 08:50:17 rillig Exp $ + +M= i386 +V.i386= OK +V.$M?= bug + +all: + @echo 'V.$M ?= ${V.$M}' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/qequals.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/recursive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/recursive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/recursive.mk (revision 367461) @@ -0,0 +1,37 @@ +# $NetBSD: recursive.mk,v 1.3 2020/10/24 08:50:17 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. +# +# Seen in pkgsrc/x11/libXfixes, and probably many more package that use +# GNU Automake. + +AM_V_lt= ${am__v_lt_${V}} +am__v_lt_= ${am__v_lt_${AM_DEFAULT_VERBOSITY}} +am__v_lt_0= --silent +am__v_lt_1= + +# On 2020-08-06, make reported: "Variable am__v_lt_ is recursive." +libXfixes_la_LINK= ... ${AM_V_lt} ... + +# somewhere later ... +AM_DEFAULT_VERBOSITY= 1 + + +# The purpose of the -dL flag is to detect unclosed variables. This +# can be achieved by just parsing the variable and not evaluating it. +# +# When the variable is only parsed but not evaluated, bugs in nested +# variables are not discovered. But these are hard to produce anyway, +# therefore that's acceptable. In most practical cases, the missing +# brace would be detected directly in the line where it is produced. +MISSING_BRACE_INDIRECT:= ${:U\${MISSING_BRACE} +UNCLOSED= $(MISSING_PAREN +UNCLOSED= ${MISSING_BRACE +UNCLOSED= ${MISSING_BRACE_INDIRECT} + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/recursive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.exp (revision 367461) @@ -0,0 +1,22 @@ +first first +hidden hidden +make: exec(...) failed (No such file or directory) +*** Error code 1 (ignored) +hidden delayed hidden +repeated repeated +commented commented +... # Run the below commands later + +*** Error code 127 (ignored) +commented delayed commented +indirect regular +indirect-space regular +... +make: exec(...) failed (No such file or directory) +*** Error code 1 (ignored) +indirect-space deferred +first delayed first +repeated delayed repeated +repeated delayed twice repeated +indirect deferred +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.mk (revision 367461) @@ -0,0 +1,54 @@ +# $NetBSD: sh-dots.mk,v 1.3 2020/10/25 22:04:24 rillig Exp $ +# +# Tests for the special shell command line "...", which does not run the +# commands below it but appends them to the list of commands that are run +# at the end. + +.MAKEFLAGS: -d0 # switch stdout to being line-buffered + +all: first hidden repeated commented indirect indirect-space + +# The ${.TARGET} correctly expands to the target name, even though the +# commands are run separately from the main commands. +first: + @echo first ${.TARGET} + ... + @echo first delayed ${.TARGET} + +# The dots cannot be prefixed by the usual @-+ characters. +# They must be written exactly as dots. +hidden: .IGNORE + @echo hidden ${.TARGET} + @... + @echo hidden delayed ${.TARGET} + +# Since the shell command lines don't recognize '#' as comment character, +# the "..." is not interpreted specially here. +commented: .IGNORE + @echo commented ${.TARGET} + ... # Run the below commands later + @echo commented delayed ${.TARGET} + +# The dots don't have to be written literally, they can also come from a +# variable expression. +indirect: + @echo indirect regular + ${:U...} + @echo indirect deferred + +# If the dots are followed by a space, that space is part of the command and +# thus does not defer the command below it. +indirect-space: .IGNORE + @echo indirect-space regular + ${:U... } + @echo indirect-space deferred + + +# The "..." can appear more than once, even though that doesn't make sense. +# The second "..." is a no-op. +repeated: .IGNORE + @echo repeated ${.TARGET} + ... + @echo repeated delayed ${.TARGET} + ... + @echo repeated delayed twice ${.TARGET} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-dots.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.exp (revision 367461) @@ -0,0 +1,9 @@ +echo normal +normal +hidden +echo always +always +echo ignore errors +ignore errors +They chatted in the sy. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.mk (revision 367461) @@ -0,0 +1,40 @@ +# $NetBSD: shell-csh.mk,v 1.5 2020/10/19 19:14:11 rillig Exp $ +# +# Tests for using a C shell for running the commands. + +CSH!= which csh || true + +# The shell path must be an absolute path. +# This is only obvious in parallel mode since in compat mode, +# simple commands are executed via execve directly. +.if ${CSH} != "" +.SHELL: name="csh" path="${CSH}" +.endif + +# In parallel mode, the commandShell->noPrint command is filtered from +# the output, rather naively (in JobOutput). +# +# Until 2020-10-03, the output in parallel mode was garbled because +# the definition of the csh had been wrong since 1993 at least. +.MAKEFLAGS: -j1 + +all: +.if ${CSH} != "" + # This command is both printed and executed. + echo normal + + # This command is only executed. + @echo hidden + + # This command is both printed and executed. + +echo always + + # This command is both printed and executed. + -echo ignore errors + + # In the C shell, "unset verbose" is set as the noPrint command. + # Therefore it is filtered from the output, rather naively. + @echo 'They chatted in the sunset verbosely.' +.else + @sed '$$d' ${MAKEFILE:.mk=.exp} # This is cheated. +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/shell-csh.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.exp (revision 367461) @@ -0,0 +1,8 @@ +: normal +-c : normal +-c : hidden +: always +-c : always +: ignore errors +-c : ignore errors +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.mk (revision 367461) @@ -0,0 +1,14 @@ +# $NetBSD: shell-custom.mk,v 1.1 2020/10/03 14:39:36 rillig Exp $ +# +# Tests for using a custom shell for running the commands. + +.SHELL: name="sh" path="echo" +# TODO: demonstrate the other shell features as well: +# - error control +# - output control + +all: + : normal + @: hidden + +: always + -: ignore errors Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/shell-custom.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.exp (revision 367461) @@ -0,0 +1,4 @@ +: normal +: always +: ignore errors +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: shell-ksh.mk,v 1.1 2020/10/03 14:39:36 rillig Exp $ +# +# Tests for using a korn shell for running the commands. + +.SHELL: name="ksh" path="ksh" + +all: + : normal + @: hidden + +: always + -: ignore errors Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/shell-ksh.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.exp (revision 367461) @@ -0,0 +1,4 @@ +: normal +: always +: ignore errors +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: shell-sh.mk,v 1.1 2020/10/03 14:39:36 rillig Exp $ +# +# Tests for using a bourne shell for running the commands. +# This is the default shell, so there's nothing surprising. + +.SHELL: name="sh" path="sh" + +all: + : normal + @: hidden + +: always + -: ignore errors Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/shell-sh.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.exp (revision 367461) @@ -0,0 +1,15 @@ +defining transformation from `.c' to `.d' +inserting ".c" (1) at end of list +inserting ".d" (2) at end of list +defining transformation from `.d' to `.e' +inserting ".d" (2) at end of list +inserting ".e" (3) at end of list +: 'Making issue5a.c out of nothing.' +make: don't know how to make issue5a.d (continuing) +make: don't know how to make issue5b.c (continuing) +make: don't know how to make issue5c (continuing) +: 'Making issue5d.d out of nothing.' +make: don't know how to make issue5d.e (continuing) +make: don't know how to make issue5e.d (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.mk (revision 367461) @@ -0,0 +1,34 @@ +# $NetBSD: suff-add-later.mk,v 1.2 2020/10/21 08:18:24 rillig Exp $ +# +# https://gnats.netbsd.org/49086, issue 5: +# Adding more suffixes does not turn existing rules into suffix rules. + +.MAKEFLAGS: -ds + +all: issue5a.d issue5b.c issue5c issue5d.e issue5e.d + +.SUFFIXES: .c + +# At this point, only .c is a suffix, therefore the following are all regular +# rules. +.c.d .d.c .d .d.e .e.d: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +# Adding .d and .e as suffixes should turn the above regular rules into +# suffix rules. +.SUFFIXES: .d .e + +issue5a.c issue5b.d issue5c.d issue5d.d issue5e.e: + : 'Making ${.TARGET} out of nothing.' + +# XXX: As of 2020-10-20, the result is unexpected. +# XXX: .d.c is not a transformation rule but a regular target. +# XXX: .d is not a transformation rule but a regular target. +# XXX: .e.d is not a transformation but a regular target. +# XXX: .c.d is listed as "Files that are only sources". +# XXX: .d.e is listed as "Files that are only sources". +# XXX: The suffixes .c and .e both have the number 2. +# XXX: don't know how to make issue5a.d (even though .c.d is a transformation +# rule and issue5a.c can be readily made) +#.MAKEFLAGS: -dg1 +.MAKEFLAGS: -d0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-add-later.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.exp (revision 367461) @@ -0,0 +1,5 @@ +make: don't know how to make .a (continuing) +make: don't know how to make .a.b (continuing) +make: don't know how to make .b.a (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.mk (revision 367461) @@ -0,0 +1,31 @@ +# $NetBSD: suff-clear-regular.mk,v 1.1 2020/10/20 20:36:53 rillig Exp $ +# +# https://gnats.netbsd.org/49086, issue 4: +# Suffix rules do not become regular rules when .SUFFIXES is cleared. + +all: .a .a.b .b.a + +.SUFFIXES: .a .b .c + +# At this point, .a and .b are known suffixes, therefore the following +# targets are interpreted as transformation rules. +.a .a.b .b.a: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +# The empty .SUFFIXES discards all previous suffixes. +# This means the above rules should be turned into regular targets. +.SUFFIXES: + +# XXX: As of 2020-10-20, the result is unexpected. +# XXX: .a.b is still a transformation rule. +# XXX: .a belongs to "Files that are only sources". +# XXX: .a.b belongs to "Files that are only sources". +# XXX: .b.a belongs to "Files that are only sources". +# XXX: .a is listed in "Transformations". +# XXX: .a.b is listed in "Transformations". +# XXX: .b.a is listed in "Transformations". +# XXX: don't know how to make .a +# XXX: don't know how to make .a.b +# XXX: don't know how to make .b.a +# XXX: exit status 0 +#.MAKEFLAGS: -dg1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-regular.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.exp (revision 367461) @@ -0,0 +1,3 @@ +make: don't know how to make issue3 (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: suff-clear-single.mk,v 1.1 2020/10/20 20:36:53 rillig Exp $ +# +# https://gnats.netbsd.org/49086, issue 3: +# Single suffix rules remain active after .SUFFIXES is cleared. +# +# There's a rule for issue3.a, but .a is no longer a known suffix when +# targets are being made, so issue3 should not get made. + +all: issue3 + +.SUFFIXES: .a .b .c + +.a .a.b .b.a: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +.SUFFIXES: + +issue3.a: + : 'There is a bug if you see this.' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-clear-single.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.exp (revision 367461) @@ -0,0 +1,58 @@ +defining transformation from `.ccc' to `.cc' +inserting ".ccc" (3) at end of list +inserting ".cc" (2) at end of list +transformation .ccc.cc complete +defining transformation from `.c' to `.ccc' +inserting ".c" (1) at end of list +inserting ".ccc" (3) at end of list +transformation .c.ccc complete +defining transformation from `.short' to `.c' +inserting ".short" (4) at end of list +inserting ".c" (1) at end of list +transformation .short.c complete +defining transformation from `.sho' to `.c' +inserting ".sho" (5) at end of list +inserting ".c" (1) at end of list +transformation .sho.c complete +defining transformation from `.dead-end' to `.short' +inserting ".dead-end" (6) at end of list +inserting ".short" (4) at end of list +transformation .dead-end.short complete +inserting ".ccc" (3) at end of list +inserting ".cc" (2) at end of list +inserting ".c" (1) at end of list +inserting ".ccc" (3) at end of list +inserting ".short" (4) at end of list +inserting ".c" (1) at end of list +inserting ".sho" (5) at end of list +inserting ".c" (1) at end of list +inserting ".dead-end" (6) at end of list +inserting ".short" (4) at end of list +Wildcard expanding "all"... +SuffFindDeps (all) + No known suffix on all. Using .NULL suffix +adding suffix rules +Wildcard expanding "suff-lookup.cc"...suffix is ".cc"... +SuffFindDeps (suff-lookup.cc) + trying suff-lookup.ccc...not there + trying suff-lookup.c...not there + trying suff-lookup.short...not there + trying suff-lookup.sho...got it + applying .sho -> .c to "suff-lookup.c" + applying .c -> .ccc to "suff-lookup.ccc" + applying .ccc -> .cc to "suff-lookup.cc" +suffix is ".ccc"... +suffix is ".c"... +suffix is ".sho"... +SuffFindDeps (suff-lookup.sho) +suffix is ".sho"... +: 'Making suff-lookup.sho out of nothing.' +: 'Making suff-lookup.c from suff-lookup.sho.' +: 'Making suff-lookup.ccc from suff-lookup.c.' +: 'Making suff-lookup.cc from suff-lookup.ccc.' +Wildcard expanding "all"... +SuffFindDeps (.END) + No known suffix on .END. Using .NULL suffix +adding suffix rules +Wildcard expanding ".END"... +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.mk (revision 367461) @@ -0,0 +1,40 @@ +# $NetBSD: suff-lookup.mk,v 1.2 2020/10/24 03:18:22 rillig Exp $ +# +# Demonstrate name resolution for suffixes. +# +# See also: +# FindSuffByName + +.MAKEFLAGS: -ds + +all: suff-lookup.cc + +.SUFFIXES: .c .cc .ccc + +# Register '.short' before '.sho'. When searching for the transformation +# '.sho.c', the suffix '.short' must not be found even though it starts with +# the correct characters. +.SUFFIXES: .short .sho .dead-end + +# From long to short suffix. +.ccc.cc: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +# From short to long suffix. +.c.ccc: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +.short.c: + : 'Making ${.TARGET} from ${.IMPSRC}.' +.sho.c: + : 'Making ${.TARGET} from ${.IMPSRC}.' +.dead-end.short: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +suff-lookup.sho: + : 'Making ${.TARGET} out of nothing.' + +# Deleting all suffixes and adding them again rebuilds all of the above +# transformation rules. +.SUFFIXES: +.SUFFIXES: .c .cc .ccc .short .sho .dead-end Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-lookup.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-main.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-main.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-main.exp (revision 367461) @@ -0,0 +1,2 @@ +: Making next-main +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-main.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-main.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-main.mk (revision 367461) @@ -0,0 +1,22 @@ +# $NetBSD: suff-main.mk,v 1.1 2020/10/18 16:33:18 rillig Exp $ +# +# Demonstrate that an inference rule is considered the main target if its +# suffixes are not known at the point of declaration. + +.1.2: + : Making ${.TARGET} from ${.IMPSRC}. + +# At this point, the target '.1.2' is a normal target. +# Since it is the first target in the first dependency declaration, +# it becomes the main target. + +next-main: + : Making ${.TARGET} + +# At this point, 'next-main' is effectively ignored. + +# Declaring both '.1' and '.2' as suffixes turns the '.1.2' target into an +# inference rule (OP_TRANSFORM). As a side effect, this target is no longer +# a candidate for the main target. Therefore the next target is selected as +# the main target, which in this case is 'next-main'. +.SUFFIXES: .1 .2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-main.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.exp (revision 367461) @@ -0,0 +1,5 @@ +: from nothing to a +: from a to b +: from b to c +: from c to nothing +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.mk (revision 367461) @@ -0,0 +1,33 @@ +# $NetBSD: suff-rebuild.mk,v 1.2 2020/10/18 16:12:39 rillig Exp $ +# +# Demonstrates what happens to transformation rules (called inference rules +# by POSIX) when all suffixes are deleted. + +all: suff-rebuild-example + +.SUFFIXES: + +.SUFFIXES: .a .b .c + +suff-rebuild-example.a: + : from nothing to a + +.a.b: + : from a to b +.b.c: + : from b to c +.c: + : from c to nothing + +# XXX: At a quick glance, the code in SuffScanTargets looks as if it were +# possible to delete the suffixes in the middle of the makefile, add back +# the suffixes from before, and have the transformation rules preserved. +# +# As of 2020-09-25, uncommenting the following line results in the error +# message "don't know how to make suff-rebuild-example" though. +# +#.SUFFIXES: + +# Add the suffixes back. It should not matter that the order of the suffixes +# is different from before. +.SUFFIXES: .c .b .a Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-rebuild.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "suff-transform-endless.mk" line 36: prevent endless loop + +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.mk (revision 367461) @@ -0,0 +1,36 @@ +# $NetBSD: suff-transform-endless.mk,v 1.1 2020/10/20 20:36:53 rillig Exp $ + +# https://gnats.netbsd.org/49086, issue 6: +# Transformation search can end up in an infinite loop. +# +# There is no file or target from which issue6.f could be made, so +# this should fail. The bug is that because rules .e.f, .d.e and .e.d +# exist, make would try to make .f from .e and then infinitely try +# to do .e from .d and vice versa. + +all: issue6.f + +.c.d .d.c .d .d.e .e.d: + : 'Making ${.TARGET} from ${.IMPSRC}.' + +.SUFFIXES: .c .d .e .f + +.e .e.f .f.e: + : 'Making ${.TARGET} out of nothing.' + +# XXX: As of 2020-10-20, the result is unexpected. +# XXX: .d.c is not a transformation rule. +# XXX: .d is not a transformation rule. +# XXX: .e.d is not a transformation rule. +# XXX: .c.d is listed as "Files that are only sources". +# XXX: .d.e is listed as "Files that are only sources". +# XXX: The suffixes .d and .f both have the number 3. +# XXX: .c.d is not listed as "Transformations". +# XXX: .d.c is not listed as "Transformations". +# XXX: .d is not listed as "Transformations". +# XXX: .d.e is not listed as "Transformations". +# XXX: .e.d is not listed as "Transformations". +# XXX: Found 'all' as '(not found)' +# XXX: trying all.e, all.e, all.f, all.e, all.e, repeatedly. +#.MAKEFLAGS: -dg1 +.error prevent endless loop Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-endless.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.exp (revision 367461) @@ -0,0 +1,5 @@ +: 'Making issue11.h out of nothing.' +make: don't know how to make .first (continuing) +: 'Making issue11.second out of nothing.' +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: suff-transform-expand.mk,v 1.1 2020/10/20 20:36:53 rillig Exp $ +# +# https://gnats.netbsd.org/49086, issue 11: +# Sources from transformation rules are expanded incorrectly. +# +# issue11.j should depend on issue11.i and issue11.second. +# issue11.i should depend on issue11.h and issue11.first. +# +# XXX: The dynamic sources are expanded before ${.PREFIX} and +# ${.TARGET} were available, so they expand to an empty string. + +all: issue11.j + +.SUFFIXES: .h .i .j + +.h.i: ${.PREFIX}.first + : 'Making ${.TARGET} from ${.IMPSRC} all ${.ALLSRC}.' + +.i.j: ${.PREFIX}.second + : 'Making ${.TARGET} from ${.IMPSRC} all ${.ALLSRC}.' + +issue11.h issue11.first issue11.second: + : 'Making ${.TARGET} out of nothing.' + +#.MAKEFLAGS: -dg1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-expand.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "suff-transform-select.mk" line 28: prevent endless loop + +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.mk (revision 367461) @@ -0,0 +1,28 @@ +# $NetBSD: suff-transform-select.mk,v 1.1 2020/10/20 20:36:53 rillig Exp $ +# +# https://gnats.netbsd.org/49086, issue 10: +# Explicit dependencies affect transformation rule selection. +# +# If issue10.e is wanted and both issue10.d and issue10.f are available, +# make should choose the .d.e rule, because .d is before .f in .SUFFIXES. +# The bug was that if issue10.d had an explicit dependency on issue10.f, +# it would choose .f.e instead. + +_!= rm -f issue10.* + +all: issue10.e + +.c.d .d.c .d .d.e .e.d: + : 'Making ${.TARGET} from ${.IMPSRC} (first set).' + +.SUFFIXES: .c .d .e .f .g + +.e .e.f .f.e: + : 'Making ${.TARGET} from ${.IMPSRC} (second set).' + +issue10.d issue10.f: + : 'Making ${.TARGET} out of nothing.' + +# XXX: see suff-bug-endless, which must be fixed first. +#.MAKEFLAGS: -dg1 +.error prevent endless loop Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/suff-transform-select.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sunshcmd.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sunshcmd.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sunshcmd.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: sunshcmd.mk,v 1.3 2020/10/24 08:50:17 rillig Exp $ + +BYECMD= echo bye +LATERCMD= echo later +TEST1 :sh = echo hello +TEST2 :sh = ${BYECMD} +TEST3= ${LATERCMD:sh} + +all: + @echo "TEST1=${TEST1}" + @echo "TEST2=${TEST2}" + @echo "TEST3=${TEST3}" Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sunshcmd.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/ternary.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/ternary.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/ternary.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: ternary.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ + +all: + @for x in "" A= A=42; do ${.MAKE} -f ${MAKEFILE} show $$x; done + +show: + @echo "The answer is ${A:?known:unknown}" + @echo "The answer is ${A:?$A:unknown}" + @echo "The answer is ${empty(A):?empty:$A}" Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/ternary.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/unexport-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/unexport-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/unexport-env.mk (revision 367461) @@ -0,0 +1,15 @@ +# $NetBSD: unexport-env.mk,v 1.4 2020/10/24 08:50:17 rillig Exp $ + +# pick up a bunch of exported vars +FILTER_CMD= grep ^UT_ +.include "export.mk" + +# an example of setting up a minimal environment. +PATH= /bin:/usr/bin:/sbin:/usr/sbin + +# now clobber the environment to just PATH and UT_TEST +UT_TEST= unexport-env + +# this removes everything +.unexport-env +.export PATH UT_TEST Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/unexport-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/unexport.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/unexport.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/unexport.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: unexport.mk,v 1.5 2020/10/24 08:50:17 rillig Exp $ + +# pick up a bunch of exported vars +FILTER_CMD= grep ^UT_ +.include "export.mk" + +.unexport UT_ZOO UT_FOO + +UT_TEST= unexport + +# Until 2020-08-08, Var_UnExport had special handling for '\n', that code +# was not reachable though. At that point, backslash-newline has already +# been replaced with a simple space, and variables are not yet expanded. +UT_BEFORE_NL= before +UT_AFTER_NL= after +.export UT_BEFORE_NL UT_AFTER_NL +.unexport \ + UT_BEFORE_NL +.unexport ${.newline} UT_AFTER_NL Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/unexport.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.exp (revision 367461) @@ -0,0 +1,2 @@ +: all overwritten +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.mk (revision 367461) @@ -0,0 +1,31 @@ +# $NetBSD: var-class-local.mk,v 1.4 2020/10/25 09:46:25 rillig Exp $ +# +# Tests for target-local variables, such as ${.TARGET} or $@. + +# TODO: Implementation + +# Ensure that the name of the variable is exactly the given one. +# The variable "@" is an alias for ".TARGET", so the implementation might +# canonicalize these aliases at some point, and that might be surprising. +# This aliasing happens for single-character variable names like $@ or $< +# (see VarFind, CanonicalVarname), but not for braced or parenthesized +# expressions like ${@}, ${.TARGET} ${VAR:Mpattern} (see Var_Parse, +# ParseVarname). +.if ${@:L} != "@" +. error +.endif +.if ${.TARGET:L} != ".TARGET" +. error +.endif +.if ${@F:L} != "@F" +. error +.endif +.if ${@D:L} != "@D" +. error +.endif + +all: + # The ::= modifier overwrites the .TARGET variable in the node + # 'all', not in the global scope. This can be seen with the -dv + # option, looking for "all:@ = overwritten". + : ${.TARGET} ${.TARGET::=overwritten}${.TARGET} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-class-local.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.exp (revision 367461) @@ -0,0 +1,7 @@ +Var_Parse: ${:U\$\$\$\$\$\$\$\$} with VARE_WANTRES +Applying ${:U...} to "" (VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U\$\$\$\$\$\$\$\$} is "$$$$$$$$" (VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Global:VAR.$$$$ = dollars +Global:.MAKEFLAGS = -r -k -d v -d +Global:.MAKEFLAGS = -r -k -d v -d 0 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.mk (revision 367461) @@ -0,0 +1,48 @@ +# $NetBSD: var-op-append.mk,v 1.7 2020/10/30 20:36:33 rillig Exp $ +# +# Tests for the += variable assignment operator, which appends to a variable, +# creating it if necessary. + +# Appending to an undefined variable is possible. +# The variable is created, and no extra space is added before the value. +VAR+= one +.if ${VAR} != "one" +. error +.endif + +# Appending to an existing variable adds a single space and the value. +VAR+= two +.if ${VAR} != "one two" +. error +.endif + +# Appending an empty string nevertheless adds a single space. +VAR+= # empty +.if ${VAR} != "one two " +. error +.endif + +# Variable names may contain '+', and this character is also part of the +# '+=' assignment operator. As far as possible, the '+' is interpreted as +# part of the assignment operator. +# +# See Parse_DoVar +C++= value +.if ${C+} != "value" || defined(C++) +. error +.endif + +# Try out how often the variable name is expanded when appending to a +# nonexistent variable. +# As of 2020-10-30, that's two times. +# XXX: That's one time too often. +# See Var_Append, the call to Var_Set. +.MAKEFLAGS: -dv +VAR.${:U\$\$\$\$\$\$\$\$}+= dollars +.MAKEFLAGS: -d0 +.if ${VAR.${:U\$\$\$\$}} != "dollars" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-op-append.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-op-assign.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-op-assign.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-op-assign.mk (revision 367461) @@ -0,0 +1,89 @@ +# $NetBSD: var-op-assign.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ +# +# Tests for the = variable assignment operator, which overwrites an existing +# variable or creates it. + +# This is a simple variable assignment. +# To the left of the assignment operator '=' there is the variable name, +# and to the right is the variable value. +# +VAR= value + +# This condition demonstrates that whitespace around the assignment operator +# is discarded. Otherwise the value would start with a single tab. +# +.if ${VAR} != "value" +. error +.endif + +# Whitespace to the left of the assignment operator is ignored as well. +# The variable value can contain arbitrary characters. +# +# The '#' needs to be escaped with a backslash, this happens in a very +# early stage of parsing and applies to all line types, except for the +# commands, which are indented with a tab. +# +# The '$' needs to be escaped with another '$', otherwise it would refer to +# another variable. +# +VAR= new value and \# some $$ special characters # comment + +# When a string literal appears in a condition, the escaping rules are +# different. Run make with the -dc option to see the details. +.if ${VAR} != "new value and \# some \$ special characters" +. error ${VAR} +.endif + +# The variable value may contain references to other variables. +# In this example, the reference is to the variable with the empty name, +# which always expands to an empty string. This alone would not produce +# any side-effects, therefore the variable has a :!...! modifier that +# executes a shell command. +VAR= ${:! echo 'not yet evaluated' 1>&2 !} +VAR= ${:! echo 'this will be evaluated later' 1>&2 !} + +# Now force the variable to be evaluated. +# This outputs the line to stderr. +.if ${VAR} +.endif + +# In a variable assignment, the variable name must consist of a single word. +# +VARIABLE NAME= variable value + +# But if the whitespace appears inside parentheses or braces, everything is +# fine. +# +# XXX: This was not an intentional decision, as variable names typically +# neither contain parentheses nor braces. This is only a side-effect from +# the implementation of the parser, which cheats when parsing a variable +# name. It only counts parentheses and braces instead of properly parsing +# nested variable expressions such as VAR.${param}. +# +VAR(spaces in parentheses)= () +VAR{spaces in braces}= {} + +# Be careful and use indirect variable names here, to prevent accidentally +# accepting the test in case the parser just uses "VAR" as the variable name, +# ignoring all the rest. +# +VARNAME_PAREN= VAR(spaces in parentheses) +VARNAME_BRACES= VAR{spaces in braces} + +.if ${${VARNAME_PAREN}} != "()" +. error +.endif + +.if ${${VARNAME_BRACES}} != "{}" +. error +.endif + +# In safe mode, parsing would stop immediately after the "VARIABLE NAME=" +# line, since any commands run after that are probably working with +# unexpected variable values. +# +# Therefore, just output an info message. +.info Parsing still continues until here. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-op-assign.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.mk (revision 367461) @@ -0,0 +1,122 @@ +# $NetBSD: var-op-sunsh.mk,v 1.5 2020/10/04 08:32:52 rillig Exp $ +# +# Tests for the :sh= variable assignment operator, which runs its right-hand +# side through the shell. It is a seldom-used alternative to the != +# assignment operator, adopted from Sun make. + +.MAKEFLAGS: -dL # Enable sane error messages + +# This is the idiomatic form of the Sun shell assignment operator. +# The assignment operator is directly preceded by the ':sh'. +VAR:sh= echo colon-sh +.if ${VAR} != "colon-sh" +. error +.endif + +# It is also possible to have whitespace around the :sh assignment +# operator modifier. +VAR :sh = echo colon-sh-spaced +.if ${VAR} != "colon-sh-spaced" +. error +.endif + +# Until 2020-10-04, the ':sh' could even be followed by other characters. +# This was neither documented by NetBSD make nor by Solaris make and was +# an implementation error. +# +# Since 2020-10-04, this is a normal variable assignment using the '=' +# assignment operator. +VAR:shell= echo colon-shell +.if ${${:UVAR\:shell}} != "echo colon-shell" +. error +.endif + +# Several colons can syntactically appear in a variable name. +# Until 2020-10-04, the last of them was interpreted as the ':sh' +# assignment operator. +# +# Since 2020-10-04, the colons are part of the variable name. +VAR:shoe:shore= echo two-colons +.if ${${:UVAR\:shoe\:shore}} != "echo two-colons" +. error +.endif + +# Until 2020-10-04, the following expression was wrongly marked as +# a parse error. This was because the parser for variable assignments +# just looked for the previous ":sh", without taking any contextual +# information into account. +# +# There are two different syntactical elements that look exactly the same: +# The variable modifier ':sh' and the assignment operator modifier ':sh'. +# Intuitively this variable name contains the variable modifier, but until +# 2020-10-04, the parser regarded it as an assignment operator modifier, in +# Parse_DoVar. +VAR.${:Uecho 123:sh}= ok-123 +.if ${VAR.123} != "ok-123" +. error +.endif + +# Same pattern here. Until 2020-10-04, the ':sh' inside the nested expression +# was taken for the :sh assignment operator modifier, even though it was +# escaped by a backslash. +VAR.${:U echo\:shell}= ok-shell +.if ${VAR.${:U echo\:shell}} != "ok-shell" +. error +.endif + +# Until 2020-10-04, the word 'shift' was also affected since it starts with +# ':sh'. +VAR.key:shift= Shift +.if ${${:UVAR.key\:shift}} != "Shift" +. error +.endif + +# Just for fun: The code in Parse_IsVar allows for multiple appearances of +# the ':sh' assignment operator modifier. Let's see what happens ... +# +# Well, the end result is correct but the way until there is rather +# adventurous. This only works because the parser replaces each an every +# whitespace character that is not nested with '\0' (see Parse_DoVar). +# The variable name therefore ends before the first ':sh', and the last +# ':sh' turns the assignment operator into the shell command evaluation. +# Parse_DoVar completely trusts Parse_IsVar to properly verify the syntax. +# +# The ':sh' is the only word that may occur between the variable name and +# the assignment operator at nesting level 0. All other words would lead +# to a parse error since the left-hand side of an assignment must be +# exactly one word. +VAR :sh :sh :sh :sh= echo multiple +.if ${VAR} != "multiple" +. error +.endif + +# The word ':sh' is not the only thing that can occur after a variable name. +# Since the parser just counts braces and parentheses instead of properly +# expanding nested expressions, the token ' :sh' can be used to add arbitrary +# text between the variable name and the assignment operator, it just has to +# be enclosed in braces or parentheses. +VAR :sh(Put a comment here)= comment in parentheses +.if ${VAR} != "comment in parentheses" +. error +.endif + +# The unintended comment can include multiple levels of nested braces and +# parentheses, they don't even need to be balanced since they are only +# counted by Parse_IsVar and ignored by Parse_DoVar. +VAR :sh{Put}((((a}{comment}}}}{here}= comment in braces +.if ${VAR} != "comment in braces" +. error +.endif + +# Syntactically, the ':sh' modifier can be combined with the '+=' assignment +# operator. In such a case the ':sh' modifier is silently ignored. +# +# XXX: This combination should not be allowed at all. +VAR= one +VAR :sh += echo two +.if ${VAR} != "one echo two" +. error ${VAR} +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-op-sunsh.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.exp (revision 367461) @@ -0,0 +1,12 @@ +make: "var-recursive.mk" line 20: still there +Variable DIRECT is recursive. + +make: stopped in unit-tests +Variable INDIRECT1 is recursive. + +make: stopped in unit-tests +make: "var-recursive.mk" line 35: ok +Variable V is recursive. + +make: stopped in unit-tests +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.mk (revision 367461) @@ -0,0 +1,49 @@ +# $NetBSD: var-recursive.mk,v 1.2 2020/10/31 13:45:00 rillig Exp $ +# +# Tests for variable expressions that refer to themselves and thus +# cannot be evaluated. + +TESTS= direct indirect conditional short + +# Since make exits immediately when it detects a recursive expression, +# the actual tests are run in sub-makes. +TEST?= # none +.if ${TEST} == "" +all: +.for test in ${TESTS} + @${.MAKE} -f ${MAKEFILE} TEST=${test} || : +.endfor + +.elif ${TEST} == direct + +DIRECT= ${DIRECT} # Defining a recursive variable is not yet an error. +. info still there # Therefore this line is printed. +. info ${DIRECT} # But expanding the variable is an error. + +.elif ${TEST} == indirect + +# The chain of variables that refer to each other may be long. +INDIRECT1= ${INDIRECT2} +INDIRECT2= ${INDIRECT1} +. info ${INDIRECT1} + +.elif ${TEST} == conditional + +# The variable refers to itself, but only in the branch of a condition that +# is never satisfied and is thus not evaluated. +CONDITIONAL= ${1:?ok:${CONDITIONAL}} +. info ${CONDITIONAL} + +.elif ${TEST} == short + +# Short variable names can be expanded using the short-hand $V notation, +# which takes a different code path in Var_Parse for parsing the variable +# name. Ensure that these are checked as well. +V= $V +. info $V + +.else +. error Unknown test "${TEST}" +.endif + +all: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-recursive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varcmd.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varcmd.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varcmd.mk (revision 367461) @@ -0,0 +1,60 @@ +# $NetBSD: varcmd.mk,v 1.5 2020/10/24 08:50:17 rillig Exp $ +# +# Test behaviour of recursive make and vars set on command line. + +FU= fu +FOO?= foo +.if !empty(.TARGETS) +TAG= ${.TARGETS} +.endif +TAG?= default + +all: one + +show: + @echo "${TAG} FU=${FU} FOO=${FOO} VAR=${VAR}" + +one: show + @${.MAKE} -f ${MAKEFILE} FU=bar FOO+=goo two + +two: show + @${.MAKE} -f ${MAKEFILE} three + +three: show + @${.MAKE} -f ${MAKEFILE} four + + +.ifmake two +# this should not work +FU+= oops +FOO+= oops +_FU:= ${FU} +_FOO:= ${FOO} +two: immutable +immutable: + @echo "$@ FU='${_FU}'" + @echo "$@ FOO='${_FOO}'" +.endif +.ifmake four +VAR=Internal +.MAKEOVERRIDES+= VAR +.endif + +four: show + @${.MAKE} -f ${MAKEFILE} five + +M= x +V.y= is y +V.x= is x +V:= ${V.$M} +K:= ${V} + +show-v: + @echo '${TAG} v=${V} k=${K}' + +five: show show-v + @${.MAKE} -f ${MAKEFILE} M=y six + +six: show-v + @${.MAKE} -f ${MAKEFILE} V=override show-v + Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varcmd.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/vardebug.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/vardebug.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/vardebug.exp (revision 367461) @@ -0,0 +1,86 @@ +Global:delete FROM_CMDLINE (not found) +Command:FROM_CMDLINE = +Global:.MAKEOVERRIDES = FROM_CMDLINE +Global:VAR = added +Global:VAR = overwritten +Global:delete VAR +Global:delete VAR (not found) +Var_Parse: ${:U} with VARE_WANTRES +Applying ${:U} to "" (VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U} is "" (VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Var_Set("${:U}", "empty name", ...) name expands to empty string - ignored +Var_Parse: ${:U} with VARE_WANTRES +Applying ${:U} to "" (VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U} is "" (VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Var_Append("${:U}", "empty name", ...) name expands to empty string - ignored +Global:FROM_CMDLINE = overwritten ignored! +Global:VAR = 1 +Global:VAR = 1 2 +Global:VAR = 1 2 3 +Var_Parse: ${VAR:M[2]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:M...} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Pattern[VAR] for [1 2 3] is [[2]] +ModifyWords: split "1 2 3" into 3 words +VarMatch [1] [[2]] +VarMatch [2] [[2]] +VarMatch [3] [[2]] +Result of ${VAR:M[2]} is "2" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${VAR:N[2]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:N...} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Pattern[VAR] for [1 2 3] is [[2]] +ModifyWords: split "1 2 3" into 3 words +Result of ${VAR:N[2]} is "1 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${VAR:S,2,two,} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:S...} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Modifier part: "2" +Modifier part: "two" +ModifyWords: split "1 2 3" into 3 words +Result of ${VAR:S,2,two,} is "1 two 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${VAR:Q} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:Q} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Result of ${VAR:Q} is "1\ 2\ 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${VAR:tu:tl:Q} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:t...} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Result of ${VAR:tu} is "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Applying ${VAR:t...} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Result of ${VAR:tl} is "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Applying ${VAR:Q} to "1 2 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Result of ${VAR:Q} is "1\ 2\ 3" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${:Uvalue:${:UM*e}:Mvalu[e]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:Uvalue} is "value" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Var_Parse: ${:UM*e}:Mvalu[e]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:UM*e} is "M*e" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Indirect modifier "M*e" from "${:UM*e}" +Applying ${:M...} to "value" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[] for [value] is [*e] +ModifyWords: split "value" into 1 words +VarMatch [value] [*e] +Result of ${:M*e} is "value" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Applying ${:M...} to "value" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[] for [value] is [valu[e]] +ModifyWords: split "value" into 1 words +VarMatch [value] [valu[e]] +Result of ${:Mvalu[e]} is "value" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Var_Parse: ${:UVAR} with VARE_WANTRES +Applying ${:U...} to "" (VARE_WANTRES, none, VEF_UNDEF) +Result of ${:UVAR} is "VAR" (VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Global:delete VAR +Var_Parse: ${:Uvariable:unknown} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:Uvariable} is "variable" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Applying ${:u...} to "variable" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +make: Unknown modifier 'u' +Result of ${:unknown} is error (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +make: "vardebug.mk" line 44: Malformed conditional (${:Uvariable:unknown}) +Var_Parse: ${UNDEFINED} with VARE_UNDEFERR|VARE_WANTRES +make: "vardebug.mk" line 53: Malformed conditional (${UNDEFINED}) +Global:delete .SHELL (not found) +Command:.SHELL = /bin/sh +Command:.SHELL = overwritten ignored (read-only) +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 Index: vendor/NetBSD/bmake/20201101/unit-tests/vardebug.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/vardebug.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/vardebug.mk (revision 367461) @@ -0,0 +1,64 @@ +# $NetBSD: vardebug.mk,v 1.6 2020/10/31 13:15:10 rillig Exp $ +# +# Demonstrates the debugging output for var.c. + +.MAKEFLAGS: -dv FROM_CMDLINE= + +VAR= added # VarAdd +VAR= overwritten # Var_Set +.undef VAR # Var_Delete (found) +.undef VAR # Var_Delete (not found) + +# The variable with the empty name cannot be set at all. +${:U}= empty name # Var_Set +${:U}+= empty name # Var_Append + +FROM_CMDLINE= overwritten # Var_Set (ignored) + +VAR= 1 +VAR+= 2 +VAR+= 3 + +.if ${VAR:M[2]} # ModifyWord_Match +.endif +.if ${VAR:N[2]} # ModifyWord_NoMatch (no debug output) +.endif + +.if ${VAR:S,2,two,} # ParseModifierPart +.endif + +.if ${VAR:Q} # VarQuote +.endif + +.if ${VAR:tu:tl:Q} # ApplyModifiers +.endif + +# ApplyModifiers, "Got ..." +.if ${:Uvalue:${:UM*e}:Mvalu[e]} +.endif + +.undef ${:UVAR} # Var_Delete + +# When ApplyModifiers results in an error, this appears in the debug log +# as "is error", without surrounding quotes. +.if ${:Uvariable:unknown} +.endif + +# XXX: The error message is "Malformed conditional", which is wrong. +# The condition is syntactically fine, it just contains an undefined variable. +# +# There is a specialized error message for "Undefined variable", but as of +# 2020-08-08, that is not covered by any unit tests. It might even be +# unreachable. +.if ${UNDEFINED} +.endif + +# By default, .SHELL is not defined and thus can be set. As soon as it is +# accessed, it is initialized in the command line context (during VarFind), +# where it is set to read-only. Assigning to it is ignored. +.MAKEFLAGS: .SHELL=overwritten + +.MAKEFLAGS: -d0 + +all: + @: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/vardebug.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmisc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmisc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmisc.mk (revision 367461) @@ -0,0 +1,228 @@ +# $Id: varmisc.mk,v 1.20 2020/10/26 17:43:57 sjg Exp $ +# $NetBSD: varmisc.mk,v 1.26 2020/10/24 08:50:17 rillig Exp $ +# +# Miscellaneous variable tests. + +all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \ + strftime cmpv manok +all: save-dollars +all: export-appended +all: parse-dynamic +all: varerror-unclosed + +unmatched_var_paren: + @echo ${foo::=foo-text} + +True= ${echo true >&2:L:sh}TRUE +False= ${echo false >&2:L:sh}FALSE + +VSET= is set +.undef UNDEF + +U_false: + @echo :U skipped when var set + @echo ${VSET:U${False}} + +D_false: + @echo :D skipped if var undef + @echo ${UNDEF:D${False}} + +U_true: + @echo :U expanded when var undef + @echo ${UNDEF:U${True}} + +D_true: + @echo :D expanded when var set + @echo ${VSET:D${True}} + +Q_lhs: + @echo :? only lhs when value true + @echo ${1:L:?${True}:${False}} + +Q_rhs: + @echo :? only rhs when value false + @echo ${0:L:?${True}:${False}} + +NQ_none: + @echo do not evaluate or expand :? if discarding + @echo ${VSET:U${1:L:?${True}:${False}}} + +April1= 1459494000 + +# slightly contorted syntax to use utc via variable +strftime: + @echo ${year=%Y month=%m day=%d:L:gmtime=1459494000} + @echo date=${%Y%m%d:L:${gmtime=${April1}:L}} + +# big jumps to handle 3 digits per step +M_cmpv.units= 1 1000 1000000 +M_cmpv= S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh + +Version= 123.456.789 +cmpv.only= target specific vars + +cmpv: + @echo Version=${Version} == ${Version:${M_cmpv}} + @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}} + @echo We have ${${.TARGET:T}.only} + +# catch misshandling of nested vars in .for loop +MAN= +MAN1= make.1 +.for s in 1 2 +. if defined(MAN$s) && !empty(MAN$s) +MAN+= ${MAN$s} +. endif +.endfor + +manok: + @echo MAN=${MAN} + +# This is an expanded variant of the above .for loop. +# Between 2020-06-28 and 2020-07-02 this paragraph generated a wrong +# error message "Variable VARNAME is recursive". +# When evaluating the !empty expression, the ${:U1} was not expanded and +# thus resulted in the seeming definition VARNAME=${VARNAME}, which is +# obviously recursive. +VARNAME= ${VARNAME${:U1}} +.if defined(VARNAME${:U2}) && !empty(VARNAME${:U2}) +.endif + +# begin .MAKE.SAVE_DOLLARS; see Var_Set_with_flags and s2Boolean. +SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off +SD_4_DOLLARS= $$$$ + +.for val in ${SD_VALUES} +.MAKE.SAVE_DOLLARS:= ${val} # Must be := since a simple = has no effect. +SD.${val}:= ${SD_4_DOLLARS} +.endfor +.MAKE.SAVE_DOLLARS:= yes + +save-dollars: +.for val in ${SD_VALUES} + @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q} +.endfor + +# Appending to an undefined variable does not add a space in front. +.undef APPENDED +APPENDED+= value +.if ${APPENDED} != "value" +. error "${APPENDED}" +.endif + +# Appending to an empty variable adds a space between the old value +# and the additional value. +APPENDED= # empty +APPENDED+= value +.if ${APPENDED} != " value" +. error "${APPENDED}" +.endif + +# Appending to parameterized variables works as well. +PARAM= param +VAR.${PARAM}= 1 +VAR.${PARAM}+= 2 +.if ${VAR.param} != "1 2" +. error "${VAR.param}" +.endif + +# The variable name can contain arbitrary characters. +# If the expanded variable name ends in a +, this still does not influence +# the parser. The assignment operator is still a simple assignment. +# Therefore, there is no need to add a space between the variable name +# and the assignment operator. +PARAM= + +VAR.${PARAM}= 1 +VAR.${PARAM}+= 2 +.if ${VAR.+} != "1 2" +. error "${VAR.+}" +.endif +.for param in + ! ? +VAR.${param}= ${param} +.endfor +.if ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?" +. error "${VAR.+}" "${VAR.!}" "${VAR.?}" +.endif + +# Appending to a variable from the environment creates a copy of that variable +# in the global context. +# The appended value is not exported automatically. +# When a variable is exported, the exported value is taken at the time of the +# .export directive. Later changes to the variable have no effect. +.export FROM_ENV_BEFORE +FROM_ENV+= mk +FROM_ENV_BEFORE+= mk +FROM_ENV_AFTER+= mk +.export FROM_ENV_AFTER + +export-appended: + @echo $@: "$$FROM_ENV" + @echo $@: "$$FROM_ENV_BEFORE" + @echo $@: "$$FROM_ENV_AFTER" + +# begin parse-dynamic +# +# Demonstrate that the target-specific variables are not evaluated in +# the global context. They are preserved until there is a local context +# in which resolving them makes sense. + +# There are different code paths for short names ... +${:U>}= before +GS_TARGET:= $@ +GS_MEMBER:= $% +GS_PREFIX:= $* +GS_ARCHIVE:= $! +GS_ALLSRC:= $> +${:U>}= after +# ... and for braced short names ... +GB_TARGET:= ${@} +GB_MEMBER:= ${%} +GB_PREFIX:= ${*} +GB_ARCHIVE:= ${!} +GB_ALLSRC:= ${>} +# ... and for long names. +GL_TARGET:= ${.TARGET} +GL_MEMBER:= ${.MEMBER} +GL_PREFIX:= ${.PREFIX} +GL_ARCHIVE:= ${.ARCHIVE} +GL_ALLSRC:= ${.ALLSRC} + +parse-dynamic: + @echo $@: ${GS_TARGET} ${GS_MEMBER} ${GS_PREFIX} ${GS_ARCHIVE} ${GS_ALLSRC} + @echo $@: ${GB_TARGET} ${GB_MEMBER} ${GB_PREFIX} ${GB_ARCHIVE} ${GB_ALLSRC} + @echo $@: ${GL_TARGET} ${GL_MEMBER} ${GL_PREFIX} ${GL_ARCHIVE} ${GL_ALLSRC} + +# Since 2020-07-28, make complains about unclosed variables. +# Before that, it had complained about unclosed variables only when +# parsing the modifiers, but not when parsing the variable name. + +UNCLOSED_INDIR_1= ${UNCLOSED_ORIG +UNCLOSED_INDIR_2= ${UNCLOSED_INDIR_1} + +FLAGS= one two +FLAGS+= ${FLAGS.${.ALLSRC:M*.c:T:u}} +FLAGS.target2.c= three four + +target1.c: +target2.c: + +all: target1-flags target2-flags +target1-flags: target1.c + @echo $@: we have: ${FLAGS} + +target2-flags: target2.c + @echo $@: we have: ${FLAGS} + +varerror-unclosed: + @echo $@:begin + @echo $( + @echo $(UNCLOSED + @echo ${UNCLOSED + @echo ${UNCLOSED:M${PATTERN + @echo ${UNCLOSED.${param + @echo $ +.for i in 1 2 3 + @echo ${UNCLOSED.${i} +.endfor + @echo ${UNCLOSED_INDIR_2} + @echo $@:end Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmisc.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.exp (revision 367461) @@ -0,0 +1,26 @@ +mod-assign: first=1. +mod-assign: last=3. +mod-assign: appended=1 2 3. +1 +2 +3 +mod-assign: ran:3. +mod-assign: global: 1, 3, 1 2 3, 3. +mod-assign-nested: then1t1 +mod-assign-nested: else2e2 +mod-assign-nested: then3t3 +mod-assign-nested: else4e4 +make: Bad modifier `:' for +mod-assign-empty: value} +make: Bad modifier `:' for +mod-assign-empty: overwritten} +mod-assign-empty: VAR=overwritten +make: Unknown modifier ':' + +sysv:y +make: Unfinished modifier for ASSIGN ('}' missing) + +ok=word +make: " echo word; false " returned non-zero status +err=previous +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.mk (revision 367461) @@ -0,0 +1,107 @@ +# $NetBSD: varmod-assign.mk,v 1.8 2020/10/18 21:37:24 rillig Exp $ +# +# Tests for the obscure ::= variable modifiers, which perform variable +# assignments during evaluation, just like the = operator in C. + +all: mod-assign +all: mod-assign-nested +all: mod-assign-empty +all: mod-assign-parse +all: mod-assign-shell-error + +mod-assign: + # The ::?= modifier applies the ?= assignment operator 3 times. + # The ?= operator only has an effect for the first time, therefore + # the variable FIRST ends up with the value 1. + @echo $@: ${1 2 3:L:@i@${FIRST::?=$i}@} first=${FIRST}. + + # The ::= modifier applies the = assignment operator 3 times. + # The = operator overwrites the previous value, therefore the + # variable LAST ends up with the value 3. + @echo $@: ${1 2 3:L:@i@${LAST::=$i}@} last=${LAST}. + + # The ::+= modifier applies the += assignment operator 3 times. + # The += operator appends 3 times to the variable, therefore + # the variable APPENDED ends up with the value "1 2 3". + @echo $@: ${1 2 3:L:@i@${APPENDED::+=$i}@} appended=${APPENDED}. + + # The ::!= modifier applies the != assignment operator 3 times. + # The side effects of the shell commands are visible in the output. + # Just as with the ::= modifier, the last value is stored in the + # RAN variable. + @echo $@: ${echo.1 echo.2 echo.3:L:@i@${RAN::!=${i:C,.*,&; & 1>\&2,:S,., ,g}}@} ran:${RAN}. + + # The assignments happen in the global scope and thus are + # preserved even after the shell command has been run. + @echo $@: global: ${FIRST:Q}, ${LAST:Q}, ${APPENDED:Q}, ${RAN:Q}. + +mod-assign-nested: + # The condition "1" is true, therefore THEN1 gets assigned a value, + # and IT1 as well. Nothing surprising here. + @echo $@: ${1:?${THEN1::=then1${IT1::=t1}}:${ELSE1::=else1${IE1::=e1}}}${THEN1}${ELSE1}${IT1}${IE1} + + # The condition "0" is false, therefore ELSE1 gets assigned a value, + # and IE1 as well. Nothing surprising here as well. + @echo $@: ${0:?${THEN2::=then2${IT2::=t2}}:${ELSE2::=else2${IE2::=e2}}}${THEN2}${ELSE2}${IT2}${IE2} + + # The same effects happen when the variables are defined elsewhere. + @echo $@: ${SINK3:Q} + @echo $@: ${SINK4:Q} +SINK3:= ${1:?${THEN3::=then3${IT3::=t3}}:${ELSE3::=else3${IE3::=e3}}}${THEN3}${ELSE3}${IT3}${IE3} +SINK4:= ${0:?${THEN4::=then4${IT4::=t4}}:${ELSE4::=else4${IE4::=e4}}}${THEN4}${ELSE4}${IT4}${IE4} + +mod-assign-empty: + # Assigning to the empty variable would obviously not work since that + # variable is write-protected. Therefore it is rejected early with a + # "Bad modifier" message. + # + # XXX: The error message is hard to read since the variable name is + # empty. This leads to a trailing space in the error message. + @echo $@: ${::=value} + + # In this variant, it is not as obvious that the name of the + # expression is empty. Assigning to it is rejected as well, with the + # same "Bad modifier" message. + # + # XXX: The error message is hard to read since the variable name is + # empty. This leads to a trailing space in the error message. + @echo $@: ${:Uvalue::=overwritten} + + # The :L modifier sets the value of the expression to its variable + # name. The name of the expression is "VAR", therefore assigning to + # that variable works. + @echo $@: ${VAR:L::=overwritten} VAR=${VAR} + +mod-assign-parse: + # The modifier for assignment operators starts with a ':'. + # An 'x' after that is an invalid modifier. + @echo ${ASSIGN::x} # 'x' is an unknown assignment operator + + # When parsing an assignment operator fails because the operator is + # incomplete, make falls back to the SysV modifier. + @echo ${SYSV::=sysv\:x}${SYSV::x=:y} + + @echo ${ASSIGN::=value # missing closing brace + +mod-assign-shell-error: + # If the command succeeds, the variable is assigned. + @${SH_OK::!= echo word; true } echo ok=${SH_OK} + + # If the command fails, the variable keeps its previous value. + # FIXME: the error message says: "previous" returned non-zero status + @${SH_ERR::=previous} + @${SH_ERR::!= echo word; false } echo err=${SH_ERR} + +# XXX: The ::= modifier expands its right-hand side, exactly once. +# This differs subtly from normal assignments such as '+=' or '=', which copy +# their right-hand side literally. +APPEND.prev= previous +APPEND.var= ${APPEND.prev} +APPEND.indirect= indirect $${:Unot expanded} +APPEND.dollar= $${APPEND.indirect} +.if ${APPEND.var::+=${APPEND.dollar}} != "" +. error +.endif +.if ${APPEND.var} != "previous indirect \${:Unot expanded}" +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-assign.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.mk (revision 367461) @@ -0,0 +1,89 @@ +# $NetBSD: varmod-defined.mk,v 1.7 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :D variable modifier, which returns the given string +# if the variable is defined. It is closely related to the :U modifier. + +DEF= defined +.undef UNDEF + +# Since DEF is defined, the value of the expression is "value", not +# "defined". +# +.if ${DEF:Dvalue} != "value" +. error +.endif + +# Since UNDEF is not defined, the "value" is ignored. Instead of leaving the +# expression undefined, it is set to "", exactly to allow the expression to +# be used in .if conditions. In this place, other undefined expressions +# would generate an error message. +# XXX: Ideally the error message would be "undefined variable", but as of +# 2020-08-25 it is "Malformed conditional". +# +.if ${UNDEF:Dvalue} != "" +. error +.endif + +# The modifier text may contain plain text as well as expressions. +# +.if ${DEF:D<${DEF}>} != "" +. error +.endif + +# Special characters that would be interpreted differently can be escaped. +# These are '}' (the closing character of the expression), ':', '$' and '\'. +# Any other backslash sequences are preserved. +# +# The escaping rules for string literals in conditions are completely +# different though. There, any character may be escaped using a backslash. +# +.if ${DEF:D \} \: \$ \\ \) \n } != " } : \$ \\ \\) \\n " +. error +.endif + +# Like in several other places in variable expressions, when +# ApplyModifier_Defined calls Var_Parse, double dollars lead to a parse +# error that is silently ignored. This makes all dollar signs disappear, +# except for the last, which is a well-formed variable expression. +# +.if ${DEF:D$$$$$${DEF}} != "defined" +. error +.endif + +# Any other text is written without any further escaping. In contrast +# to the :M modifier, parentheses and braces do not need to be nested. +# Instead, the :D modifier is implemented sanely by parsing nested +# expressions as such, without trying any shortcuts. See ApplyModifier_Match +# for an inferior variant. +# +.if ${DEF:D!&((((} != "!&((((" +. error +.endif + +# The :D modifier is often used in combination with the :U modifier. +# It does not matter in which order the :D and :U modifiers appear. +.if ${UNDEF:Dyes:Uno} != no +. error +.endif +.if ${UNDEF:Uno:Dyes} != no +. error +.endif +.if ${DEF:Dyes:Uno} != yes +. error +.endif +.if ${DEF:Uno:Dyes} != yes +. error +.endif + +# Since the variable with the empty name is never defined, the :D modifier +# can be used to add comments in the middle of an expression. That +# expression always evaluates to an empty string. +.if ${:D This is a comment. } != "" +. error +.endif + +# TODO: Add more tests for parsing the plain text part, to cover each branch +# of ApplyModifier_Defined. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.mk (revision 367461) @@ -0,0 +1,173 @@ +# $NetBSD: varmod-edge.mk,v 1.13 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for edge cases in variable modifiers. +# +# These tests demonstrate the current implementation in small examples. +# They may contain surprising behavior. +# +# Each test consists of: +# - INP, the input to the test +# - MOD, the expression for testing the modifier +# - EXP, the expected output + +TESTS+= M-paren +INP.M-paren= (parentheses) {braces} (opening closing) () +MOD.M-paren= ${INP.M-paren:M(*)} +EXP.M-paren= (parentheses) () + +# The first closing brace matches the opening parenthesis. +# The second closing brace actually ends the variable expression. +# +# XXX: This is unexpected but rarely occurs in practice. +TESTS+= M-mixed +INP.M-mixed= (paren-brace} ( +MOD.M-mixed= ${INP.M-mixed:M(*}} +EXP.M-mixed= (paren-brace} + +# After the :M modifier has parsed the pattern, only the closing brace +# and the colon are unescaped. The other characters are left as-is. +# To actually see this effect, the backslashes in the :M modifier need +# to be doubled since single backslashes would simply be unescaped by +# Str_Match. +# +# XXX: This is unexpected. The opening brace should also be unescaped. +TESTS+= M-unescape +INP.M-unescape= ({}): \(\{\}\)\: \(\{}\): +MOD.M-unescape= ${INP.M-unescape:M\\(\\{\\}\\)\\:} +EXP.M-unescape= \(\{}\): + +# When the :M and :N modifiers are parsed, the pattern finishes as soon +# as open_parens + open_braces == closing_parens + closing_braces. This +# means that ( and } form a matching pair. +# +# Nested variable expressions are not parsed as such. Instead, only the +# parentheses and braces are counted. This leads to a parse error since +# the nested expression is not "${:U*)}" but only "${:U*)", which is +# missing the closing brace. The expression is evaluated anyway. +# The final brace in the output comes from the end of M.nest-mix. +# +# XXX: This is unexpected but rarely occurs in practice. +TESTS+= M-nest-mix +INP.M-nest-mix= (parentheses) +MOD.M-nest-mix= ${INP.M-nest-mix:M${:U*)}} +EXP.M-nest-mix= (parentheses)} +# make: Unclosed variable specification (expecting '}') for "" (value "*)") modifier U + +# In contrast to parentheses and braces, the brackets are not counted +# when the :M modifier is parsed since Makefile variables only take the +# ${VAR} or $(VAR) forms, but not $[VAR]. +# +# The final ] in the pattern is needed to close the character class. +TESTS+= M-nest-brk +INP.M-nest-brk= [ [[ [[[ +MOD.M-nest-brk= ${INP.M-nest-brk:M${:U[[[[[]}} +EXP.M-nest-brk= [ + +# The pattern in the nested variable has an unclosed character class. +# No error is reported though, and the pattern is closed implicitly. +# +# XXX: It is unexpected that no error is reported. +# See str.c, function Str_Match. +# +# Before 2019-12-02, this test case triggered an out-of-bounds read +# in Str_Match. +TESTS+= M-pat-err +INP.M-pat-err= [ [[ [[[ +MOD.M-pat-err= ${INP.M-pat-err:M${:U[[}} +EXP.M-pat-err= [ + +# The first backslash does not escape the second backslash. +# Therefore, the second backslash escapes the parenthesis. +# This means that the pattern ends there. +# The final } in the output comes from the end of MOD.M-bsbs. +# +# If the first backslash were to escape the second backslash, the first +# closing brace would match the opening parenthesis (see M-mixed), and +# the second closing brace would be needed to close the variable. +# After that, the remaining backslash would escape the parenthesis in +# the pattern, therefore (} would match. +TESTS+= M-bsbs +INP.M-bsbs= (} \( \(} +MOD.M-bsbs= ${INP.M-bsbs:M\\(}} +EXP.M-bsbs= \(} +#EXP.M-bsbs= (} # If the first backslash were to escape ... + +# The backslash in \( does not escape the parenthesis, therefore it +# counts for the nesting level and matches with the first closing brace. +# The second closing brace closes the variable, and the third is copied +# literally. +# +# The second :M in the pattern is nested between ( and }, therefore it +# does not start a new modifier. +TESTS+= M-bs1-par +INP.M-bs1-par= ( (:M (:M} \( \(:M \(:M} +MOD.M-bs1-par= ${INP.M-bs1-par:M\(:M*}}} +EXP.M-bs1-par= (:M}} + +# The double backslash is passed verbatim to the pattern matcher. +# The Str_Match pattern is \\(:M*}, and there the backslash is unescaped. +# Again, the ( takes place in the nesting level, and there is no way to +# prevent this, no matter how many backslashes are used. +TESTS+= M-bs2-par +INP.M-bs2-par= ( (:M (:M} \( \(:M \(:M} +MOD.M-bs2-par= ${INP.M-bs2-par:M\\(:M*}}} +EXP.M-bs2-par= \(:M}} + +# Str_Match uses a recursive algorithm for matching the * patterns. +# Make sure that it survives patterns with 128 asterisks. +# That should be enough for all practical purposes. +# To produce a stack overflow, just add more :Qs below. +TESTS+= M-128 +INP.M-128= ${:U\\:Q:Q:Q:Q:Q:Q:Q:S,\\,x,g} +PAT.M-128= ${:U\\:Q:Q:Q:Q:Q:Q:Q:S,\\,*,g} +MOD.M-128= ${INP.M-128:M${PAT.M-128}} +EXP.M-128= ${INP.M-128} + +# This is the normal SysV substitution. Nothing surprising here. +TESTS+= eq-ext +INP.eq-ext= file.c file.cc +MOD.eq-ext= ${INP.eq-ext:%.c=%.o} +EXP.eq-ext= file.o file.cc + +# The SysV := modifier is greedy and consumes all the modifier text +# up until the closing brace or parenthesis. The :Q may look like a +# modifier, but it really isn't, that's why it appears in the output. +TESTS+= eq-q +INP.eq-q= file.c file.cc +MOD.eq-q= ${INP.eq-q:%.c=%.o:Q} +EXP.eq-q= file.o:Q file.cc + +# The = in the := modifier can be escaped. +TESTS+= eq-bs +INP.eq-bs= file.c file.c=%.o +MOD.eq-bs= ${INP.eq-bs:%.c\=%.o=%.ext} +EXP.eq-bs= file.c file.ext + +# Having only an escaped '=' results in a parse error. +# The call to "pattern.lhs = ParseModifierPart" fails. +TESTS+= eq-esc +INP.eq-esc= file.c file... +MOD.eq-esc= ${INP.eq-esc:a\=b} +EXP.eq-esc= # empty +# make: Unfinished modifier for INP.eq-esc ('=' missing) + +TESTS+= colon +INP.colon= value +MOD.colon= ${INP.colon:} +EXP.colon= value + +TESTS+= colons +INP.colons= value +MOD.colons= ${INP.colons::::} +EXP.colons= # empty + +.for test in ${TESTS} +. if ${MOD.${test}} == ${EXP.${test}} +. info ok ${test} +. else +. warning error in ${test}: expected "${EXP.${test}}", got "${MOD.${test}}" +. endif +.endfor + +all: + @echo ok Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.mk (revision 367461) @@ -0,0 +1,28 @@ +# $NetBSD: varmod-exclam-shell.mk,v 1.3 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :!cmd! variable modifier. + +.if ${:!echo hello | tr 'l' 'l'!} != "hello" +. warning unexpected +.endif + +# The output is truncated at the first null byte. +# Cmd_Exec returns only a string pointer without length information. +.if ${:!echo hello | tr 'l' '\0'!} != "he" +. warning unexpected +.endif + +.if ${:!echo!} != "" +. warning A newline at the end of the output must be stripped. +.endif + +.if ${:!echo;echo!} != " " +. warning Only a single newline at the end of the output is stripped. +.endif + +.if ${:!echo;echo;echo;echo!} != " " +. warning Other newlines in the output are converted to spaces. +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.exp (revision 367461) @@ -0,0 +1,27 @@ +mod-gmtime: +%Y +2020 +%Y +localtime == localtime +mod-gmtime-indirect: +make: Invalid time value: ${:U1593536400}} + +mtime=1593536400} +parse-errors: +make: Invalid time value: -1}. + +: -1 becomes mtime=-1}. +make: Invalid time value: 1}. + +: space 1 becomes mtime= 1}. +: 0 becomes ok. +: 1 becomes Thu Jan 1 00:00:01 1970. +: INT32_MAX becomes Tue Jan 19 03:14:07 2038. +: INT32_MAX + 1 becomes Tue Jan 19 03:14:08 2038. +make: Invalid time value: 10000000000000000000000000000000}. + +: overflow becomes mtime=10000000000000000000000000000000}. +make: Invalid time value: error}. + +: letter becomes mtime=error}. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.mk (revision 367461) @@ -0,0 +1,87 @@ +# $NetBSD: varmod-gmtime.mk,v 1.6 2020/10/31 20:30:06 rillig Exp $ +# +# Tests for the :gmtime variable modifier, which formats a timestamp +# using strftime(3) in UTC. + +all: mod-gmtime +all: mod-gmtime-indirect +all: parse-errors + +# Test for the default time format, %c. Since the time always varies, it's +# only possible to check for the general format here. The names of the +# month and weekday are always in English, independent from the locale. +# Example: Thu Oct 29 18:56:41 2020 +.if ${:U:gmtime:tW:M??? ??? ?? ??\:??\:?? ????} == "" +. error +.endif + +mod-gmtime: + @echo $@: + + # modifier name too short + @echo ${%Y:L:gmtim=1593536400} + + # 2020-07-01T00:00:00Z + @echo ${%Y:L:gmtime=1593536400} + + # modifier name too long + @echo ${%Y:L:gmtimer=1593536400} + + # If the modifier name is not matched exactly, fall back to the + # :from=to modifier. + @echo ${gmtime:L:gm%=local%} == localtime + +mod-gmtime-indirect: + @echo $@: + + # As of 2020-08-16, it is not possible to pass the seconds via a + # variable expression. This is because parsing of the :gmtime + # modifier stops at the '$' and returns to ApplyModifiers. + # + # There, a colon would be skipped but not a dollar. + # Parsing therefore continues at the '$' of the ${:U159...}, looking + # for an ordinary variable modifier. + # + # At this point, the ${:U} is expanded and interpreted as a variable + # modifier, which results in the error message "Unknown modifier '1'". + # + # If ApplyModifier_Gmtime were to pass its argument through + # ParseModifierPart, this would work. + @echo ${%Y:L:gmtime=${:U1593536400}} + +parse-errors: + @echo $@: + + # As of 2020-10-31, it is possible to pass negative time stamps + # to the :gmtime modifier, resulting in dates before 1970. + # Going back 50 years in the past is not a practical use case for + # make. + : -1 becomes ${:L:gmtime=-1}. + + # Spaces are allowed, not because it would make sense but just as + # a side-effect from using strtoul. + : space 1 becomes ${:L:gmtime= 1}. + + # 0 means now; to get consistent test results, the actual value has + # to be normalized. + : 0 becomes ${:L:gmtime=0:C,^... ... .. ..:..:.. 20..$,ok,W}. + + : 1 becomes ${:L:gmtime=1}. + + : INT32_MAX becomes ${:L:gmtime=2147483647}. + + # This may be different if time_t is still a 32-bit signed integer. + : INT32_MAX + 1 becomes ${:L:gmtime=2147483648}. + + # Integer overflow. + # Because this modifier is implemented using strtoul, the parsed + # time is ULONG_MAX, which gets converted to -1. This results + # in a time stamp of the second before 1970. + : overflow becomes ${:L:gmtime=10000000000000000000000000000000}. + + # As of 2020-10-31, there is no error handling while parsing the + # :gmtime modifier, thus no error message is printed. Parsing + # stops after the '=', and the remaining string is parsed for + # more variable modifiers. Because of the unknown modifier 'e', + # the whole variable value is discarded and thus not printed. + : letter becomes ${:L:gmtime=error}. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-gmtime.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.mk (revision 367461) @@ -0,0 +1,64 @@ +# $NetBSD: varmod-hash.mk,v 1.5 2020/09/04 06:54:07 rillig Exp $ +# +# Tests for the :hash variable modifier, which computes a 32-bit hash from +# the value of the expression. + +# Test vectors for generating certain hashes. Found by a brute force +# search over [a-z]{8}. +# +VECTORS+= 00000000 adjbuqnt +VECTORS+= 00000001 beiiyxdp +VECTORS+= 00000002 ajriwzqe +VECTORS+= 00000004 aimszzcb +VECTORS+= 00000008 afffvsgz +VECTORS+= 00000010 alkksbun +VECTORS+= 00000020 arqeianj +VECTORS+= 00000040 acgaltwv +VECTORS+= 00000080 addsjxec +VECTORS+= 00000100 acbozubm +VECTORS+= 00000200 acnbugtp +VECTORS+= 00000400 ajyfkpcl +VECTORS+= 00000800 akobyelz +VECTORS+= 00001000 aclmaggk +VECTORS+= 00002000 aauwlqiq +VECTORS+= 00004000 ankfvoqf +VECTORS+= 00008000 airtytts +VECTORS+= 00010000 bfwwrqfi +VECTORS+= 00020000 actwkzix +VECTORS+= 00040000 alsfbgvo +VECTORS+= 00080000 aioiauem +VECTORS+= 00100000 bxexhpji +VECTORS+= 00200000 awtxcwch +VECTORS+= 00400000 aoqpmqam +VECTORS+= 00800000 akgtvjhz +VECTORS+= 01000000 bcmsuvrm +VECTORS+= 02000000 aqnktorm +VECTORS+= 04000000 aweqylny +VECTORS+= 08000000 crvkuyze +VECTORS+= 10000000 alxiatjv +VECTORS+= 20000000 aezwuukx +VECTORS+= 40000000 abdpnifu +VECTORS+= 80000000 auusgoii +VECTORS+= ffffffff ahnvmfdw + +VECTORS+= b2af338b "" +VECTORS+= 3360ac65 a +VECTORS+= 7747f046 ab +VECTORS+= 9ca87054 abc +VECTORS+= 880fe816 abcd +VECTORS+= 208fcbd3 abcde +VECTORS+= d5d376eb abcdef +VECTORS+= de41416c abcdefghijklmnopqrstuvwxyz + +.for hash input in ${VECTORS} +. if ${input:S,^""$,,:hash} != ${hash} +. warning Expected ${hash} for ${input}, but was ${input:hash}. +. endif +.endfor + +all: + @echo ${12345:L:has} # modifier name too short + @echo ${12345:L:hash} # ok + @echo ${12345:L:hash=SHA-256} # :hash does not accept '=' + @echo ${12345:L:hasX} # misspelled + @echo ${12345:L:hashed} # modifier name too long Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.exp (revision 367461) @@ -0,0 +1,8 @@ +make: Bad conditional expression `variable expression == "literal"' in variable expression == "literal"?bad:bad +make: "varmod-ifelse.mk" line 27: Malformed conditional (${${:Uvariable expression} == "literal":?bad:bad}) +make: Bad conditional expression ` == ""' in == ""?bad-assign:bad-assign +make: Bad conditional expression ` == ""' in == ""?bad-cond:bad-cond +make: "varmod-ifelse.mk" line 44: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond}) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.mk (revision 367461) @@ -0,0 +1,61 @@ +# $NetBSD: varmod-ifelse.mk,v 1.5 2020/10/23 14:24:51 rillig Exp $ +# +# Tests for the ${cond:?then:else} variable modifier, which evaluates either +# the then-expression or the else-expression, depending on the condition. +# +# The modifier was added on 1998-04-01. +# +# Until 2015-10-11, the modifier always evaluated both the "then" and the +# "else" expressions. + +# TODO: Implementation + +# The variable name of the expression is expanded and then taken as the +# condition. In this case it becomes: +# +# variable expression == "variable expression" +# +# This confuses the parser, which expects an operator instead of the bare +# word "expression". If the name were expanded lazily, everything would be +# fine since the condition would be: +# +# ${:Uvariable expression} == "literal" +# +# Evaluating the variable name lazily would require additional code in +# Var_Parse and ParseVarname, it would be more useful and predictable +# though. +.if ${${:Uvariable expression} == "literal":?bad:bad} +. error +.else +. error +.endif + +# In a variable assignment, undefined variables are not an error. +# Because of the early expansion, the whole condition evaluates to +# ' == ""' though, which cannot be parsed because the left-hand side looks +# empty. +COND:= ${${UNDEF} == "":?bad-assign:bad-assign} + +# In a condition, undefined variables generate a "Malformed conditional" +# error. That error message is wrong though. In lint mode, the correct +# "Undefined variable" error message is generated. +# The difference to the ':=' variable assignment is the additional +# "Malformed conditional" error message. +.if ${${UNDEF} == "":?bad-cond:bad-cond} +. error +.else +. error +.endif + +# When the :? is parsed, it is greedy. The else branch spans all the +# text, up until the closing character '}', even if the text looks like +# another modifier. +.if ${1:?then:else:Q} != "then" +. error +.endif +.if ${0:?then:else:Q} != "else:Q" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-ifelse.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.mk (revision 367461) @@ -0,0 +1,44 @@ +# $NetBSD: varmod-l-name-to-value.mk,v 1.7 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :L modifier, which returns the variable name as the new value. + +# The empty variable name leads to an empty string. +.if ${:L} != "" +. error +.endif + +# The variable name is converted into an expression with the variable name +# "VARNAME" and the value "VARNAME". +.if ${VARNAME:L} != "VARNAME" +. error +.endif + +# The value of the expression can be modified afterwards. +.if ${VARNAME:L:S,VAR,,} != "NAME" +. error +.endif + +# The name of the expression is still the same as before. Using the :L +# modifier, it can be restored. +# +# Hmmm, this can be used as a double storage or a backup mechanism. +# Probably unintended, but maybe useful. +.if ${VARNAME:L:S,VAR,,:L} != "VARNAME" +. error +.endif + +# Between 2020-09-22 (var.c 1.527) and 2020-09-30 (var.c 1.553), there was +# a bug in the evaluation of variable expressions. Indirect modifiers like +# the below :L did not update the definedness of the enclosing expression. +# This resulted in a wrong "Malformed conditional". +.if ${value:${:UL}} == "" +.endif + +# As of 2020-10-02, the :L modifier does not ensure that it is followed by +# a delimiter, that is, a ':' or endc. Neither does the :P modifier. +.if ${value:LLLLLLPL} != "value" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.exp (revision 367461) @@ -0,0 +1,27 @@ +mod-localtime +%Y +2020 +%Y +gmtime == gmtime +mod-localtime-indirect: +make: Invalid time value: ${:U1593536400}} + +ocaltime=1593536400} +parse-errors: +make: Invalid time value: -1}. + +: -1 becomes ocaltime=-1}. +make: Invalid time value: 1}. + +: space 1 becomes ocaltime= 1}. +: 0 becomes ok. +: 1 becomes Thu Jan 1 01:00:01 1970. +: INT32_MAX becomes Tue Jan 19 04:14:07 2038. +: INT32_MAX + 1 becomes Tue Jan 19 04:14:08 2038. +make: Invalid time value: 10000000000000000000000000000000}. + +: overflow becomes ocaltime=10000000000000000000000000000000}. +make: Invalid time value: error}. + +: letter becomes ocaltime=error}. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.mk (revision 367461) @@ -0,0 +1,92 @@ +# $NetBSD: varmod-localtime.mk,v 1.5 2020/10/31 20:30:06 rillig Exp $ +# +# Tests for the :localtime variable modifier, which formats a timestamp +# using strftime(3) in local time. + +.if ${TZ} != "Europe/Berlin" # see unit-tests/Makefile +. error +.endif + +all: mod-localtime +all: mod-localtime-indirect +all: parse-errors + +# Test for the default time format, %c. Since the time always varies, it's +# only possible to check for the general format here. The names of the +# month and weekday are always in English, independent from the locale. +# Example: Thu Oct 29 18:56:41 2020 +.if ${:U:localtime:tW:M??? ??? ?? ??\:??\:?? ????} == "" +. error +.endif + +mod-localtime: + @echo $@ + + # modifier name too short + @echo ${%Y:L:localtim=1593536400} + + # 2020-07-01T00:00:00Z + @echo ${%Y:L:localtime=1593536400} + + # modifier name too long + @echo ${%Y:L:localtimer=1593536400} + + # If the modifier name is not matched exactly, fall back to the + # :from=to modifier. + @echo ${localtime:L:local%=gm%} == gmtime + +mod-localtime-indirect: + @echo $@: + + # As of 2020-08-16, it is not possible to pass the seconds via a + # variable expression. This is because parsing of the :localtime + # modifier stops at the '$' and returns to ApplyModifiers. + # + # There, a colon would be skipped but not a dollar. + # Parsing therefore continues at the '$' of the ${:U159...}, looking + # for an ordinary variable modifier. + # + # At this point, the ${:U} is expanded and interpreted as a variable + # modifier, which results in the error message "Unknown modifier '1'". + # + # If ApplyModifier_Localtime were to pass its argument through + # ParseModifierPart, this would work. + @echo ${%Y:L:localtime=${:U1593536400}} + +parse-errors: + @echo $@: + + # As of 2020-10-31, it is possible to pass negative time stamps + # to the :localtime modifier, resulting in dates before 1970. + # Going back 50 years in the past is not a practical use case for + # make. + : -1 becomes ${:L:localtime=-1}. + + # Spaces are allowed, not because it would make sense but just as + # a side-effect from using strtoul. + : space 1 becomes ${:L:localtime= 1}. + + # 0 means now; to get consistent test results, the actual value has + # to be normalized. + : 0 becomes ${:L:localtime=0:C,^... ... .. ..:..:.. 20..$,ok,W}. + + : 1 becomes ${:L:localtime=1}. + + : INT32_MAX becomes ${:L:localtime=2147483647}. + + # This may be different if time_t is still a 32-bit signed integer. + : INT32_MAX + 1 becomes ${:L:localtime=2147483648}. + + # Integer overflow. + # Because this modifier is implemented using strtoul, the parsed + # time is ULONG_MAX, which gets converted to -1. This results + # in a time stamp of the second before 1970 (in UTC) or 3599 seconds + # after New Year's Day in Europe/Berlin. + : overflow becomes ${:L:localtime=10000000000000000000000000000000}. + + # As of 2020-10-31, there is no error handling while parsing the + # :localtime modifier, thus no error message is printed. Parsing + # stops after the '=', and the remaining string is parsed for + # more variable modifiers. Because of the unknown modifier 'e', + # the whole variable value is discarded and thus not printed. + : letter becomes ${:L:localtime=error}. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-localtime.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.exp (revision 367461) @@ -0,0 +1,17 @@ +:+one+ +two+ +three+: +:x1y x2y x3y: +:x1y x2y x3y: +:mod-loop-varname: :x1y x2y x3y: :: +:x1y x2y x3y: +empty: :xy xy xy: +mod-loop-resolve:w1d2d3w w2i3w w1i2d3 2i${RES3}w w1d2d3 2i${RES3} 1i${RES2}w: +mod-loop-varname-dollar:(1) (2) (3). +mod-loop-varname-dollar:() () (). +mod-loop-varname-dollar:() () (). +mod-loop-dollar:1: +mod-loop-dollar:${word}$: +mod-loop-dollar:$3$: +mod-loop-dollar:$${word}$$: +mod-loop-dollar:$$5$$: +mod-loop-dollar:$$${word}$$$: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.mk (revision 367461) @@ -0,0 +1,102 @@ +# $NetBSD: varmod-loop.mk,v 1.5 2020/10/31 12:34:03 rillig Exp $ +# +# Tests for the :@var@...${var}...@ variable modifier. + +all: mod-loop-varname +all: mod-loop-resolve +all: mod-loop-varname-dollar +all: mod-loop-dollar + +# In the :@ modifier, the name of the loop variable can even be generated +# dynamically. There's no practical use-case for this, and hopefully nobody +# will ever depend on this, but technically it's possible. +# Therefore, in -dL mode, this is forbidden, see lint.mk. +mod-loop-varname: + @echo :${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@:Q}: + + # ":::" is a very creative variable name, unlikely in practice. + # The expression ${\:\:\:} would not work since backslashes can only + # be escaped in the modifiers, but not in the variable name. + @echo :${:U1 2 3:@:::@x${${:U\:\:\:}}y@}: + + # "@@" is another creative variable name. + @echo :${:U1 2 3:@\@\@@x${@@}y@}: + + # Even "@" works as a variable name since the variable is installed + # in the "current" scope, which in this case is the one from the + # target. + @echo :$@: :${:U1 2 3:@\@@x${@}y@}: :$@: + + # In extreme cases, even the backslash can be used as variable name. + # It needs to be doubled though. + @echo :${:U1 2 3:@\\@x${${:Ux:S,x,\\,}}y@}: + + # The variable name can technically be empty, and in this situation + # the variable value cannot be accessed since the empty variable is + # protected to always return an empty string. + @echo empty: :${:U1 2 3:@@x${}y@}: + +# The :@ modifier resolves the variables a little more often than expected. +# In particular, it resolves _all_ variables from the context, and not only +# the loop variable (in this case v). +# +# The d means direct reference, the i means indirect reference. +RESOLVE= ${RES1} $${RES1} +RES1= 1d${RES2} 1i$${RES2} +RES2= 2d${RES3} 2i$${RES3} +RES3= 3 + +mod-loop-resolve: + @echo $@:${RESOLVE:@v@w${v}w@:Q}: + +# Until 2020-07-20, the variable name of the :@ modifier could end with one +# or two dollar signs, which were silently ignored. +# There's no point in allowing a dollar sign in that position. +mod-loop-varname-dollar: + @echo $@:${1 2 3:L:@v$@($v)@:Q}. + @echo $@:${1 2 3:L:@v$$@($v)@:Q}. + @echo $@:${1 2 3:L:@v$$$@($v)@:Q}. + +# Demonstrate that it is possible to generate dollar characters using the +# :@ modifier. +# +# These are edge cases that could have resulted in a parse error as well +# since the $@ at the end could have been interpreted as a variable, which +# would mean a missing closing @ delimiter. +mod-loop-dollar: + @echo $@:${:U1:@word@${word}$@:Q}: + @echo $@:${:U2:@word@$${word}$$@:Q}: + @echo $@:${:U3:@word@$$${word}$$$@:Q}: + @echo $@:${:U4:@word@$$$${word}$$$$@:Q}: + @echo $@:${:U5:@word@$$$$${word}$$$$$@:Q}: + @echo $@:${:U6:@word@$$$$$${word}$$$$$$@:Q}: + +# It may happen that there are nested :@ modifiers that use the same name for +# for the loop variable. These modifiers influence each other. +# +# As of 2020-10-18, the :@ modifier is implemented by actually setting a +# variable in the context of the expression and deleting it again after the +# loop. This is different from the .for loops, which substitute the variable +# expression with ${:Uvalue}, leading to different unwanted side effects. +# +# To make the behavior more predictable, the :@ modifier should restore the +# loop variable to the value it had before the loop. This would result in +# the string "1a b c1 2a b c2 3a b c3", making the two loops independent. +.if ${:U1 2 3:@i@$i${:Ua b c:@i@$i@}${i:Uu}@} != "1a b cu 2a b cu 3a b cu" +. error +.endif + +# During the loop, the variable is actually defined and nonempty. +# If the loop were implemented in the same way as the .for loop, the variable +# would be neither defined nor nonempty since all expressions of the form +# ${var} would have been replaced with ${:Uword} before evaluating them. +.if defined(var) +. error +.endif +.if ${:Uword:@var@${defined(var):?def:undef} ${empty(var):?empty:nonempty}@} \ + != "def nonempty" +. error +.endif +.if defined(var) +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-loop.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.exp (revision 367461) @@ -0,0 +1,61 @@ +Global:SPECIALS = \: : \\ * \* +CondParser_Eval: ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} +Var_Parse: ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} with VARE_UNDEFERR|VARE_WANTRES +Applying ${SPECIALS:M...} to "\: : \\ * \*" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${:U}\: with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U} is "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[SPECIALS] for [\: : \\ * \*] is [\:] +ModifyWords: split "\: : \\ * \*" into 5 words +VarMatch [\:] [\:] +VarMatch [:] [\:] +VarMatch [\\] [\:] +VarMatch [*] [\:] +VarMatch [\*] [\:] +Result of ${SPECIALS:M${:U}\:} is ":" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${SPECIALS:M\:${:U}} with VARE_UNDEFERR|VARE_WANTRES +Applying ${SPECIALS:M...} to "\: : \\ * \*" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${:U} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U} is "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[SPECIALS] for [\: : \\ * \*] is [:] +ModifyWords: split "\: : \\ * \*" into 5 words +VarMatch [\:] [:] +VarMatch [:] [:] +VarMatch [\\] [:] +VarMatch [*] [:] +VarMatch [\*] [:] +Result of ${SPECIALS:M\:${:U}} is ":" (VARE_UNDEFERR|VARE_WANTRES, none, none) +lhs = ":", rhs = ":", op = != +Global:VALUES = : :: :\: +CondParser_Eval: ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} +Var_Parse: ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VALUES:M...} to ": :: :\:" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${:U:} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U} is "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[VALUES] for [: :: :\:] is [:] +ModifyWords: split ": :: :\:" into 3 words +VarMatch [:] [:] +VarMatch [::] [:] +VarMatch [:\:] [:] +Result of ${VALUES:M\:${:U\:}} is ":" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${VALUES:M${:U\:}\:} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VALUES:M...} to ": :: :\:" (VARE_UNDEFERR|VARE_WANTRES, none, none) +Var_Parse: ${:U\:}\: with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:U\:} is ":" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Pattern[VALUES] for [: :: :\:] is [:\:] +ModifyWords: split ": :: :\:" into 3 words +VarMatch [:] [:\:] +VarMatch [::] [:\:] +VarMatch [:\:] [:\:] +Result of ${VALUES:M${:U\:}\:} is "::" (VARE_UNDEFERR|VARE_WANTRES, none, none) +lhs = ":", rhs = "::", op = != +make: "varmod-match-escape.mk" line 42: warning: XXX: Oops +Global:.MAKEFLAGS = -r -k -d cv -d +Global:.MAKEFLAGS = -r -k -d cv -d 0 +make: "varmod-match-escape.mk" line 67: Dollar followed by nothing +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.mk (revision 367461) @@ -0,0 +1,72 @@ +# $NetBSD: varmod-match-escape.mk,v 1.5 2020/11/01 19:49:28 rillig Exp $ +# +# As of 2020-08-01, the :M and :N modifiers interpret backslashes differently, +# depending on whether there was a variable expression somewhere before the +# first backslash or not. See ApplyModifier_Match, "copy = TRUE". +# +# Apart from the different and possibly confusing debug output, there is no +# difference in behavior. When parsing the modifier text, only \{, \} and \: +# are unescaped, and in the pattern matching these have the same meaning as +# their plain variants '{', '}' and ':'. In the pattern matching from +# Str_Match, only \*, \? or \[ would make a noticeable difference. + +.MAKEFLAGS: -dcv + +SPECIALS= \: : \\ * \* +.if ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} +. warning unexpected +.endif + +# And now both cases combined: A single modifier with both an escaped ':' +# as well as a variable expression that expands to a ':'. +# +# XXX: As of 2020-11-01, when an escaped ':' occurs before the variable +# expression, the whole modifier text is subject to unescaping '\:' to ':', +# before the variable expression is expanded. This means that the '\:' in +# the variable expression is expanded as well, turning ${:U\:} into a simple +# ${:U:}, which silently expands to an empty string, instead of generating +# an error message. +# +# XXX: As of 2020-11-01, the modifier on the right-hand side of the +# comparison is parsed differently though. First, the variable expression +# is parsed, resulting in ':' and needSubst=TRUE. After that, the escaped +# ':' is seen, and this time, copy=TRUE is not executed but stays copy=FALSE. +# Therefore the escaped ':' is kept as-is, and the final pattern becomes +# ':\:'. +# +# If ApplyModifier_Match had used the same parsing algorithm as Var_Subst, +# both patterns would end up as '::'. +# +VALUES= : :: :\: +.if ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} +. warning XXX: Oops +.endif + +.MAKEFLAGS: -d0 + +# XXX: As of 2020-11-01, unlike all other variable modifiers, a '$' in the +# :M and :N modifiers is written as '$$', not as '\$'. This is confusing, +# undocumented and hopefully not used in practice. +.if ${:U\$:M$$} != "\$" +. error +.endif + +# XXX: As of 2020-11-01, unlike all other variable modifiers, '\$' is not +# parsed as an escaped '$'. Instead, ApplyModifier_Match first scans for +# the ':' at the end of the modifier, which results in the pattern '\$'. +# No unescaping takes place since the pattern neither contained '\:' nor +# '\{' nor '\}'. But the text is expanded, and a lonely '$' at the end +# is silently discarded. The resulting expanded pattern is thus '\', that +# is a single backslash. +.if ${:U\$:M\$} != "" +. error +.endif + +# In lint mode, the case of a lonely '$' is covered with an error message. +.MAKEFLAGS: -dL +.if ${:U\$:M\$} != "" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match-escape.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.exp (revision 367461) @@ -0,0 +1,12 @@ +CondParser_Eval: ${NUMBERS:M[A-Z]*} != "One Two Three Four" +lhs = "One Two Three Four", rhs = "One Two Three Four", op = != +CondParser_Eval: ${NUMBERS:M[^A-Z]*} != "five six seven" +lhs = "five six seven", rhs = "five six seven", op = != +CondParser_Eval: ${NUMBERS:M[^s]*[ex]} != "One Three five" +lhs = "One Three five", rhs = "One Three five", op = != +CondParser_Eval: ${:U****************:M****************b} +CondParser_Eval: ${:Ua \$ sign:M*$$*} != "\$" +lhs = "$", rhs = "$", op = != +CondParser_Eval: ${:Ua \$ sign any-asterisk:M*\$*} != "any-asterisk" +lhs = "any-asterisk", rhs = "any-asterisk", op = != +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.mk (revision 367461) @@ -0,0 +1,55 @@ +# $NetBSD: varmod-match.mk,v 1.5 2020/09/13 05:36:26 rillig Exp $ +# +# Tests for the :M variable modifier, which filters words that match the +# given pattern. +# +# See ApplyModifier_Match and ModifyWord_Match for the implementation. + +.MAKEFLAGS: -dc + +NUMBERS= One Two Three Four five six seven + +# Only keep words that start with an uppercase letter. +.if ${NUMBERS:M[A-Z]*} != "One Two Three Four" +. error +.endif + +# Only keep words that start with a character other than an uppercase letter. +.if ${NUMBERS:M[^A-Z]*} != "five six seven" +. error +.endif + +# Only keep words that don't start with s and at the same time end with +# either of [ex]. +# +# This test case ensures that the negation from the first character class +# does not propagate to the second character class. +.if ${NUMBERS:M[^s]*[ex]} != "One Three five" +. error +.endif + +# Before 2020-06-13, this expression took quite a long time in Str_Match, +# calling itself 601080390 times for 16 asterisks. +.if ${:U****************:M****************b} +.endif + +# To match a dollar sign in a word, double it. +# +# This is different from the :S and :C variable modifiers, where a '$' +# has to be escaped as '\$'. +.if ${:Ua \$ sign:M*$$*} != "\$" +. error +.endif + +# In the :M modifier, '\$' does not escape a dollar. Instead it is +# interpreted as a backslash followed by whatever expression the +# '$' starts. +# +# This differs from the :S, :C and several other variable modifiers. +${:U*}= asterisk +.if ${:Ua \$ sign any-asterisk:M*\$*} != "any-asterisk" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-match.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.mk (revision 367461) @@ -0,0 +1,13 @@ +# $NetBSD: varmod-order-reverse.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :Or variable modifier, which returns the words, sorted in +# descending order. + +NUMBERS= one two three four five six seven eight nine ten + +.if ${NUMBERS:Or} != "two three ten six seven one nine four five eight" +. error ${NUMBERS:Or} +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.mk (revision 367461) @@ -0,0 +1,41 @@ +# $NetBSD: varmod-order-shuffle.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :Ox variable modifier, which returns the words of the +# variable, shuffled. +# +# As of 2020-08-16, make uses random(3) seeded by the current time in seconds. +# This makes the random numbers completely predictable since there is no other +# part of make that uses random numbers. +# +# Tags: probabilistic + +NUMBERS= one two three four five six seven eight nine ten + +# Note that 1 in every 10! trials two independently generated +# randomized orderings will be the same. The test framework doesn't +# support checking probabilistic output, so we accept that each of the +# 3 :Ox tests will incorrectly fail with probability 2.756E-7, which +# lets the whole test fail once in 1.209.600 runs, on average. + +# Create two shuffles using the := assignment operator. +shuffled1:= ${NUMBERS:Ox} +shuffled2:= ${NUMBERS:Ox} +.if ${shuffled1} == ${shuffled2} +. error ${shuffled1} == ${shuffled2} +.endif + +# Sorting the list before shuffling it has no effect. +shuffled1:= ${NUMBERS:O:Ox} +shuffled2:= ${NUMBERS:O:Ox} +.if ${shuffled1} == ${shuffled2} +. error ${shuffled1} == ${shuffled2} +.endif + +# Sorting after shuffling must produce the original numbers. +sorted:= ${NUMBERS:Ox:O} +.if ${sorted} != ${NUMBERS:O} +. error ${sorted} != ${NUMBERS:O} +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: varmod-order.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :O variable modifier, which returns the words, sorted in +# ascending order. + +NUMBERS= one two three four five six seven eight nine ten + +.if ${NUMBERS:O} != "eight five four nine one seven six ten three two" +. error ${NUMBERS:O} +.endif + +# Unknown modifier "OX" +_:= ${NUMBERS:OX} + +# Unknown modifier "OxXX" +_:= ${NUMBERS:OxXX} + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.mk (revision 367461) @@ -0,0 +1,21 @@ +# $NetBSD: varmod-quote.mk,v 1.3 2020/10/29 19:07:45 rillig Exp $ +# +# Tests for the :Q variable modifier, which quotes the variable value +# to be used in a shell program. + +# Any characters that might be interpreted by the shell are escaped. +# The set of escaped characters is the same, no matter which shell (sh, csh, +# ksh) is in effect. +.if ${:Ua b c:Q} != "a\\ b\\ c" +. error +.endif + +# The quote modifier only applies if the whole modifier name is "Q". +# There is no "Qshell" or "Qawk" or "Qregex" or even "Qhtml" variant. +# All strings except the plain "Q" are interpreted as SysV modifier. +.if ${:Ua.Qshell:Qshell=replaced} != "a.replaced" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.exp (revision 367461) @@ -0,0 +1,14 @@ +make: "varmod-range.mk" line 53: Invalid number: x}Rest" != "Rest" + +make: "varmod-range.mk" line 53: Malformed conditional ("${:U:range=x}Rest" != "Rest") +make: Unknown modifier 'x' +make: "varmod-range.mk" line 62: Malformed conditional ("${:U:range=0x0}Rest" != "Rest") +make: Unknown modifier 'r' +make: "varmod-range.mk" line 78: Malformed conditional ("${a b c:L:rang}Rest" != "Rest") +make: Unknown modifier 'r' +make: "varmod-range.mk" line 85: Malformed conditional ("${a b c:L:rango}Rest" != "Rest") +make: Unknown modifier 'r' +make: "varmod-range.mk" line 92: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest") +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.mk (revision 367461) @@ -0,0 +1,98 @@ +# $NetBSD: varmod-range.mk,v 1.7 2020/11/01 14:36:25 rillig Exp $ +# +# Tests for the :range variable modifier, which generates sequences +# of integers from the given range. +# +# See also: +# modword.mk + +# The :range modifier generates a sequence of integers, one number per +# word of the variable expression's value. +.if ${a b c:L:range} != "1 2 3" +. error +.endif + +# To preserve spaces in a word, they can be enclosed in quotes, just like +# everywhere else. +.if ${:U first "the second word" third 4 :range} != "1 2 3 4" +. error +.endif + +# The :range modifier takes the number of words from the value of the +# variable expression. If that expression is undefined, the range is +# undefined as well. This should not come as a surprise. +.if "${:range}" != "" +. error +.endif + +# The :range modifier can be given a parameter, which makes the generated +# range independent from the value or the name of the variable expression. +# +# XXX: As of 2020-09-27, the :range=... modifier does not turn the undefined +# expression into a defined one. This looks like an oversight. +.if "${:range=5}" != "" +. error +.endif + +# Negative ranges don't make sense. +# As of 2020-11-01, they are accepted though, using up all available memory. +#.if "${:range=-1}" +#. error +#.else +#. error +#.endif + +# The :range modifier requires a number as parameter. +# +# Until 2020-11-01, the parser tried to read the 'x' as a number, failed and +# stopped there. It then tried to parse the next modifier at that point, +# which failed with the message "Unknown modifier". +# +# Since 2020-11-01, the parser issues a more precise "Invalid number" error +# instead. +.if "${:U:range=x}Rest" != "Rest" +. error +.else +. error +.endif + +# The upper limit of the range must always be given in decimal. +# This parse error stops at the 'x', trying to parse it as a variable +# modifier. +.if "${:U:range=0x0}Rest" != "Rest" +. error +.else +. error +.endif + +# As of 2020-11-01, numeric overflow is not detected. +# Since strtoul returns ULONG_MAX in such a case, it is interpreted as a +# very large number, consuming all available memory. +#.if "${:U:range=18446744073709551619}Rest" != "Rest" +#. error +#.else +#. error +#.endif + +# modifier name too short +.if "${a b c:L:rang}Rest" != "Rest" +. error +.else +. error +.endif + +# misspelled modifier name +.if "${a b c:L:rango}Rest" != "Rest" +. error +.else +. error +.endif + +# modifier name too long +.if "${a b c:L:ranger}Rest" != "Rest" +. error +.else +. error +.endif + +all: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-range.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.mk (revision 367461) @@ -0,0 +1,104 @@ +# $NetBSD: varmod-subst-regex.mk,v 1.5 2020/10/31 12:20:36 rillig Exp $ +# +# Tests for the :C,from,to, variable modifier. + +all: mod-regex-compile-error +all: mod-regex-limits +all: mod-regex-errors + +# The variable expression expands to 4 words. Of these words, none matches +# the regular expression "a b" since these words don't contain any +# whitespace. +.if ${:Ua b b c:C,a b,,} != "a b b c" +. error +.endif + +# Using the '1' modifier does not change anything. The '1' modifier just +# means to apply at most 1 replacement in the whole variable expression. +.if ${:Ua b b c:C,a b,,1} != "a b b c" +. error +.endif + +# The 'W' modifier treats the whole variable value as a single big word, +# containing whitespace. This big word matches the regular expression, +# therefore it gets replaced. Whitespace is preserved after replacing. +.if ${:Ua b b c:C,a b,,W} != " b c" +. error +.endif + +# The 'g' modifier does not have any effect here since each of the words +# contains the character 'b' a single time. +.if ${:Ua b b c:C,b,,g} != "a c" +. error +.endif + +# The first :C modifier has the 'W' modifier, which makes the whole +# expression a single word. The 'g' modifier then replaces all occurrences +# of "1 2" with "___". The 'W' modifier only applies to this single :C +# modifier. This is demonstrated by the :C modifier that follows. If the +# 'W' modifier would be preserved, only a single underscore would have been +# replaced with an 'x'. +.if ${:U1 2 3 1 2 3:C,1 2,___,Wg:C,_,x,} != "x__ 3 x__ 3" +. error +.endif + +# The regular expression does not match in the first word. +# It matches once in the second word, and the \0\0 doubles that word. +# In the third word, the regular expression matches as early as possible, +# and since the matches must not overlap, the next possible match would +# start at the 6, but at that point, there is only one character left, +# and that cannot match the regular expression "..". Therefore only the +# "45" is doubled in the third word. +.if ${:U1 23 456:C,..,\0\0,} != "1 2323 45456" +. error +.endif + +# The modifier '1' applies the replacement at most once, across the whole +# expression value, no matter whether it is a single big word or many small +# words. +# +# Up to 2020-08-28, the manual page said that the modifiers '1' and 'g' +# were orthogonal, which was wrong. It doesn't make sense to specify both +# 'g' and '1' at the same time. +.if ${:U12345 12345:C,.,\0\0,1} != "112345 12345" +. error +.endif + +# A regular expression that matches the empty string applies before every +# single character of the word. +# XXX: Most other places where regular expression are used match at the end +# of the string as well. +.if ${:U1a2b3c:C,a*,*,g} != "*1**2*b*3*c" +. error +.endif + +# A dot in the regular expression matches any character, even a newline. +# In most other contexts where regular expressions are used, a dot matches +# any character except newline. In make, regcomp is called without +# REG_NEWLINE, thus newline is an ordinary character. +.if ${:U"${.newline}":C,.,.,g} != "..." +. error +.endif + +# Multiple asterisks form an invalid regular expression. This produces an +# error message and (as of 2020-08-28) stops parsing in the middle of the +# variable expression. The unparsed part of the expression is then copied +# verbatim to the output, which is unexpected and can lead to strange shell +# commands being run. +mod-regex-compile-error: + @echo $@: ${:Uword1 word2:C,****,____,g:C,word,____,:Q}. + +# These tests generate error messages but as of 2020-08-28 just continue +# parsing and execution as if nothing bad had happened. +mod-regex-limits: + @echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q} + @echo $@:11-ok:${:U1 23 456:C,(.).,\1\1,:Q} + @echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q} + @echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q} + @echo $@:22-ok:${:U1 23 456:C,(.)(.),\2\2,:Q} + # The :C modifier only handles single-digit capturing groups, + # which is more than enough for daily use. + @echo $@:capture:${:UabcdefghijABCDEFGHIJrest:C,(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.),\9\8\7\6\5\4\3\2\1\0\10\11\12,} + +mod-regex-errors: + @echo $@: ${UNDEF:Uvalue:C,[,,} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.mk (revision 367461) @@ -0,0 +1,153 @@ +# $NetBSD: varmod-subst.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :S,from,to, variable modifier. + +all: mod-subst +all: mod-subst-delimiter +all: mod-subst-chain +all: mod-subst-dollar + +WORDS= sequences of letters +.if ${WORDS:S,,,} != ${WORDS} +. warning The empty pattern matches something. +.endif +.if ${WORDS:S,e,*,1} != "s*quences of letters" +. warning The :S modifier flag '1' is not applied exactly once. +.endif +.if ${WORDS:S,f,*,1} != "sequences o* letters" +. warning The :S modifier flag '1' is only applied to the first word,\ + not to the first occurrence. +.endif +.if ${WORDS:S,e,*,} != "s*quences of l*tters" +. warning The :S modifier does not replace every first match per word. +.endif +.if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs" +. warning The :S modifier flag 'g' does not replace every occurrence. +.endif +.if ${WORDS:S,^sequ,occurr,} != "occurrences of letters" +. warning The :S modifier fails for a short match anchored at the start. +.endif +.if ${WORDS:S,^of,with,} != "sequences with letters" +. warning The :S modifier fails for an exact match anchored at the start. +.endif +.if ${WORDS:S,^office,does not match,} != ${WORDS} +. warning The :S modifier matches a too long pattern anchored at the start. +.endif +.if ${WORDS:S,f$,r,} != "sequences or letters" +. warning The :S modifier fails for a short match anchored at the end. +.endif +.if ${WORDS:S,s$,,} != "sequence of letter" +. warning The :S modifier fails to replace one occurrence per word. +.endif +.if ${WORDS:S,of$,,} != "sequences letters" +. warning The :S modifier fails for an exact match anchored at the end. +.endif +.if ${WORDS:S,eof$,,} != ${WORDS} +. warning The :S modifier matches a too long pattern anchored at the end. +.endif +.if ${WORDS:S,^of$,,} != "sequences letters" +. warning The :S modifier does not match a word anchored at both ends. +.endif +.if ${WORDS:S,^o$,,} != ${WORDS} +. warning The :S modifier matches a prefix anchored at both ends. +.endif +.if ${WORDS:S,^f$,,} != ${WORDS} +. warning The :S modifier matches a suffix anchored at both ends. +.endif +.if ${WORDS:S,^eof$,,} != ${WORDS} +. warning The :S modifier matches a too long prefix anchored at both ends. +.endif +.if ${WORDS:S,^office$,,} != ${WORDS} +. warning The :S modifier matches a too long suffix anchored at both ends. +.endif + +mod-subst: + @echo $@: + @echo :${:Ua b b c:S,a b,,:Q}: + @echo :${:Ua b b c:S,a b,,1:Q}: + @echo :${:Ua b b c:S,a b,,W:Q}: + @echo :${:Ua b b c:S,b,,g:Q}: + @echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}: + @echo ${:U12345:S,,sep,g:Q} + +# The :S and :C modifiers accept an arbitrary character as the delimiter, +# including characters that are otherwise used as escape characters or +# interpreted in a special way. This can be used to confuse humans. +mod-subst-delimiter: + @echo $@: + @echo ${:U1 2 3:S 2 two :Q} horizontal tabulator + @echo ${:U1 2 3:S 2 two :Q} space + @echo ${:U1 2 3:S!2!two!:Q} exclamation mark + @echo ${:U1 2 3:S"2"two":Q} double quotes + # In shell command lines, the hash does not need to be escaped. + # It needs to be escaped in variable assignment lines though. + @echo ${:U1 2 3:S#2#two#:Q} hash + @echo ${:U1 2 3:S$2$two$:Q} dollar + @echo ${:U1 2 3:S%2%two%:Q} percent + @echo ${:U1 2 3:S'2'two':Q} apostrophe + @echo ${:U1 2 3:S(2(two(:Q} opening parenthesis + @echo ${:U1 2 3:S)2)two):Q} closing parenthesis + @echo ${:U1 2 3:S121two1:Q} digit + @echo ${:U1 2 3:S:2:two::Q} colon + @echo ${:U1 2 3:S<22>two>:Q} greater than sign + @echo ${:U1 2 3:S?2?two?:Q} question mark + @echo ${:U1 2 3:S@2@two@:Q} at + @echo ${:U1 2 3:Sa2atwoa:Q} letter + @echo ${:U1 2 3:S[2[two[:Q} opening bracket + @echo ${:U1 2 3:S\2\two\:Q} backslash + @echo ${:U1 2 3:S]2]two]:Q} closing bracket + @echo ${:U1 2 3:S^2^two^:Q} caret + @echo ${:U1 2 3:S{2{two{:Q} opening brace + @echo ${:U1 2 3:S|2|two|:Q} vertical line + @echo ${:U1 2 3:S}2}two}:Q} closing brace + @echo ${:U1 2 3:S~2~two~:Q} tilde + +# The :S and :C modifiers can be chained without a separating ':'. +# This is not documented in the manual page. +# It works because ApplyModifier_Subst scans for the known modifiers g1W +# and then just returns to ApplyModifiers. There, the colon is optionally +# skipped (see the *st.next == ':' at the end of the loop). +# +# Most other modifiers cannot be chained since their parsers skip until +# the next ':' or '}' or ')'. +mod-subst-chain: + @echo $@: + @echo ${:Ua b c:S,a,A,S,b,B,}. + # There is no 'i' modifier for the :S or :C modifiers. + # The error message is "make: Unknown modifier 'i'", which is + # kind of correct, although it is mixing the terms for variable + # modifiers with the matching modifiers. + @echo ${:Uvalue:S,a,x,i}. + +# No matter how many dollar characters there are, they all get merged +# into a single dollar by the :S modifier. +# +# As of 2020-08-09, this is because ParseModifierPart sees a '$' and +# calls Var_Parse to expand the variable. In all other places, the "$$" +# is handled outside of Var_Parse. Var_Parse therefore considers "$$" +# one of the "really stupid names", skips the first dollar, and parsing +# continues with the next character. This repeats for the other dollar +# signs, except the one before the delimiter. That one is handled by +# the code that optionally interprets the '$' as the end-anchor in the +# first part of the :S modifier. That code doesn't call Var_Parse but +# simply copies the dollar to the result. +mod-subst-dollar: + @echo $@:${:U1:S,^,$,:Q}: + @echo $@:${:U2:S,^,$$,:Q}: + @echo $@:${:U3:S,^,$$$,:Q}: + @echo $@:${:U4:S,^,$$$$,:Q}: + @echo $@:${:U5:S,^,$$$$$,:Q}: + @echo $@:${:U6:S,^,$$$$$$,:Q}: + @echo $@:${:U7:S,^,$$$$$$$,:Q}: + @echo $@:${:U8:S,^,$$$$$$$$,:Q}: + @echo $@:${:U40:S,^,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$,:Q}: +# This generates no dollar at all: + @echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}: +# Here is an alternative way to generate dollar characters. +# It's unexpectedly complicated though. + @echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}: +# In modifiers, dollars are escaped using the backslash, not using another +# dollar sign. Therefore, creating a dollar sign is pretty simple: + @echo $@:${:Ugood3:S,^,\$\$\$,:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.exp (revision 367461) @@ -0,0 +1,5 @@ +make: Unfinished modifier for word203 ('=' missing) +make: "varmod-sysv.mk" line 210: Malformed conditional (${word203:L:from${:D=}to}) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.mk (revision 367461) @@ -0,0 +1,237 @@ +# $NetBSD: varmod-sysv.mk,v 1.11 2020/11/01 22:28:52 rillig Exp $ +# +# Tests for the ${VAR:from=to} variable modifier, which replaces the suffix +# "from" with "to". It can also use '%' as a wildcard. +# +# This modifier is applied when the other modifiers don't match exactly. +# +# See ApplyModifier_SysV. + +# A typical use case for the :from=to modifier is conversion of filename +# extensions. +.if ${src.c:L:.c=.o} != "src.o" +. error +.endif + +# The modifier applies to each word on its own. +.if ${one.c two.c three.c:L:.c=.o} != "one.o two.o three.o" +. error +.endif + +# Words that don't match the pattern are passed unmodified. +.if ${src.c src.h:L:.c=.o} != "src.o src.h" +. error +.endif + +# The :from=to modifier is therefore often combined with the :M modifier. +.if ${src.c src.h:L:M*.c:.c=.o} != "src.o" +. error +.endif + +# Another use case for the :from=to modifier is to append a suffix to each +# word. In this case, the "from" string is empty, therefore it always +# matches. The same effect can be achieved with the :S,$,teen, modifier. +.if ${four six seven nine:L:=teen} != "fourteen sixteen seventeen nineteen" +. error +.endif + +# The :from=to modifier can also be used to surround each word by strings. +# It might be tempting to use this for enclosing a string in quotes for the +# shell, but that's the job of the :Q modifier. +.if ${one two three:L:%=(%)} != "(one) (two) (three)" +. error +.endif + +# When the :from=to modifier is parsed, it lasts until the closing brace +# or parenthesis. The :Q in the below expression may look like a modifier +# but isn't. It is part of the replacement string. +.if ${a b c d e:L:%a=x:Q} != "x:Q b c d e" +. error +.endif + +# In the :from=to modifier, both parts can contain variable expressions. +.if ${one two:L:${:Uone}=${:U1}} != "1 two" +. error +.endif + +# In the :from=to modifier, the "from" part is expanded exactly once. +.if ${:U\$ \$\$ \$\$\$\$:${:U\$\$\$\$}=4} != "\$ \$\$ 4" +. error +.endif + +# In the :from=to modifier, the "to" part is expanded exactly twice. +# XXX: The right-hand side should be expanded only once. +# XXX: It's hard to get the escaping correct here, and to read that. +# XXX: It's not intuitive why the closing brace must be escaped but not +# the opening brace. +.if ${:U1 2 4:4=${:Uonce\${\:Utwice\}}} != "1 2 oncetwice" +. error +.endif + +# The replacement string can contain spaces, thereby changing the number +# of words in the variable expression. +.if ${In:L:%=% ${:Uthe Sun}} != "In the Sun" +. error +.endif + +# If the variable value is empty, it is debatable whether it consists of a +# single empty word, or no word at all. The :from=to modifier treats it as +# no word at all. +.if ${:L:=suffix} != "" +. error +.endif + +# If the variable value is empty, it is debatable whether it consists of a +# single empty word, or no word at all. The :from=to modifier treats it as +# no word at all. +.if ${:L:%=suffix} != "" +. error +.endif + +# Before 2020-07-19, an ampersand could be used in the replacement part +# of a SysV substitution modifier, and it was replaced with the whole match, +# just like in the :S modifier. +# +# This was probably a copy-and-paste mistake since the code for the SysV +# modifier looked a lot like the code for the :S and :C modifiers. +# The ampersand is not mentioned in the manual page. +.if ${a.bcd.e:L:a.%=%} != "bcd.e" +. error +.endif +# Before 2020-07-19, the result of the expression was "a.bcd.e". +.if ${a.bcd.e:L:a.%=&} != "&" +. error +.endif + +# Before 2020-07-20, when a SysV modifier was parsed, a single dollar +# before the '=' was parsed (but not interpreted) as an anchor. +# Parsing something without then evaluating it accordingly doesn't make +# sense. +.if ${value:L:e$=x} != "value" +. error +.endif +# Before 2020-07-20, the modifier ":e$=x" was parsed as having a left-hand +# side "e" and a right-hand side "x". The dollar was parsed (but not +# interpreted) as 'anchor at the end'. Therefore the modifier was equivalent +# to ":e=x", which doesn't match the string "value$". Therefore the whole +# expression evaluated to "value$". +.if ${${:Uvalue\$}:L:e$=x} != "valux" +. error +.endif +.if ${value:L:e=x} != "valux" +. error +.endif + +# Words that don't match are copied unmodified. +.if ${:Ufile.c file.h:%.c=%.cpp} != "file.cpp file.h" +. error +.endif + +# The % placeholder can be anywhere in the string, it doesn't have to be at +# the beginning of the pattern. +.if ${:Ufile.c other.c:file.%=renamed.%} != "renamed.c other.c" +. error +.endif + +# It's also possible to modify each word by replacing the prefix and adding +# a suffix. +.if ${one two:L:o%=a%w} != "anew two" +. error +.endif + +# Each word gets the suffix "X" appended. +.if ${one two:L:=X} != "oneX twoX" +. error +.endif + +# The suffix "o" is replaced with "X". +.if ${one two:L:o=X} != "one twX" +. error +.endif + +# The suffix "o" is replaced with nothing. +.if ${one two:L:o=} != "one tw" +. error +.endif + +# The suffix "o" is replaced with a literal percent. The percent is only +# a wildcard when it appears on the left-hand side. +.if ${one two:L:o=%} != "one tw%" +. error +.endif + +# Each word with the suffix "o" is replaced with "X". The percent is a +# wildcard even though the right-hand side does not contain another percent. +.if ${one two:L:%o=X} != "one X" +. error +.endif + +# Each word with the prefix "o" is replaced with "X". The percent is a +# wildcard even though the right-hand side does not contain another percent. +.if ${one two:L:o%=X} != "X two" +. error +.endif + +# For each word with the prefix "o" and the suffix "e", the whole word is +# replaced with "X". +.if ${one two oe oxen:L:o%e=X} != "X two X oxen" +. error +.endif + +# Only the first '%' is the wildcard. +.if ${one two o%e other%e:L:o%%e=X} != "one two X X" +. error +.endif + +# In the replacement, only the first '%' is the placeholder, all others +# are literal percent characters. +.if ${one two:L:%=%%} != "one% two%" +. error +.endif + +# In the word "one", only a prefix of the pattern suffix "nes" matches, +# the whole word is too short. Therefore it doesn't match. +.if ${one two:L:%nes=%xxx} != "one two" +. error +.endif + +# The :from=to modifier can be used to replace both the prefix and a suffix +# of a word with other strings. This is not possible with a single :S +# modifier, and using a :C modifier for the same task looks more complicated +# in many cases. +.if ${prefix-middle-suffix:L:prefix-%-suffix=p-%-s} != "p-middle-s" +. error +.endif + +# This is not a SysV modifier since the nested variable expression expands +# to an empty string. The '=' in it should be irrelevant during parsing. +# As of 2020-11-01, this seemingly correct modifier leads to a parse error. +# XXX +.if ${word203:L:from${:D=}to} +. error +.endif + +# XXX: This specially constructed case demonstrates that the SysV modifier +# lasts longer than expected. The whole expression initially has the value +# "fromto}...". The next modifier is a SysV modifier. ApplyModifier_SysV +# parses the modifier as "from${:D=}to", ending at the '}'. Next, the two +# parts of the modifier are parsed using ParseModifierPart, which scans +# differently, properly handling nested variable expressions. The two parts +# are now "fromto}..." and "replaced". +.if "${:Ufromto\}...:from${:D=}to}...=replaced}" != "replaced" +. error +.endif + +# As of 2020-10-06, the right-hand side of the SysV modifier is expanded +# twice. The first expansion happens in ApplyModifier_SysV, where the +# modifier is split into its two parts. The second expansion happens +# when each word is replaced in ModifyWord_SYSVSubst. +# XXX: This is unexpected. Add more test case to demonstrate the effects +# of removing one of the expansions. +VALUE= value +INDIRECT= 1:${VALUE} 2:$${VALUE} 4:$$$${VALUE} +.if ${x:L:x=${INDIRECT}} != "1:value 2:value 4:\${VALUE}" +. error +.endif + +all: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-sysv.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: varmod-to-lower.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :tl variable modifier, which returns the words in the +# variable value, converted to lowercase. + +.if ${:UUPPER:tl} != "upper" +. error +.endif + +.if ${:Ulower:tl} != "lower" +. error +.endif + +.if ${:UMixeD case.:tl} != "mixed case." +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.exp (revision 367461) @@ -0,0 +1,21 @@ +make: "varmod-to-separator.mk" line 107: Invalid character number: 400:tu} + +make: "varmod-to-separator.mk" line 107: Malformed conditional (${WORDS:[1..3]:ts\400:tu}) +make: "varmod-to-separator.mk" line 121: Invalid character number: 100:tu} + +make: "varmod-to-separator.mk" line 121: Malformed conditional (${WORDS:[1..3]:ts\x100:tu}) +make: Bad modifier `:ts\-300' for WORDS +make: "varmod-to-separator.mk" line 128: Malformed conditional (${WORDS:[1..3]:ts\-300:tu}) +make: Bad modifier `:ts\8' for 1 2 3 +make: "varmod-to-separator.mk" line 136: Malformed conditional (${1 2 3:L:ts\8:tu}) +make: Bad modifier `:ts\100L' for 1 2 3 +make: "varmod-to-separator.mk" line 143: Malformed conditional (${1 2 3:L:ts\100L}) +make: Bad modifier `:ts\x40g' for 1 2 3 +make: "varmod-to-separator.mk" line 150: Malformed conditional (${1 2 3:L:ts\x40g}) +make: Bad modifier `:tx' for WORDS +make: "varmod-to-separator.mk" line 158: Malformed conditional (${WORDS:tx} != "anything") +make: Bad modifier `:t\X' for WORDS +make: "varmod-to-separator.mk" line 165: Malformed conditional (${WORDS:t\X} != "anything") +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.mk (revision 367461) @@ -0,0 +1,169 @@ +# $NetBSD: varmod-to-separator.mk,v 1.6 2020/11/01 14:36:25 rillig Exp $ +# +# Tests for the :ts variable modifier, which joins the words of the variable +# using an arbitrary character as word separator. + +WORDS= one two three four five six + +# The words are separated by a single space, just as usual. +.if ${WORDS:ts } != "one two three four five six" +. warning Space as separator does not work. +.endif + +# The separator can be an arbitrary character, for example a comma. +.if ${WORDS:ts,} != "one,two,three,four,five,six" +. warning Comma as separator does not work. +.endif + +# After the :ts modifier, other modifiers can follow. +.if ${WORDS:ts/:tu} != "ONE/TWO/THREE/FOUR/FIVE/SIX" +. warning Chaining modifiers does not work. +.endif + +# To use the ':' as the separator, just write it normally. +# The first colon is the separator, the second ends the modifier. +.if ${WORDS:ts::tu} != "ONE:TWO:THREE:FOUR:FIVE:SIX" +. warning Colon as separator does not work. +.endif + +# When there is just a colon but no other character, the words are +# "separated" by an empty string, that is, they are all squashed +# together. +.if ${WORDS:ts:tu} != "ONETWOTHREEFOURFIVESIX" +. warning Colon as separator does not work. +.endif + +# Applying the :tu modifier first and then the :ts modifier does not change +# anything since neither of these modifiers is related to how the string is +# split into words. Beware of separating the words using a single or double +# quote though, or other special characters like dollar or backslash. +# +# This example also demonstrates that the closing brace is not interpreted +# as a separator, but as the closing delimiter of the whole variable +# expression. +.if ${WORDS:tu:ts} != "ONETWOTHREEFOURFIVESIX" +. warning Colon as separator does not work. +.endif + +# The '}' plays the same role as the ':' in the preceding examples. +# Since there is a single character before it, that character is taken as +# the separator. +.if ${WORDS:tu:ts/} != "ONE/TWO/THREE/FOUR/FIVE/SIX" +. warning Colon as separator does not work. +.endif + +# Now it gets interesting and ambiguous: The separator could either be empty +# since it is followed by a colon. Or it could be the colon since that +# colon is followed by the closing brace. It's the latter case. +.if ${WORDS:ts:} != "one:two:three:four:five:six" +. warning Colon followed by closing brace does not work. +.endif + +# As in the ${WORDS:tu:ts} example above, the separator is empty. +.if ${WORDS:ts} != "onetwothreefourfivesix" +. warning Empty separator before closing brace does not work. +.endif + +# The :ts modifier can be followed by other modifiers. +.if ${WORDS:ts:S/two/2/} != "one2threefourfivesix" +. warning Separator followed by :S modifier does not work. +.endif + +# The :ts modifier can follow other modifiers. +.if ${WORDS:S/two/2/:ts} != "one2threefourfivesix" +. warning :S modifier followed by :ts modifier does not work. +.endif + +# The :ts modifier with an actual separator can be followed by other +# modifiers. +.if ${WORDS:ts/:S/two/2/} != "one/2/three/four/five/six" +. warning The :ts modifier followed by an :S modifier does not work. +.endif + +# The separator can be \n, which is a newline. +.if ${WORDS:[1..3]:ts\n} != "one${.newline}two${.newline}three" +. warning The separator \n does not produce a newline. +.endif + +# The separator can be \t, which is a tab. +.if ${WORDS:[1..3]:ts\t} != "one two three" +. warning The separator \t does not produce a tab. +.endif + +# The separator can be given as octal number. +.if ${WORDS:[1..3]:ts\012:tu} != "ONE${.newline}TWO${.newline}THREE" +. warning The separator \012 is not interpreted in octal ASCII. +.endif + +# The octal number can have as many digits as it wants. +.if ${WORDS:[1..2]:ts\000000000000000000000000012:tu} != "ONE${.newline}TWO" +. warning The separator \012 cannot have many leading zeroes. +.endif + +# The value of the separator character must not be outside the value space +# for an unsigned character though. +# +# Since 2020-11-01, these out-of-bounds values are rejected. +.if ${WORDS:[1..3]:ts\400:tu} +. warning The separator \400 is accepted even though it is out of bounds. +.else +. warning The separator \400 is accepted even though it is out of bounds. +.endif + +# The separator can be given as hexadecimal number. +.if ${WORDS:[1..3]:ts\xa:tu} != "ONE${.newline}TWO${.newline}THREE" +. warning The separator \xa is not interpreted in hexadecimal ASCII. +.endif + +# The hexadecimal number must be in the range of an unsigned char. +# +# Since 2020-11-01, these out-of-bounds values are rejected. +.if ${WORDS:[1..3]:ts\x100:tu} +. warning The separator \x100 is accepted even though it is out of bounds. +.else +. warning The separator \x100 is accepted even though it is out of bounds. +.endif + +# Negative numbers are not allowed for the separator character. +.if ${WORDS:[1..3]:ts\-300:tu} +. warning The separator \-300 is accepted even though it is negative. +.else +. warning The separator \-300 is accepted even though it is negative. +.endif + +# The character number is interpreted as octal number by default. +# The digit '8' is not an octal digit though. +.if ${1 2 3:L:ts\8:tu} +. warning The separator \8 is accepted even though it is not octal. +.else +. warning The separator \8 is accepted even though it is not octal. +.endif + +# Trailing characters after the octal character number are rejected. +.if ${1 2 3:L:ts\100L} +. warning The separator \100L is accepted even though it contains an 'L'. +.else +. warning The separator \100L is accepted even though it contains an 'L'. +.endif + +# Trailing characters after the hexadecimal character number are rejected. +.if ${1 2 3:L:ts\x40g} +. warning The separator \x40g is accepted even though it contains a 'g'. +.else +. warning The separator \x40g is accepted even though it contains a 'g'. +.endif + + +# In the :t modifier, the :t must be followed by any of A, l, s, u. +.if ${WORDS:tx} != "anything" +. info This line is not reached because of the malformed condition. +. info If this line were reached, it would be visible in the -dcpv log. +.endif + +# After the backslash, only n, t, an octal number, or x and a hexadecimal +# number are allowed. +.if ${WORDS:t\X} != "anything" +. info This line is not reached. +.endif + +all: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-separator.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.mk (revision 367461) @@ -0,0 +1,21 @@ +# $NetBSD: varmod-to-upper.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :tu variable modifier, which returns the words in the +# variable value, converted to uppercase. + +.if ${:UUPPER:tu} != "UPPER" +. error +.endif + +.if ${:Ulower:tu} != "LOWER" +. error +.endif + +.if ${:UMixeD case.:tu} != "MIXED CASE." +. error +.endif + +# The :tu and :tl modifiers operate on the variable value as a single string, +# not as a list of words. Therefore, the adjacent spaces are preserved. +mod-tu-space: + @echo $@: ${a b:L:tu:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.mk (revision 367461) @@ -0,0 +1,67 @@ +# $NetBSD: varmod-undefined.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the :U variable modifier, which returns the given string +# if the variable is undefined. +# +# See also: +# varmod-defined.mk + +# The pattern ${:Uword} is heavily used when expanding .for loops. +# +# This is how an expanded .for loop looks like. +# .for word in one +# . if ${word} != one +.if ${:Uone} != one +# . error ${word} +. error ${:Uone} +# . endif +.endif +# .endfor + +# The variable expressions in the text of the :U modifier may be arbitrarily +# nested. + +.if ${:U${:Unested}${${${:Udeeply}}}} != nested +. error +.endif + +# The nested variable expressions may contain braces, and these braces don't +# need to match pairwise. In the following example, the :S modifier uses '{' +# as delimiter, which confuses both editors and humans because the opening +# and # closing braces don't match anymore. It's syntactically valid though. +# For more similar examples, see varmod-subst.mk, mod-subst-delimiter. + +.if ${:U${:Uvalue:S{a{X{}} != vXlue +. error +.endif + +# The escaping rules for the :U modifier (left-hand side) and condition +# string literals (right-hand side) are completely different. +# +# In the :U modifier, the backslash only escapes very few characters, all +# other backslashes are retained. +# +# In condition string literals, the backslash always escapes the following +# character, no matter whether it would be necessary or not. +# +# In both contexts, \n is an escaped letter n, not a newline; that's what +# the .newline variable is for. +# +# Whitespace at the edges is preserved, on both sides of the comparison. +# +.if ${:U \: \} \$ \\ \a \b \n } != " : } \$ \\ \\a \\b \\n " +. error +.endif + +# Even after the :U modifier has been applied, the expression still remembers +# that it originated from an undefined variable, and the :U modifier can +# be used to overwrite the value of the expression. +# +.if ${UNDEF:Uvalue:S,a,X,} != "vXlue" +. error +.elif ${UNDEF:Uvalue:S,a,X,:Uwas undefined} != "was undefined" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod.exp (revision 367461) @@ -0,0 +1,6 @@ +make: "varmod.mk" line 42: To escape a dollar, use \$, not $$, at "$$:L} != """ +make: "varmod.mk" line 42: Invalid variable name ':', at "$:L} != """ +make: "varmod.mk" line 47: Dollar followed by nothing +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod.mk (revision 367461) @@ -0,0 +1,51 @@ +# $NetBSD: varmod.mk,v 1.3 2020/09/13 07:42:20 rillig Exp $ +# +# Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback. + +DOLLAR1= $$ +DOLLAR2= ${:U\$} + +# To get a single '$' sign in the value of a variable expression, it has to +# be written as '$$' in a literal variable value. +# +# See Var_Parse, where it calls Var_Subst. +.if ${DOLLAR1} != "\$" +. error +.endif + +# Another way to get a single '$' sign is to use the :U modifier. In the +# argument of that modifier, a '$' is escaped using the backslash instead. +# +# See Var_Parse, where it calls Var_Subst. +.if ${DOLLAR2} != "\$" +. error +.endif + +# It is also possible to use the :U modifier directly in the expression. +# +# See Var_Parse, where it calls Var_Subst. +.if ${:U\$} != "\$" +. error +.endif + +# XXX: As of 2020-09-13, it is not possible to use '$$' in a variable name +# to mean a single '$'. This contradicts the manual page, which says that +# '$' can be escaped as '$$'. +.if ${$$:L} != "" +. error +.endif + +# In lint mode, make prints helpful error messages. +# For compatibility, make does not print these error messages in normal mode. +# Should it? +.MAKEFLAGS: -dL +.if ${$$:L} != "" +. error +.endif + +# A '$' followed by nothing is an error as well. +.if ${:Uword:@word@${word}$@} != "word" +. error +.endif + +all: # nothing Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.mk (revision 367461) @@ -0,0 +1,45 @@ +# $NetBSD: varname-dot-curdir.mk,v 1.7 2020/10/08 19:09:08 rillig Exp $ +# +# Tests for the special .CURDIR variable, which is initially set to the +# canonical path of the current working directory, when make started. + +# In all normal situations, the current directory exists, and its name can +# be resolved. If not, make fails at startup. +# +# It would be possible on some systems to remove the current directory, even +# while a process runs in it, but this is so unrealistic that it's no worth +# testing. +.if !exists(${.CURDIR}) +. error +.endif +.if !exists(${.CURDIR}/) +. error +.endif +.if !exists(${.CURDIR}/.) +. error +.endif +.if !exists(${.CURDIR}/..) +. error +.endif + +# Until 2020-10-04, assigning the result of a shell assignment to .CURDIR +# tried to add the shell command ("echo /") to the .PATH instead of the +# output of the shell command ("/"). Since "echo /" does not exist, the +# .PATH was left unmodified. See VarAssign_Eval. +# +# Since 2020-10-04, the output of the shell command is added to .PATH. +.CURDIR!= echo / +.if ${.PATH:M/} != "/" +. error +.endif + +# A normal assignment works fine, as does a substitution assignment. +# Appending to .CURDIR does not make sense, therefore it doesn't matter that +# this code path is buggy as well. +.CURDIR= / +.if ${.PATH:M/} != "/" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: varname-dot-includes.mk,v 1.2 2020/09/13 16:53:19 rillig Exp $ +# +# Tests for the special .INCLUDES variable, which is not documented in the +# manual page. +# +# It is yet unclear in which situations this feature is useful. + +.SUFFIXES: .h + +.PATH.h: . .. + +.INCLUDES: .h + +# The .INCLUDES variable is not yet available. +.if defined(.INCLUDES) +. error +.endif + +all: + @echo .INCLUDES=${.INCLUDES:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: varname-dot-libs.mk,v 1.2 2020/09/13 16:53:19 rillig Exp $ +# +# Tests for the special .LIBS variable, which is not documented in the +# manual page. +# +# It is yet unclear in which situations this feature is useful. + +.SUFFIXES: .a + +.PATH.a: . .. + +.LIBS: .a + +# The .LIBS variable is not yet available. +.if defined(.LIBS) +. error +.endif + +all: + @echo .LIBS=${.LIBS:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.mk (revision 367461) @@ -0,0 +1,23 @@ +# $NetBSD: varname-dot-newline.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# +# Tests for the special .newline variable. +# +# Contrary to the special variable named "" that is used in expressions like +# ${:Usome-value}, the variable ".newline" is not protected against +# modification. Nobody exploits that though. + +NEWLINE:= ${.newline} + +.newline= overwritten + +.if ${.newline} == ${NEWLINE} +. info The .newline variable cannot be overwritten. Good. +.else +. info The .newline variable can be overwritten. Just don't do that. +.endif + +# Restore the original value. +.newline= ${NEWLINE} + +all: + @echo 'first${.newline}second' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "varname-dot-parsedir.mk" line 28: At this point, .PARSEDIR is undefined. +make: "" line 34: The location can be faked in some cases. +make: "varname-dot-parsedir.mk" line 38: The location is no longer fake. +At run time, .PARSEDIR is undefined. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.mk (revision 367461) @@ -0,0 +1,41 @@ +# $NetBSD: varname-dot-parsedir.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ +# +# Tests for the special .PARSEDIR variable, which contains the directory part +# of the file that is currently parsed. + +# The .PARSEDIR may be absolute or relative, therefore there is not much that +# can be tested here. +.if !${.PARSEDIR:tA:M*/unit-tests} +. error +.endif + +# During parsing, it is possible to undefine .PARSEDIR. +# Not that anyone would ever want to do this, but there's code in parse.c, +# function PrintLocation, that explicitly handles this situation. +.if !defined(.PARSEDIR) +. error +.endif +.undef .PARSEDIR +.if defined(.PARSEDIR) +. error +.endif + +# The variable .PARSEDIR is indirectly used by the .info directive, +# via PrintLocation. +# +# The .rawout file contains the full path to the current directory. +# In the .out file, it is filtered out. +.info At this point, .PARSEDIR is undefined. + +# There is absolutely no point in faking the location of the file that is +# being parsed. Technically, it's possible though, but only if the file +# being parsed is a relative pathname. See PrintLocation for details. +.PARSEDIR= /fake-absolute-path +.info The location can be faked in some cases. + +# After including another file, .PARSEDIR is reset. +.include "/dev/null" +.info The location is no longer fake. + +all: + @echo At run time, .PARSEDIR is ${.PARSEDIR:Uundefined}. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsedir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "varname-dot-parsefile.mk" line 23: At this point, .PARSEFILE is undefined. +make: "" line 29: The location can be faked in some cases. +make: "varname-dot-parsefile.mk" line 33: The location is no longer fake. +At run time, .PARSEFILE is undefined. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.mk (revision 367461) @@ -0,0 +1,36 @@ +# $NetBSD: varname-dot-parsefile.mk,v 1.5 2020/10/24 08:50:17 rillig Exp $ +# +# Tests for the special .PARSEFILE variable, which contains the basename part +# of the file that is currently parsed. + +.if ${.PARSEFILE} != "varname-dot-parsefile.mk" +. error +.endif + +# During parsing, it is possible to undefine .PARSEFILE. +# Not that anyone would ever want to do this, but there's code in parse.c, +# function PrintLocation, that explicitly handles this situation. +.if !defined(.PARSEFILE) +. error +.endif +.undef .PARSEFILE +.if defined(.PARSEFILE) +. error +.endif + +# The variable .PARSEFILE is indirectly used by the .info directive, +# via PrintLocation. +.info At this point, .PARSEFILE is undefined. + +# There is absolutely no point in faking the location of the file that is +# being parsed. Technically, it's possible though, but only if the file +# being parsed is a relative pathname. See PrintLocation for details. +.PARSEFILE= fake-parsefile +.info The location can be faked in some cases. + +# After including another file, .PARSEFILE is reset. +.include "/dev/null" +.info The location is no longer fake. + +all: + @echo At run time, .PARSEFILE is ${.PARSEFILE:Uundefined}. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-parsefile.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.mk (revision 367461) @@ -0,0 +1,56 @@ +# $NetBSD: varname-dot-path.mk,v 1.3 2020/10/02 18:46:54 rillig Exp $ +# +# Tests for the special .PATH variable, which TODO: describe the purpose. + +_!= mkdir -p varname-dot-path.d + +# By default, .PATH consists of "." and .CURDIR. +# XXX: Why both? Shouldn't they have the same effect? +.if ${.PATH} != ". ${.CURDIR}" +. error ${.PATH} +.endif + +# The special target .PATH adds a directory to the path. +.PATH: / +.if ${.PATH} != ". ${.CURDIR} /" +. error ${.PATH} +.endif + +# Only existing directories are added to the path, the others are ignored. +.PATH: /nonexistent +.if ${.PATH} != ". ${.CURDIR} /" +. error ${.PATH} +.endif + +# Only directories are added to the path, not regular files. +.PATH: ${.PARSEDIR}/${.PARSEFILE} +.if ${.PATH} != ". ${.CURDIR} /" +. error ${.PATH} +.endif + +# Relative directories can be added as well. +# Each directory is only added once to the path. +.PATH: varname-dot-path.d / +.if ${.PATH} != ". ${.CURDIR} / varname-dot-path.d" +. error ${.PATH} +.endif + +# The pathnames are not normalized before being added to the path. +.PATH: ./. +.if ${.PATH} != ". ${.CURDIR} / varname-dot-path.d ./." +. error ${.PATH} +.endif + +# The two default entries can be placed at the back of the path, +# by adding the special entry ".DOTLAST" somewhere in the path. +# The entry .DOTLAST, if any, is listed in the path, always at the +# very beginning, to make this magic less surprising. +.PATH: .DOTLAST +.if ${.PATH} != ".DOTLAST / varname-dot-path.d ./. . ${.CURDIR}" +. error ${.PATH} +.endif + +_!= rmdir varname-dot-path.d + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.exp (revision 367461) @@ -0,0 +1,32 @@ +ParseReadLine (10): 'ORIG_SHELL:= ${.SHELL}' +Global:ORIG_SHELL = +Var_Parse: ${.SHELL} with VARE_WANTRES|VARE_ASSIGN +Global:delete .SHELL (not found) +Command:.SHELL = (details omitted) +Global:ORIG_SHELL = (details omitted) +ParseReadLine (12): '.SHELL= overwritten' +Global:.SHELL = overwritten +CondParser_Eval: ${.SHELL} != ${ORIG_SHELL} +Var_Parse: ${.SHELL} != ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +Var_Parse: ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +lhs = "(details omitted)", rhs = "(details omitted)", op = != +ParseReadLine (19): '.MAKEFLAGS: .SHELL+=appended' +ParseDoDependency(.MAKEFLAGS: .SHELL+=appended) +Ignoring append to .SHELL since it is read-only +CondParser_Eval: ${.SHELL} != ${ORIG_SHELL} +Var_Parse: ${.SHELL} != ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +Var_Parse: ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +lhs = "(details omitted)", rhs = "(details omitted)", op = != +ParseReadLine (27): '.undef .SHELL' +Global:delete .SHELL +ParseReadLine (28): '.SHELL= newly overwritten' +Global:.SHELL = newly overwritten +CondParser_Eval: ${.SHELL} != ${ORIG_SHELL} +Var_Parse: ${.SHELL} != ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +Var_Parse: ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +lhs = "(details omitted)", rhs = "(details omitted)", op = != +ParseReadLine (33): '.MAKEFLAGS: -d0' +ParseDoDependency(.MAKEFLAGS: -d0) +Global:.MAKEFLAGS = -r -k -d cpv -d +Global:.MAKEFLAGS = -r -k -d cpv -d 0 +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.mk (revision 367461) @@ -0,0 +1,36 @@ +# $NetBSD: varname-dot-shell.mk,v 1.6 2020/10/30 16:09:56 rillig Exp $ +# +# Tests for the special .SHELL variable, which contains the shell used for +# running the commands. +# +# This variable is read-only. + +.MAKEFLAGS: -dcpv + +ORIG_SHELL:= ${.SHELL} + +.SHELL= overwritten +.if ${.SHELL} != ${ORIG_SHELL} +. error +.endif + +# Trying to append to the variable. +# Since 2020-10-30 this is prevented. +.MAKEFLAGS: .SHELL+=appended +.if ${.SHELL} != ${ORIG_SHELL} +. error +.endif + +# Trying to delete the variable. +# This has no effect since the variable is not defined in the global context, +# but in the command-line context. +.undef .SHELL +.SHELL= newly overwritten +.if ${.SHELL} != ${ORIG_SHELL} +. error +.endif + +.MAKEFLAGS: -d0 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-shell.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.exp (revision 367461) @@ -0,0 +1,13 @@ +Var_Set("${:U}", "cmdline-u", ...) name expands to empty string - ignored +Var_Set("", "cmline-plain", ...) name expands to empty string - ignored +Var_Set("", "default", ...) name expands to empty string - ignored +Var_Set("", "assigned", ...) name expands to empty string - ignored +Var_Set("", "appended", ...) name expands to empty string - ignored +Var_Set("", "", ...) name expands to empty string - ignored +Var_Set("", "subst", ...) name expands to empty string - ignored +Var_Set("", "shell-output", ...) name expands to empty string - ignored +Var_Set("${:U}", "assigned indirectly", ...) name expands to empty string - ignored +Var_Set("", "assigned", ...) name expands to empty string - ignored +out: fallback +out: 1 2 3 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.mk (revision 367461) @@ -0,0 +1,62 @@ +# $NetBSD: varname-empty.mk,v 1.7 2020/10/23 17:53:01 rillig Exp $ +# +# Tests for the special variable with the empty name. +# +# There is no variable named "" at all, and this fact is used a lot in +# variable expressions of the form ${:Ufallback}. These expressions are +# based on the variable named "" and use the :U modifier to assign a +# fallback value to the expression (but not to the variable). +# +# This form of expressions is used to implement value substitution in the +# .for loops. Another use case is in a variable assignment of the form +# ${:Uvarname}=value, which allows for characters in the variable name that +# would otherwise be interpreted by the parser, such as whitespace, ':', +# '=', '$', backslash. +# +# The only places where a variable is assigned a value are Var_Set and +# Var_Append, and these places protect the variable named "" from being +# defined. This is different from read-only variables, as that flag can +# only apply to variables that are defined. The variable named "" must +# never be defined though. +# +# See also: +# The special variables @F or ^D, in var-class-local.mk + +# Until 2020-08-22 it was possible to assign a value to the variable with +# the empty name, leading to all kinds of unexpected effects in .for loops +# and other places that assume that ${:Ufallback} expands to "fallback". +# The bug in Var_Set was that only expanded variables had been checked for +# the empty name, but not the direct assignments with an empty name. +?= default += assigned # undefined behavior until 2020-08-22 ++= appended +:= subst +!= echo 'shell-output' +.if ${:Ufallback} != "fallback" +. error +.endif + +${:U}= assigned indirectly +.if ${:Ufallback} != "fallback" +. error +.endif + +# Before 2020-08-22, the simple assignment operator '=' after an empty +# variable name had an off-by-one bug in Parse_DoVar. The code that was +# supposed to "skip to operator character" started its search _after_ the +# assignment operator, assuming that the variable name would be at least +# one character long. It then looked for the next occurrence of a '=', which +# could be several lines away or not occur at all. While looking for the +# '=', some whitespace was nulled out, leading to out-of-bounds write. += assigned # undefined behavior until 2020-08-22 + +# The .for loop expands the expression ${i} to ${:U1}, ${:U2} and so on. +# This only works if the variable with the empty name is guaranteed to +# be undefined. +.for i in 1 2 3 +NUMBERS+= ${i} +.endfor + +all: + @echo out: ${:Ufallback} + @echo out: ${NUMBERS} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-empty.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.exp (revision 367461) @@ -0,0 +1,7 @@ +fail +*** [all] Error code 1 + +make: stopped in unit-tests +.ERROR_TARGET='all' +.ERROR_CMD='@: command before @echo fail; false @: command after, with variable expressions expanded' +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.mk (revision 367461) @@ -0,0 +1,21 @@ +# $NetBSD: varname-make_print_var_on_error-jobs.mk,v 1.1 2020/10/23 06:18:23 rillig Exp $ +# +# Tests for the special MAKE_PRINT_VAR_ON_ERROR variable, which prints the +# values of selected variables on error. +# +# The variable .ERROR_CMD contains all commands of the target, with variable +# expressions expanded, just as they were printed to the shell command file. +# +# The commands in .ERROR_CMD are space-separated. Since each command usually +# contains spaces as well, this value is only intended as a first hint to what +# happened. For more details, use the debug options -de, -dj, -dl, -dn, -dx. + +# As of 2020-10-23, .ERROR_CMD only works in parallel mode. +.MAKEFLAGS: -j1 + +MAKE_PRINT_VAR_ON_ERROR= .ERROR_TARGET .ERROR_CMD + +all: + @: command before + @echo fail; false + @: command after${:U, with variable expressions expanded} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.exp (revision 367461) @@ -0,0 +1,8 @@ +fail +*** Error code 1 (continuing) + +Stop. +make: stopped in unit-tests +.ERROR_TARGET='all' +.ERROR_CMD='' +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.mk (revision 367461) @@ -0,0 +1,16 @@ +# $NetBSD: varname-make_print_var_on_error.mk,v 1.4 2020/10/23 06:18:23 rillig Exp $ +# +# Tests for the special MAKE_PRINT_VAR_ON_ERROR variable, which prints the +# values of selected variables on error. + +# XXX: As of 2020-10-23, the .ERROR_CMD variable is pointless in compat mode +# since at the point where it is filled in PrintOnError, the first command in +# gn->commands has been set to NULL already. This leaves .ERROR_CMD an empty +# list. + +MAKE_PRINT_VAR_ON_ERROR= .ERROR_TARGET .ERROR_CMD + +all: + @: command before + @echo fail; false + @: command after Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-make_print_var_on_error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.mk (revision 367461) @@ -0,0 +1,44 @@ +# $NetBSD: varname-makefile.mk,v 1.2 2020/09/05 06:25:38 rillig Exp $ +# +# Tests for the special MAKEFILE variable, which contains the current +# makefile from the -f command line option. +# +# When there are multiple -f options, the variable MAKEFILE is set +# again for each of these makefiles, before the file is parsed. +# Including a file via .include does not influence the MAKEFILE +# variable though. + +.if ${MAKEFILE:T} != "varname-makefile.mk" +. error +.endif + +# This variable lives in the "Internal" namespace. +# TODO: Why does it do that, and what consequences does this have? + +# Deleting the variable does not work since this variable does not live in +# the "Global" namespace but in "Internal", which is kind of a child +# namespace. +# +.undef MAKEFILE +.if ${MAKEFILE:T} != "varname-makefile.mk" +. error +.endif + +# Overwriting this variable is possible since the "Internal" namespace +# serves as a fallback for the "Global" namespace (see VarFind). +# +MAKEFILE= overwritten +.if ${MAKEFILE:T} != "overwritten" +. error +.endif + +# When the overwritten value is deleted, the fallback value becomes +# visible again. +# +.undef MAKEFILE +.if ${MAKEFILE:T} != "varname-makefile.mk" +. error +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-makefile.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname.mk,v 1.4 2020/10/18 08:47:54 rillig Exp $ +# +# Tests for special variables, such as .MAKE or .PARSEDIR. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: varparse-dynamic.mk,v 1.2 2020/09/13 21:00:34 rillig Exp $ + +# Before 2020-07-27, there was an off-by-one error in Var_Parse that skipped +# the last character in the variable name. +# To trigger the bug, the variable must not be defined. +.if ${.TARGET} # exact match, may be undefined +.endif +.if ${.TARGEX} # 1 character difference, must be defined +.endif +.if ${.TARGXX} # 2 characters difference, must be defined +.endif + +# When a dynamic variable (such as .TARGET) is evaluated in the global +# context, it is not yet ready to be expanded. Therefore the complete +# expression is returned as the variable value, hoping that it can be +# resolved at a later point. +# +# This test covers the code in Var_Parse that deals with VAR_JUNK but not +# VAR_KEEP for dynamic variables. +.if ${.TARGET:S,^,,} != "\${.TARGET:S,^,,}" +. error +.endif + +all: + @: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.mk (revision 367461) @@ -0,0 +1,61 @@ +# $NetBSD: varparse-mod.mk,v 1.1 2020/10/02 20:34:59 rillig Exp $ + +# Tests for parsing variable expressions with modifiers. + +# As of 2020-10-02, the below condition does not result in a parse error. +# The condition contains two separate mistakes. The first mistake is that +# the :!cmd! modifier is missing the closing '!'. The second mistake is that +# there is a stray '}' at the end of the whole condition. +# +# As of 2020-10-02, the actual parse result of this condition is a single +# variable expression with 2 modifiers. The first modifier is +# ":!echo "\$VAR"} !". Afterwards, the parser optionally skips a ':' (at the +# bottom of ApplyModifiers) and continues with the next modifier, in this case +# "= "value"", which is interpreted as a SysV substitution modifier with an +# empty left-hand side, thereby appending the string " "value"" to each word +# of the expression. +# +# As of 2020-10-02, some modifiers ensure that they are followed by either a +# ':' or the closing brace or parenthesis of the expression. The modifiers +# that don't ensure this are (in order of appearance in ApplyModifier): +# :@var@replacement@ +# :_ +# :L +# :P +# :!cmd! +# :gmtime=... +# :localtime=... +# :M (because '}' and ')' are treated the same) +# :N (because '}' and ')' are treated the same) +# :S +# :C +# :range=... +# On the other hand, these modifiers ensure that they are followed by a +# delimiter: +# :D +# :U +# :[...] +# :gmtime (if not followed by '=') +# :hash (if not followed by '=') +# :localtime (if not followed by '=') +# :t +# :q +# :Q +# :T +# :H +# :E +# :R +# :range (if not followed by '=') +# :O +# :u +# :sh +# These modifiers don't care since they reach until the closing character +# of the expression, which is either ')' or '}': +# ::= (as well as the other assignment modifiers) +# :? +# +.if ${:!echo "\$VAR"} != "value"} +.endif + +all: + @: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varparse-mod.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.mk (revision 367461) @@ -0,0 +1,64 @@ +# $NetBSD: varparse-undef-partial.mk,v 1.2 2020/09/27 09:53:41 rillig Exp $ + +# When an undefined variable is expanded in a ':=' assignment, only the +# initial '$' of the variable expression is skipped by the parser, while +# the remaining expression is evaluated. In edge cases this can lead to +# a completely different interpretation of the partially expanded text. + +LIST= ${DEF} ${UNDEF} ${VAR.${PARAM}} end +DEF= defined +PARAM= :Q + +# The expression ${VAR.{PARAM}} refers to the variable named "VAR.:Q", +# with the ":Q" being part of the name. This variable is not defined, +# therefore the initial '$' of that whole expression is skipped by the +# parser (see Var_Subst, the Buf_AddByte in the else branch) and the rest +# of the expression is expanded as usual. +# +# The resulting variable expression is ${VAR.:Q}, which means that the +# interpretation of the ":Q" has changed from being part of the variable +# name to being a variable modifier. This is a classical code injection. +EVAL:= ${LIST} +.if ${EVAL} != "defined end" +. error ${EVAL} +.endif + +# Define the possible outcomes, to see which of them gets expanded. +VAR.= var-dot without parameter +${:UVAR.\:Q}= var-dot with parameter :Q + +# At this point, the variable "VAR." is defined, therefore the expression +# ${VAR.:Q} is expanded as usual. +.if ${EVAL} != "defined var-dot\\ without\\ parameter end" +. error ${EVAL} +.endif + +# In contrast to the previous line, evaluating the original LIST again now +# produces a different result since the ":Q" has already been inserted +# literally into the expression. The variable named "VAR.:Q" is defined, +# therefore it is resolved as usual. The ":Q" is interpreted as part of the +# variable name, as would be expected from reading the variable expression. +EVAL:= ${LIST} +.if ${EVAL} != "defined var-dot with parameter :Q end" +. error ${EVAL} +.endif + +# It's difficult to decide what the best behavior is in this situation. +# Should the whole expression be skipped for now, or should the inner +# subexpressions be expanded already? +# +# Example 1: +# CFLAGS:= ${CFLAGS:N-W*} ${COPTS.${COMPILER}} +# +# The variable COMPILER typically contains an identifier and the variable is +# not modified later. In this practical case, it does not matter whether the +# expression is expanded early, or whether the whole ${COPTS.${COMPILER}} is +# expanded as soon as the variable COPTS.${COMPILER} becomes defined. The +# expression ${COMPILER} would be expanded several times, but in this simple +# scenario there would not be any side effects. +# +# TODO: Add a practical example where early/lazy expansion actually makes a +# difference. + +all: + @: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varparse-undef-partial.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varshell.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varshell.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varshell.exp (revision 367461) @@ -0,0 +1,10 @@ +make: "varshell.mk" line 6: warning: "/bin/no/such/command 2> /dev/null" returned non-zero status +make: "varshell.mk" line 9: warning: "false" returned non-zero status +make: "varshell.mk" line 10: warning: "echo "output before the error"; false" returned non-zero status +EXEC_FAILED='' +TERMINATED_BY_SIGNAL='' +ERROR_NO_OUTPUT='' +ERROR_WITH_OUTPUT='output before the error' +NO_ERROR_NO_OUTPUT='' +NO_ERROR_WITH_OUTPUT='this is good' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varshell.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varshell.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varshell.mk (revision 367461) @@ -0,0 +1,20 @@ +# $Id: varshell.mk,v 1.6 2020/10/26 17:55:23 sjg Exp $ +# $NetBSD: varshell.mk,v 1.4 2020/10/24 08:50:17 rillig Exp $ +# +# Test VAR != shell command + +EXEC_FAILED!= /bin/no/such/command 2> /dev/null +# SunOS cannot handle this one +#TERMINATED_BY_SIGNAL!= kill -14 $$$$ +ERROR_NO_OUTPUT!= false +ERROR_WITH_OUTPUT!= echo "output before the error"; false +NO_ERROR_NO_OUTPUT!= true +NO_ERROR_WITH_OUTPUT!= echo "this is good" + +allvars= EXEC_FAILED TERMINATED_BY_SIGNAL ERROR_NO_OUTPUT ERROR_WITH_OUTPUT \ + NO_ERROR_NO_OUTPUT NO_ERROR_WITH_OUTPUT + +all: +.for v in ${allvars} + @echo ${v}=\'${${v}}\' +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varshell.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.exp (revision 367461) @@ -0,0 +1,2 @@ +`all' is up to date. +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.mk (revision 367461) @@ -0,0 +1,23 @@ +# $NetBSD: archive-suffix.mk,v 1.1 2020/08/29 14:47:26 rillig Exp $ +# +# Between 2020-08-23 and 2020-08-30, the below code produced an assertion +# failure in Var_Set_with_flags, triggered by Compat_Make, when setting the +# .IMPSRC of an archive node to its .TARGET. +# +# The code assumed that the .TARGET variable of every node would be set, but +# but that is not guaranteed. +# +# Between 2016-03-15 and 2016-03-16 the behavior of the below code changed. +# Until 2016-03-15, it remade the target, starting with 2016-03-16 it says +# "`all' is up to date". + +.SUFFIXES: +.SUFFIXES: .c .o + +all: lib.a(obj1.o) + +.c.o: + : making $@ + +obj1.c: + : $@ Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/archive-suffix.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.exp (revision 367461) @@ -0,0 +1,9 @@ +> cmd-interrupt-ordinary +make: *** cmd-interrupt-ordinary removed +interrupt-ordinary: ok +> cmd-interrupt-phony +make: *** cmd-interrupt-phony removed +interrupt-phony: ok +> cmd-interrupt-precious +interrupt-precious: ok +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.mk (revision 367461) @@ -0,0 +1,50 @@ +# $NetBSD: cmd-interrupt.mk,v 1.2 2020/08/28 18:16:22 rillig Exp $ +# +# Tests for interrupting a command. +# +# If a command is interrupted (usually by the user, here by itself), the +# target is removed. This is to avoid having an unfinished target that +# would be newer than all of its sources and would therefore not be +# tried again in the next run. +# +# This happens for ordinary targets as well as for .PHONY targets, even +# though the .PHONY targets usually do not correspond to a file. +# +# To protect the target from being removed, the target has to be marked with +# the special source .PRECIOUS. These targets need to ensure for themselves +# that interrupting them does not leave an inconsistent state behind. +# +# See also: +# CompatDeleteTarget + +all: clean-before interrupt-ordinary interrupt-phony interrupt-precious clean-after + +clean-before clean-after: .PHONY + @rm -f cmd-interrupt-ordinary cmd-interrupt-phony cmd-interrupt-precious + +interrupt-ordinary: .PHONY + @${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-ordinary || true + # The ././ is necessary to work around the file cache. + @echo ${.TARGET}: ${exists(././cmd-interrupt-ordinary) :? error : ok } + +interrupt-phony: .PHONY + @${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-phony || true + # The ././ is necessary to work around the file cache. + @echo ${.TARGET}: ${exists(././cmd-interrupt-phony) :? error : ok } + +interrupt-precious: .PRECIOUS + @${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-precious || true + # The ././ is necessary to work around the file cache. + @echo ${.TARGET}: ${exists(././cmd-interrupt-precious) :? ok : error } + +cmd-interrupt-ordinary: + > ${.TARGET} + @kill -INT ${.MAKE.PID} + +cmd-interrupt-phony: .PHONY + > ${.TARGET} + @kill -INT ${.MAKE.PID} + +cmd-interrupt-precious: .PRECIOUS + > ${.TARGET} + @kill -INT ${.MAKE.PID} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cmd-interrupt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cmdline.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cmdline.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cmdline.exp (revision 367461) @@ -0,0 +1,5 @@ +makeobjdir-direct: +show-objdir: /tmp/6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 +makeobjdir-indirect: +show-objdir: /tmp/a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45/ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cmdline.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cmdline.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cmdline.mk (revision 367461) @@ -0,0 +1,37 @@ +# $NetBSD: cmdline.mk,v 1.1 2020/07/28 22:44:44 rillig Exp $ +# +# Tests for command line parsing and related special variables. + +RUN?= @set -eu; +TMPBASE?= /tmp +SUB1= a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45 # just a random UUID +SUB2= 6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 # just a random UUID +MAKE_CMD= env TMPBASE=${TMPBASE}/${SUB1} ${.MAKE} -f ${MAKEFILE} -r +DIR2= ${TMPBASE}/${SUB2} +DIR12= ${TMPBASE}/${SUB1}/${SUB2} + +all: prepare-dirs +all: makeobjdir-direct makeobjdir-indirect + +prepare-dirs: + ${RUN} rm -rf ${DIR2} ${DIR12} + ${RUN} mkdir -p ${DIR2} ${DIR12} + +# The .OBJDIR can be set via the MAKEOBJDIR command line variable. +# It must be a command line variable; an environment variable would not work. +makeobjdir-direct: + @echo $@: + ${RUN} ${MAKE_CMD} MAKEOBJDIR=${DIR2} show-objdir + +# The .OBJDIR can be set via the MAKEOBJDIR command line variable, +# and that variable could even contain the usual modifiers. +# Since the .OBJDIR=MAKEOBJDIR assignment happens very early, +# the SUB2 variable in the modifier is not defined yet and is therefore empty. +# The SUB1 in the resulting path comes from the environment variable TMPBASE, +# see MAKE_CMD. +makeobjdir-indirect: + @echo $@: + ${RUN} ${MAKE_CMD} MAKEOBJDIR='$${TMPBASE}/$${SUB2}' show-objdir + +show-objdir: + @echo $@: ${.OBJDIR:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cmdline.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ge.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-gt.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-le.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-lt.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-cmp-numeric-ne.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-commands.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-defined.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "cond-func-defined.mk" line 23: warning: Missing closing parenthesis for defined() +make: "cond-func-defined.mk" line 23: Malformed conditional (!defined(A B)) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-empty.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-exists.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func-target.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-func.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-func.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-func.exp (revision 367461) @@ -0,0 +1,9 @@ +make: "cond-func.mk" line 29: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 29: Malformed conditional (!defined(A B)) +make: "cond-func.mk" line 44: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 44: Malformed conditional (!defined(A&B)) +make: "cond-func.mk" line 47: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 47: Malformed conditional (!defined(A|B)) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-late.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-late.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-late.exp (revision 367461) @@ -0,0 +1,4 @@ +make: Bad conditional expression ` != "no"' in != "no"?: +yes +no +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-late.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-late.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-late.mk (revision 367461) @@ -0,0 +1,29 @@ +# $NetBSD: cond-late.mk,v 1.2 2020/07/25 20:37:46 rillig Exp $ +# +# Using the :? modifier, variable expressions can contain conditional +# expressions that are evaluated late. Any variables appearing in these +# conditions are expanded before parsing the condition. This is +# different from many other places. +# +# Because of this, variables that are used in these lazy conditions +# should not contain double-quotes, or the parser will probably fail. +# +# They should also not contain operators like == or <, since these are +# actually interpreted as these operators. This is demonstrated below. +# +# If the order of evaluation were to change to first parse the condition +# and then expand the variables, the output would change from the +# current "yes no" to "yes yes", since both variables are non-empty. + +all: cond-literal + +COND.true= "yes" == "yes" +COND.false= "yes" != "yes" + +cond-literal: + @echo ${ ${COND.true} :?yes:no} + @echo ${ ${COND.false} :?yes:no} + +VAR+= ${${UNDEF} != "no":?:} +.if empty(VAR:Mpattern) +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-late.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-not.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: cond-op-parentheses.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for parentheses in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-op-parentheses.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: cond-token-string.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for quoted and unquoted string literals in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-string.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-token-var.exp (revision 367461) @@ -0,0 +1,7 @@ +make: "cond-token-var.mk" line 9: ok +make: "cond-token-var.mk" line 15: Malformed conditional (${UNDEF} == ${DEF}) +make: "cond-token-var.mk" line 20: Malformed conditional (${DEF} == ${UNDEF}) +make: "cond-token-var.mk" line 29: Malformed conditional (${UNDEF}) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-double-colon.exp (revision 367461) @@ -0,0 +1,5 @@ +command 1a +command 1b +command 2a +command 2b +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: dep-exclam.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the ! operator in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-exclam.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-none.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-none.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-none.exp (revision 367461) @@ -0,0 +1,4 @@ +make: no target to make. + +make: stopped in unit-tests +exit status 2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-none.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep-none.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep-none.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep-none.mk (revision 367461) @@ -0,0 +1,3 @@ +# $NetBSD: dep-none.mk,v 1.1 2020/08/22 12:51:11 rillig Exp $ +# +# Test for a Makefile that declares no target at all. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep-none.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dep.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dep.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dep.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: dep.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for dependency declarations, such as "target: sources". + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dep.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.exp (revision 367461) @@ -0,0 +1,11 @@ +ignore-errors begin +false ignore-errors +ignore-errors end +all begin +*** Error code 1 (ignored) +false all +*** Error code 1 (continuing) + +Stop. +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.mk (revision 367461) @@ -0,0 +1,67 @@ +# $NetBSD: depsrc-ignore.mk,v 1.4 2020/08/29 16:13:27 rillig Exp $ +# +# Tests for the special source .IGNORE in dependency declarations, +# which ignores any command failures for that target. +# +# Even though ignore-errors fails, the all target is still made. +# Since the all target is not marked with .IGNORE, it stops at the +# first failing command. +# +# XXX: The ordering of the messages in the output is confusing. +# The "ignored" comes much too late to be related to the "false +# ignore-errors". This is due to stdout being buffered. +# +# The "continuing" message comes from the -k option. If there had been +# other targets independent of "all", these would be built as well. +# +# Enabling the debugging option -de changes the order in which the messages +# appear. Now the "ignored" message is issued in the correct position. +# The explanation for the output reordering is that the output is buffered. +# As the manual page says, in debugging mode stdout is line buffered. +# In these tests the output is redirected to a file, therefore stdout is +# fully buffered. +# +# This is what actually happens, as of 2020-08-29. To verify it, set the +# following breakpoints in CompatRunCommand: +# +# * the "!silent" line, to see all commands. +# * the "fflush" line, to see stdout being flushed. +# * the "status = WEXITSTATUS" line +# * the "(continuing)" line +# * the "(ignored)" line +# +# The breakpoints are visited in the following order: +# +# "ignore-errors begin" +# Goes directly to STDOUT_FILENO since it is run in a child process. +# "false ignore-errors" +# Goes to the stdout buffer (CompatRunCommand, keyword "!silent") and +# the immediate call to fflush(stdout) copies it to STDOUT_FILENO. +# "*** Error code 1 (ignored)" +# Goes to the stdout buffer but is not flushed (CompatRunCommand, near +# the end). +# "ignore-errors end" +# Goes directly to STDOUT_FILENO. +# "all begin" +# Goes directly to STDOUT_FILENO. +# "false all" +# Goes to the stdout buffer, where the "*** Error code 1 (ignored)" is +# still waiting to be flushed. These two lines are flushed now. +# "*** Error code 1 (continuing)" +# Goes to the stdout buffer. +# "Stop." +# Goes to the stdout buffer. +# exit(1) +# Flushes the stdout buffer to STDOUT_FILENO. + +all: ignore-errors + +ignore-errors: .IGNORE + @echo $@ begin + false $@ + @echo $@ end + +all: + @echo $@ begin + false $@ + @echo $@ end Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-ignore.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-meta.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .META in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-meta.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-nometa.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .NOMETA in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-nometa_cmp.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .NOMETA_CMP in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nometa_cmp.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-nopath.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .NOPATH in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-nopath.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-precious.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .PRECIOUS in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-precious.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.exp (revision 367461) @@ -0,0 +1,4 @@ +one +two +three +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: depsrc-silent.mk,v 1.3 2020/08/29 17:34:21 rillig Exp $ +# +# Tests for the special source .SILENT in dependency declarations, +# which hides the commands, no matter whether they are prefixed with +# '@' or not. + +# Without the .SILENT, the commands 'echo one' and 'echo two' would be +# written to stdout. +all: .SILENT + echo one + echo two + @echo three Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-silent.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.exp (revision 367461) @@ -0,0 +1,6 @@ +first 1 +first 2 +second 1 +second 2 +directly +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: depsrc-use.mk,v 1.4 2020/08/22 12:30:57 rillig Exp $ +# +# Tests for the special source .USE in dependency declarations, +# which allows to append common commands to other targets. + +all: action directly + +first: .USE + @echo first 1 # Using ${.TARGET} here would expand to "action" + @echo first 2 + +second: .USE + @echo second 1 + @echo second 2 + +# It's possible but uncommon to have a .USE target with no commands. +# This may happen as the result of expanding a .for loop. +empty: .USE + +# It's possible but uncommon to directly make a .USEBEFORE target. +directly: .USE + @echo directly + +action: first second empty Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-use.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.exp (revision 367461) @@ -0,0 +1,2 @@ +double-colon early 1 +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.mk (revision 367461) @@ -0,0 +1,30 @@ +# $NetBSD: depsrc-usebefore-double-colon.mk,v 1.1 2020/08/22 08:29:13 rillig Exp $ +# +# Tests for the special source .USEBEFORE in dependency declarations, +# combined with the double-colon dependency operator. + +all: action + +# The dependency operator :: allows commands to be added later to the same +# target. +double-colon:: .USEBEFORE + @echo double-colon early 1 + +# This command is ignored, which kind of makes sense since this dependency +# declaration has no .USEBEFORE source. +double-colon:: + @echo double-colon early 2 + +# XXX: This command is ignored even though it has a .USEBEFORE source. +# This is unexpected. +double-colon:: .USEBEFORE + @echo double-colon early 3 + +# At this point, the commands from the .USEBEFORE targets are copied to +# the "action" target. +action: double-colon + +# This command is not added to the "action" target since it comes too late. +# The commands had been copied in the previous line already. +double-colon:: + @echo double-colon late Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore-double-colon.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.exp (revision 367461) @@ -0,0 +1,6 @@ +first 1 +first 2 +second 1 +second 2 +directly +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: depsrc-usebefore.mk,v 1.5 2020/08/22 11:53:18 rillig Exp $ +# +# Tests for the special source .USEBEFORE in dependency declarations, +# which allows to prepend common commands to other targets. + +all: action directly + +first: .USEBEFORE + @echo first 1 # Using ${.TARGET} here would expand to "action" + @echo first 2 # Using ${.TARGET} here would expand to "action" + +second: .USEBEFORE + @echo second 1 + @echo second 2 + +# It is possible but uncommon to have a .USEBEFORE target with no commands. +# This may happen as the result of expanding a .for loop. +empty: .USEBEFORE + +# It is possible but uncommon to directly make a .USEBEFORE target. +directly: .USEBEFORE + @echo directly + +action: second first empty Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc-usebefore.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/depsrc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/depsrc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/depsrc.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: depsrc.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for special sources (those starting with a dot, followed by +# uppercase letters) in dependency declarations, such as .PHONY. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/depsrc.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.exp (revision 367461) @@ -0,0 +1,4 @@ +: parse time +: .BEGIN +: all +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.mk (revision 367461) @@ -0,0 +1,13 @@ +# $NetBSD: deptgt-begin.mk,v 1.3 2020/08/29 17:34:21 rillig Exp $ +# +# Tests for the special target .BEGIN in dependency declarations, +# which is a container for commands that are run before any other +# commands from the shell lines. + +.BEGIN: + : $@ + +all: + : $@ + +_!= echo : parse time 1>&2 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-begin.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-default.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .DEFAULT in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-default.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .ERROR in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-ignore.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .IGNORE in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-ignore.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-interrupt.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .INTERRUPT in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-interrupt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-main.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .MAIN in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-main.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-no_parallel.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .NO_PARALLEL in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-no_parallel.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-nopath.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .NOPATH in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-nopath.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-notparallel.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .NOTPARALLEL in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-notparallel.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-objdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .OBJDIR in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-objdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-order.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .ORDER in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-order.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-path-suffix.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .PATH.suffix in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path-suffix.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-path.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .PATH in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-path.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-phony.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .PHONY in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-phony.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-precious.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .PRECIOUS in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-precious.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-shell.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .SHELL in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-shell.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-stale.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .STALE in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-stale.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.mk (revision 367461) @@ -0,0 +1,18 @@ +# $NetBSD: deptgt-suffixes.mk,v 1.3 2020/08/28 04:05:35 rillig Exp $ +# +# Tests for the special target .SUFFIXES in dependency declarations. +# +# See also: +# varname-dot-includes.mk +# varname-dot-libs.mk + +.MAKEFLAGS: -dg1 + +.SUFFIXES: .custom-null + +# TODO: What is the effect of this? How is it useful? +.NULL: .custom-null +.PATH.custom-null: . .. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/deptgt-suffixes.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.exp (revision 367461) @@ -0,0 +1,4 @@ +dir-expand-path.dir.1/file1.src +dir-expand-path.dir.1/file2.src +dir-expand-path.dir.2/file3.src +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.mk (revision 367461) @@ -0,0 +1,19 @@ +# $NetBSD: dir-expand-path.mk,v 1.1 2020/08/22 21:55:54 rillig Exp $ +# +# Tests for filename expansion in the search path. + +_!= rm -rf dir-expand-path.dir.* +_!= mkdir dir-expand-path.dir.1 +_!= mkdir dir-expand-path.dir.2 +_!= touch dir-expand-path.dir.1/file1.src +_!= touch dir-expand-path.dir.1/file2.src +_!= touch dir-expand-path.dir.2/file3.src + +.PATH: dir-expand-path.dir.1 +.PATH: dir-expand-path.dir.2 + +all: *.src + @printf '%s\n' ${.ALLSRC:O} + +.END: + @rm -rf dir-expand-path.dir.* Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dir-expand-path.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-elif.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .elif directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-elif.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-elifdef.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .elifdef directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifdef.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-elifmake.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .elifmake directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifmake.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-elifndef.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .elifndef directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifndef.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-elifnmake.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .elifnmake directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-elifnmake.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-else.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-else.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-else.exp (revision 367461) @@ -0,0 +1,8 @@ +make: "directive-else.mk" line 10: ok +make: "directive-else.mk" line 14: ok +make: "directive-else.mk" line 20: if-less else +make: "directive-else.mk" line 26: ok +make: "directive-else.mk" line 27: warning: extra else +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-endif.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .endif directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-endif.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-error.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-error.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .error directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-export-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .export-env directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-export-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-export.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-export.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-export.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.exp (revision 367461) @@ -0,0 +1,7 @@ +make: "directive-for-generating-endif.mk" line 21: if-less endif +make: "directive-for-generating-endif.mk" line 21: if-less endif +make: "directive-for-generating-endif.mk" line 21: if-less endif +make: "directive-for-generating-endif.mk" line 0: 3 open conditionals +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: directive-for-generating-endif.mk,v 1.1 2020/08/29 18:50:25 rillig Exp $ +# +# Test whether a .for loop can be used to generate multiple .endif +# directives to close nested .if directives. Depending on the exact +# implementation, this might have been possible. +# +# If it were possible, the 3 .if directives would perfectly match the +# 3 .endif directives generated by the .for loop. +# +# After the "included file" from the .for loop, the 3 .if directives +# are still open. +# +# See For_Run and ParseReadLine. Each .for loop is treated like a separately +# included file, and in each included file the .if/.endif directives must be +# balanced. + +.if 1 +. if 2 +. if 3 +.for i in 3 2 1 +.endif +.endfor + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-for-generating-endif.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-if.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-if.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-if.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-if.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-if.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-if.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-if.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .if directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-if.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-ifdef.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .ifdef directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifdef.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.exp (revision 367461) @@ -0,0 +1,10 @@ +make: "directive-ifmake.mk" line 8: ok: positive condition works +make: "directive-ifmake.mk" line 19: ok: negation works +make: "directive-ifmake.mk" line 25: ok: double negation works +make: "directive-ifmake.mk" line 32: ok: both mentioned +make: "directive-ifmake.mk" line 39: ok: only those mentioned +make: "directive-ifmake.mk" line 49: Targets can even be added at parse time. +: first +: second +: late-target +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.mk (revision 367461) @@ -0,0 +1,55 @@ +# $NetBSD: directive-ifmake.mk,v 1.4 2020/08/30 14:25:45 rillig Exp $ +# +# Tests for the .ifmake directive, which provides a shortcut for asking +# whether a certain target is requested to be made from the command line. + +# This is the most basic form. +.ifmake first +.info ok: positive condition works +.else +.warning positive condition fails +.endif + +# The not operator works as expected. +# An alternative interpretation were that this condition is asking whether +# the target "!first" was requested. To distinguish this, see the next test. +.ifmake !first +.warning unexpected +.else +.info ok: negation works +.endif + +# See if the exclamation mark really means "not", or if it is just part of +# the target name. +.ifmake !!first +.info ok: double negation works +.else +.warning double negation fails +.endif + +# Multiple targets can be combined using the && and || operators. +.ifmake first && second +.info ok: both mentioned +.else +.warning && does not work as expected +.endif + +# Negation also works in complex conditions. +.ifmake first && !unmentioned +.info ok: only those mentioned +.else +.warning && with ! does not work as expected +.endif + +# Using the .MAKEFLAGS special dependency target, arbitrary command +# line options can be added at parse time. This means that it is +# possible to extend the targets to be made. +.MAKEFLAGS: late-target +.ifmake late-target +.info Targets can even be added at parse time. +.else +.info No, targets cannot be added at parse time anymore. +.endif + +first second unmentioned late-target: + : $@ Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-ifmake.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-info.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-info.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-info.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-info.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-info.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-info.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-info.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .info directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-info.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-undef.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-unexport-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .unexport-env directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-unexport-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive-warning.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .warning directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive-warning.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/directive.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directive.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directive.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: directive.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the preprocessing directives, such as .if or .info. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/directive.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/directives.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/directives.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/directives.exp (revision 367461) @@ -0,0 +1,42 @@ +make: "directives.mk" line 10: begin .export tests +make: "directives.mk" line 11: Unknown directive "expor" +make: "directives.mk" line 20: begin .export-env tests +make: "directives.mk" line 30: begin .export-literal tests +make: "directives.mk" line 40: begin .info tests +make: "directives.mk" line 41: Unknown directive "inf" +make: "directives.mk" line 42: Unknown directive "info" +make: "directives.mk" line 43: message +make: "directives.mk" line 44: indented message +make: "directives.mk" line 45: Unknown directive "information" +make: "directives.mk" line 46: message +make: "directives.mk" line 50: begin .undef tests +make: "directives.mk" line 51: Unknown directive "unde" +make: "directives.mk" line 60: begin .unexport tests +make: "directives.mk" line 61: Unknown directive "unexpor" +make: "directives.mk" line 70: begin .unexport-env tests +make: "directives.mk" line 80: begin .warning tests +make: "directives.mk" line 81: Unknown directive "warn" +make: "directives.mk" line 82: Unknown directive "warnin" +make: "directives.mk" line 83: Unknown directive "warning" +make: "directives.mk" line 84: warning: message +make: "directives.mk" line 85: Unknown directive "warnings" +make: "directives.mk" line 86: warning: messages +make: "directives.mk" line 90: begin .elif misspellings tests, part 1 +make: "directives.mk" line 100: begin .elif misspellings tests, part 2 +make: "directives.mk" line 110: begin .elif misspellings tests, part 3 +make: "directives.mk" line 120: which branch is taken on misspelling after false? +make: "directives.mk" line 127: else taken +make: "directives.mk" line 130: which branch is taken on misspelling after true? +make: "directives.mk" line 132: Unknown directive "elsif" +make: "directives.mk" line 133: 1 taken +make: "directives.mk" line 134: Unknown directive "elsif" +make: "directives.mk" line 135: 2 taken +make: "directives.mk" line 140: Unknown directive "indented" +make: "directives.mk" line 141: Unknown directive "indented" +make: "directives.mk" line 142: Unknown directive "indented" +make: "directives.mk" line 143: Unknown directive "info" +make: "directives.mk" line 150: Could not find nonexistent.mk +make: "directives.mk" line 160: end of the tests +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/envfirst.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/envfirst.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/envfirst.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/export-variants.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-variants.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-variants.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/export-variants.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/impsrc.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/impsrc.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/impsrc.exp (revision 367461) @@ -0,0 +1,13 @@ +expected: +actual: +expected: target1.x +actual: target1.x +expected: target1.y +actual: target1.y +expected: +actual: +expected: +actual: +expected: +actual: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/impsrc.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/impsrc.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/impsrc.mk (revision 367461) @@ -0,0 +1,60 @@ +# $NetBSD: impsrc.mk,v 1.3 2020/08/07 13:43:50 rillig Exp $ + +# Does ${.IMPSRC} work properly? +# It should be set, in order of precedence, to ${.TARGET} of: +# 1) the implied source of a transformation rule, +# 2) the first prerequisite from the dependency line of an explicit rule, or +# 3) the first prerequisite of an explicit rule. +# +# Items 2 and 3 work in GNU make. +# Items 2 and 3 are not required by POSIX 2018. + +all: target1.z target2 target3 target4 + +.SUFFIXES: .x .y .z + +.x.y: source1 + @echo 'expected: target1.x' + @echo 'actual: $<' + +.y.z: source2 + @echo 'expected: target1.y' + @echo 'actual: $<' + +# (3) Making target1.z out of target1.y is done because of an inference rule. +# Therefore $< is available here. + +# (2) This is an additional dependency on the inference rule .x.y. +# The dependency target1.x comes from the inference rule, +# therefore it is available as $<. +target1.y: source3 + +# (1) This is an explicit dependency, not an inference rule. +# Therefore POSIX does not specify that $< be available here. +target1.x: source4 + @echo 'expected: ' # either 'source4' or '' + @echo 'actual: $<' + +# (4) This is an explicit dependency, independent of any inference rule. +# Therefore $< is not available here. +target2: source1 source2 + @echo 'expected: ' + @echo 'actual: $<' + +# (5) These are two explicit dependency rules. +# The first doesn't have any dependencies, only the second has. +# If any, the value of $< would be 'source2'. +target3: source1 +target3: source2 source3 + @echo 'expected: ' + @echo 'actual: $<' + +# (6) The explicit rule does not have associated commands. +# The value of $< might come from that rule, +# but it's equally fine to leave $< undefined. +target4: source1 +target4: + @echo 'expected: ' + @echo 'actual: $<' + +source1 source2 source3 source4: Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/impsrc.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/modmatch.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modmatch.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modmatch.exp (revision 367461) @@ -0,0 +1,17 @@ +LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" +LIB=b X_LIBS:M${LIB${LIB:tu}} is "" +LIB=b X_LIBS:M*/lib${LIB}.a is "" +LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=c X_LIBS:M${LIB${LIB:tu}} is "" +LIB=c X_LIBS:M*/lib${LIB}.a is "" +LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" +LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" +Mscanner=OK +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/modmisc.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modmisc.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modmisc.exp (revision 367461) @@ -0,0 +1,21 @@ +make: Unknown modifier '$' +path=':/bin:/tmp::/:.:/no/such/dir:.' +path='/bin:/tmp:/:/no/such/dir' +path='/bin:/tmp:/:/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path='/bin':'/tmp':'/':'/no/such/dir' +path_/usr/xbin=/opt/xbin/ +paths=/bin /tmp / /no/such/dir /opt/xbin +PATHS=/BIN /TMP / /NO/SUCH/DIR /OPT/XBIN +The answer is 42 +S: +C: +@: +S:empty +C:empty +@: +mod-quote: new + +line +mod-break-many-words: 500 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/modts.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/modts.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/modts.exp (revision 367461) @@ -0,0 +1,14 @@ +make: Bad modifier `:tx' for LIST +LIST:tx="}" +make: Bad modifier `:ts\X' for LIST +LIST:ts/x:tu="\X:tu}" +FU_mod-ts="a/b/cool" +FU_mod-ts:ts:T="cool" == cool? +B.${AAA:ts}="Baaa" == Baaa? +:ts :S => aaxBbxaaxbbxaaxbb +:ts :S space => axa a axc +:ts :S space :M => axaxaxaxc +:ts :S => axa a axc +:ts :S :@ => axa a axc +:ts :S :@ :M => axaxaxaxc +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-backwards.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -B command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-backwards.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-chdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -C command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-chdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-define.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-define.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-define.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-define.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-define.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-define.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-define.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -D command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-define.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-env.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-env.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-env.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -e command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-file.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-file.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-file.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-file.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-file.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-file.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-file.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -f command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-file.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-include-dir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -I command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-include-dir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-jobs-internal.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the (intentionally undocumented) -J command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs-internal.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-jobs.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -j command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.exp (revision 367461) @@ -0,0 +1,2 @@ +ok +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.mk (revision 367461) @@ -0,0 +1,61 @@ +# $NetBSD: opt-m-include-dir.mk,v 1.4 2020/09/01 20:14:34 rillig Exp $ +# +# Tests for the -m command line option, which adds a directory to the +# search path for the .include <...> directive. +# +# The .../canary.mk special argument starts searching in the current +# directory and walks towards the file system root, until it finds a +# directory that contains a file called canary.mk. +# +# To set up this scenario, the file step2.mk is created deep in a hierarchy +# of subdirectories. Another file called opt-m-step3.mk is created a few +# steps up in the directory hierarchy, serving as the canary file. +# +# Next to the canary file, there is opt-m-step3.mk. This file is found +# by mentioning its simple name in an .include directive. It defines the +# target "step2" that is needed by "step2.mk". + +.if ${.PARSEFILE:T} == "opt-m-include-dir.mk" + +# Set up the other files needed for this test. + +TEST_DIR:= ${.PARSEFILE:R}.tmp/sub/sub/sub/workdir +CANARY_FILE:= ${.PARSEFILE:R}.tmp/sub/opt-m-canary.mk +ACTUAL_FILE:= ${.PARSEFILE:R}.tmp/sub/opt-m-step3.mk + +_!= mkdir -p ${TEST_DIR} +_!= > ${CANARY_FILE} +_!= cp ${MAKEFILE} ${TEST_DIR}/step2.mk +_!= cp ${MAKEFILE} ${ACTUAL_FILE} + +step1: + @${.MAKE} -C ${TEST_DIR} -f step2.mk step2 + +.END: + @rm -rf ${MAKEFILE:R}.tmp + +.elif ${.PARSEFILE:T} == "step2.mk" + +# This is the file deep in the directory hierarchy. It sets up the +# search path for the .include <...> directive and then includes a +# single file from that search path. + +# This option adds .tmp/sub to the search path for .include <...>. +.MAKEFLAGS: -m .../opt-m-canary.mk + +# This option does not add any directory to the search path since the +# canary file does not exist. +.MAKEFLAGS: -m .../does-not-exist + +.include + +.elif ${.PARSEFILE:T} == "opt-m-step3.mk" + +# This file is included by step2.mk. + +step2: + @echo ok + +.else +. error +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-m-include-dir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-no-action-at-all.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -N command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action-at-all.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.exp (revision 367461) @@ -0,0 +1,13 @@ +command during parsing +echo '.BEGIN: hidden command' +echo '.BEGIN: run always' +.BEGIN: run always +echo 'main: hidden command' +echo 'main: run always' +main: run always +run-always: hidden command +run-always: run always +echo '.END: hidden command' +echo '.END: run always' +.END: run always +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.mk (revision 367461) @@ -0,0 +1,33 @@ +# $NetBSD: opt-no-action.mk,v 1.3 2020/08/19 05:25:26 rillig Exp $ +# +# Tests for the -n command line option, which runs almost no commands. +# It just outputs them, to be inspected by human readers. +# Only commands that are in a .MAKE target or prefixed by '+' are run. + +# This command cannot be prevented from being run since it is used at parse +# time, and any later variable assignments may depend on its result. +!= echo 'command during parsing' 1>&2; echo + +all: main +all: run-always + +# Both of these commands are printed, but only the '+' command is run. +.BEGIN: + @echo '$@: hidden command' + @+echo '$@: run always' + +# Both of these commands are printed, but only the '+' command is run. +main: + @echo '$@: hidden command' + @+echo '$@: run always' + +# None of these commands is printed, but both are run, because this target +# depends on the special source ".MAKE". +run-always: .MAKE + @echo '$@: hidden command' + @+echo '$@: run always' + +# Both of these commands are printed, but only the '+' command is run. +.END: + @echo '$@: hidden command' + @+echo '$@: run always' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-no-action.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-query.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-query.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-query.exp (revision 367461) @@ -0,0 +1,2 @@ +command during parsing +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-query.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-query.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-query.mk (revision 367461) @@ -0,0 +1,24 @@ +# $NetBSD: opt-query.mk,v 1.3 2020/08/19 05:13:18 rillig Exp $ +# +# Tests for the -q command line option. +# +# The -q option only looks at the dependencies between the targets. +# None of the commands in the targets are run, not even those that are +# prefixed with '+'. + +# This command cannot be prevented from being run since it is used at parse +# time, and any later variable assignments may depend on its result. +!= echo 'command during parsing' 1>&2; echo + +# None of these commands are run. +.BEGIN: + @echo '$@: hidden command' + @+echo '$@: run always' + +# None of these commands are run. +all: + @echo '$@: hidden command' + @+echo '$@: run always' + +# The exit status 1 is because the "all" target has to be made, that is, +# it is not up-to-date. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-query.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-raw.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -r command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-raw.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-silent.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -s command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-silent.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-touch.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -t command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-touch.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-tracefile.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -T command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-tracefile.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.exp (revision 367461) @@ -0,0 +1,3 @@ +other value $$ +value +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.mk (revision 367461) @@ -0,0 +1,6 @@ +# $NetBSD: opt-var-expanded.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# +# Tests for the -v command line option. + +VAR= other ${VALUE} $$$$ +VALUE= value Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-expanded.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.exp (revision 367461) @@ -0,0 +1,3 @@ +other ${VALUE} $$$$ +value +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.mk (revision 367461) @@ -0,0 +1,6 @@ +# $NetBSD: opt-var-literal.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# +# Tests for the -V command line option. + +VAR= other ${VALUE} $$$$ +VALUE= value Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-var-literal.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.exp (revision 367461) @@ -0,0 +1,7 @@ +make: "opt-warnings-as-errors.mk" line 5: warning: message 1 +make: parsing warnings being treated as errors +make: "opt-warnings-as-errors.mk" line 6: warning: message 2 +parsing continues +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: opt-warnings-as-errors.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# +# Tests for the -W command line option, which turns warnings into errors. + +.warning message 1 +.warning message 2 + +_!= echo 'parsing continues' 1>&2 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-warnings-as-errors.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-where-am-i.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -w command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-where-am-i.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt-x-reduce-exported.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the -x command line option. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt-x-reduce-exported.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/opt.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/opt.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/opt.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/opt.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: opt.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the command line options. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/opt.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/phony-end.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/phony-end.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/phony-end.exp (revision 367461) @@ -0,0 +1,6 @@ +.TARGET="phony" .PREFIX="phony" .IMPSRC="" +.TARGET="all" .PREFIX="all" .IMPSRC="" +.TARGET="ok" .PREFIX="ok" .IMPSRC="" +.TARGET="also.ok" .PREFIX="also.ok" .IMPSRC="" +.TARGET="bug" .PREFIX="bug" .IMPSRC="" +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/recursive.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/recursive.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/recursive.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "recursive.mk" line 34: Unclosed variable "MISSING_PAREN" +make: "recursive.mk" line 35: Unclosed variable "MISSING_BRACE" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: sh-jobs-error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for error handling in the "run in jobs mode" part of the "Shell +# Commands" section from the manual page. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs-error.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: sh-jobs.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the "run in jobs mode" part of the "Shell Commands" section +# from the manual page. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.exp (revision 367461) @@ -0,0 +1,5 @@ +ok +space after @ +echo 'echoed' +echoed +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: sh-leading-at.mk,v 1.3 2020/08/22 09:16:08 rillig Exp $ +# +# Tests for shell commands preceded by an '@', to suppress printing +# the command to stdout. + +all: + @ + @echo 'ok' + @ echo 'space after @' + echo 'echoed' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-at.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: sh-leading-hyphen.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for shell commands preceded by a '-', to ignore the exit status of +# the command line. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-hyphen.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.exp (revision 367461) @@ -0,0 +1,4 @@ +echo 'this command is not run' +echo 'this command is run' +this command is run +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: sh-leading-plus.mk,v 1.3 2020/08/23 14:46:33 rillig Exp $ +# +# Tests for shell commands preceded by a '+', to run them even if +# the command line option -n is given. + +all: + @echo 'this command is not run' + @+echo 'this command is run' Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-leading-plus.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.mk (revision 367461) @@ -0,0 +1,11 @@ +# $NetBSD: sh-meta-chars.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for running shell commands that contain meta-characters. +# +# These meta-characters decide whether the command is run by the shell +# or executed directly via execv. See Cmd_Exec for details. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-meta-chars.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: sh-multi-line.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for multi-line shell commands, to ensure that the line breaks +# are preserved. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-multi-line.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: sh-single-line.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for running single-line shell commands. +# +# In jobs mode, the shell commands are combined into a single shell +# program, as described in the manual page, section "Shell Commands", +# "the entire script". + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh-single-line.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/sh.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/sh.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/sh.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/sh.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: sh.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for running shell commands from the targets, or from the != variable +# assignment operator or the :sh variable modifier. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/sh.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/use-inference.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/use-inference.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/use-inference.exp (revision 367461) @@ -0,0 +1,4 @@ +Building use-inference.from from nothing +make: don't know how to make use-inference.to (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/use-inference.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/use-inference.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/use-inference.mk (revision 367461) @@ -0,0 +1,35 @@ +# $NetBSD: use-inference.mk,v 1.1 2020/08/09 16:32:28 rillig Exp $ +# +# Demonstrate that .USE rules do not have an effect on inference rules. +# At least not in the special case where the inference rule does not +# have any associated commands. + +.SUFFIXES: +.SUFFIXES: .from .to + +all: use-inference.to + +verbose: .USE + @echo 'Verbosely making $@ out of $>' + +.from.to: verbose +# Since this inference rule does not have any associated commands, it +# is ignored. +# +# @echo 'Building $@ from $<' + +use-inference.from: # assume it exists + @echo 'Building $@ from nothing' + +# Possible but unproven explanation: +# +# The main target is "all", which depends on "use-inference.to". +# The inference connects the .from to the .to file, otherwise make +# would not know that the .from file would need to be built. +# +# The .from file is then built. +# +# After this, make stops since it doesn't know how to make the .to file. +# This is strange since make definitely knows about the .from.to suffix +# inference rule. But it seems to ignore it, maybe because it doesn't +# have any associated commands. Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/use-inference.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: var-class-cmdline.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for variables specified on the command line. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-class-cmdline.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: var-class-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for variables specified in the process environment. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-class-env.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: var-class-global.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for global variables, which are the most common variables. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/var-class-global.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/var-class-local-legacy.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: var-class-local-legacy.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for legacy target-local variables, such as ${:Q} + @echo $@: long ${.ARCHIVE:Q} + @echo $@: abbr ${!:Q} + @echo $@: long ${.IMPSRC:Q} + @echo $@: abbr ${<:Q} + @echo $@: long ${.MEMBER:Q} + @echo $@: abbr ${%:Q} + @echo $@: long ${.OODATE:Q} + @echo $@: abbr ${?:Q} + @echo $@: long ${.PREFIX:Q} + @echo $@: abbr ${*:Q} + @echo $@: long ${.TARGET:Q} + @echo $@: abbr ${@:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varfind.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmisc.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmisc.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmisc.exp (revision 367461) @@ -0,0 +1,74 @@ + +:D expanded when var set +true +TRUE +:U expanded when var undef +true +TRUE +:D skipped if var undef + +:U skipped when var set +is set +:? only lhs when value true +true +TRUE +:? only rhs when value false +false +FALSE +do not evaluate or expand :? if discarding +is set +year=2016 month=04 day=01 +date=20160401 +Version=123.456.789 == 123456789 +Literal=3.4.5 == 3004005 +We have target specific vars +MAN= make.1 +save-dollars: 0 = $ +save-dollars: 1 = $$ +save-dollars: 2 = $$ +save-dollars: False = $ +save-dollars: True = $$ +save-dollars: false = $ +save-dollars: true = $$ +save-dollars: Yes = $$ +save-dollars: No = $ +save-dollars: yes = $$ +save-dollars: no = $ +save-dollars: On = $$ +save-dollars: Off = $ +save-dollars: ON = $$ +save-dollars: OFF = $ +save-dollars: on = $$ +save-dollars: off = $ +export-appended: env +export-appended: env +export-appended: env mk +parse-dynamic: parse-dynamic parse-dynamic before +parse-dynamic: parse-dynamic parse-dynamic after +parse-dynamic: parse-dynamic parse-dynamic after +varerror-unclosed:begin +make: Unclosed variable "" + +make: Unclosed variable "UNCLOSED" + +make: Unclosed variable "UNCLOSED" + +make: Unclosed variable "PATTERN" +make: Unclosed variable specification (expecting '}') for "UNCLOSED" (value "") modifier M + +make: Unclosed variable "param" +make: Unclosed variable "UNCLOSED." + + +make: Unclosed variable "UNCLOSED.1" + +make: Unclosed variable "UNCLOSED.2" + +make: Unclosed variable "UNCLOSED.3" + +make: Unclosed variable "UNCLOSED_ORIG" + +varerror-unclosed:end +target1-flags: we have: one two +target2-flags: we have: one two three four +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-defined.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-edge.exp (revision 367461) @@ -0,0 +1,22 @@ +make: "varmod-edge.mk" line omitted: ok M-paren +make: "varmod-edge.mk" line omitted: ok M-mixed +make: "varmod-edge.mk" line omitted: ok M-unescape +make: Unclosed variable specification (expecting '}') for "" (value "*)") modifier U +make: "varmod-edge.mk" line omitted: ok M-nest-mix +make: "varmod-edge.mk" line omitted: ok M-nest-brk +make: "varmod-edge.mk" line omitted: ok M-pat-err +make: "varmod-edge.mk" line omitted: ok M-bsbs +make: "varmod-edge.mk" line omitted: ok M-bs1-par +make: "varmod-edge.mk" line omitted: ok M-bs2-par +make: "varmod-edge.mk" line omitted: ok M-128 +make: "varmod-edge.mk" line omitted: ok eq-ext +make: "varmod-edge.mk" line omitted: ok eq-q +make: "varmod-edge.mk" line omitted: ok eq-bs +make: Unfinished modifier for INP.eq-esc ('=' missing) +make: "varmod-edge.mk" line omitted: ok eq-esc +make: "varmod-edge.mk" line omitted: ok colon +make: Unknown modifier ':' +make: Unknown modifier ':' +make: "varmod-edge.mk" line omitted: ok colons +ok +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-exclam-shell.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.exp (revision 367461) @@ -0,0 +1,10 @@ +extension of 'a/b/c' is '' +extension of 'def' is '' +extension of 'a.b.c' is 'c' +extension of 'a.b/c' is 'b/c' +extension of 'a' is '' +extension of 'a.a' is 'a' +extension of '.gitignore' is 'gitignore' +extension of 'a' is '' +extension of 'a.a' is 'a' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-extension.mk,v 1.3 2020/08/23 15:09:15 rillig Exp $ +# +# Tests for the :E variable modifier, which returns the filename extension +# of each word in the variable. + +all: +.for path in a/b/c def a.b.c a.b/c a a.a .gitignore a a.a + @echo "extension of '"${path:Q}"' is '"${path:E:Q}"'" +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-extension.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-hash.exp (revision 367461) @@ -0,0 +1,9 @@ +make: Unknown modifier 'h' + +26bb0f5f +12345 +make: Unknown modifier 'h' + +make: Unknown modifier 'h' + +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.exp (revision 367461) @@ -0,0 +1,10 @@ +head (dirname) of 'a/b/c' is 'a/b' +head (dirname) of 'def' is '.' +head (dirname) of 'a.b.c' is '.' +head (dirname) of 'a.b/c' is 'a.b' +head (dirname) of 'a' is '.' +head (dirname) of 'a.a' is '.' +head (dirname) of '.gitignore' is '.' +head (dirname) of 'a' is '.' +head (dirname) of 'a.a' is '.' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-head.mk,v 1.3 2020/08/23 15:09:15 rillig Exp $ +# +# Tests for the :H variable modifier, which returns the dirname of +# each of the words in the variable value. + +all: +.for path in a/b/c def a.b.c a.b/c a a.a .gitignore a a.a + @echo "head (dirname) of '"${path:Q}"' is '"${path:H:Q}"'" +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-head.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-l-name-to-value.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-no-match.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :N variable modifier, which filters words that do not match +# the given pattern. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-no-match.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-reverse.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order-shuffle.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-order.exp (revision 367461) @@ -0,0 +1,7 @@ +make: Bad modifier `:OX' for NUMBERS +make: "varmod-order.mk" line 13: Undefined variable "${NUMBERS:OX" +make: Bad modifier `:OxXX' for NUMBERS +make: "varmod-order.mk" line 16: Undefined variable "${NUMBERS:Ox" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.exp (revision 367461) @@ -0,0 +1,4 @@ +varmod-path.subdir/varmod-path.phony +varmod-path.subdir/varmod-path.real +varmod-path.enoent +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.mk (revision 367461) @@ -0,0 +1,35 @@ +# $NetBSD: varmod-path.mk,v 1.3 2020/08/23 08:10:49 rillig Exp $ +# +# Tests for the :P variable modifier, which looks up the path for a given +# target. +# +# The phony target does not have a corresponding path, therefore ... oops, +# as of 2020-08-23 it is nevertheless resolved to a path. This is probably +# unintended. +# +# The real target is located in a subdirectory, and its full path is returned. +# If it had been in the current directory, the difference between its path and +# its name would not be visible. +# +# The enoent target does not exist, therefore the target name is returned. + +.MAIN: all + +_!= rm -rf varmod-path.subdir +_!= mkdir varmod-path.subdir +_!= > varmod-path.subdir/varmod-path.phony +_!= > varmod-path.subdir/varmod-path.real + +# To have an effect, this .PATH declaration must be after the directory is created. +.PATH: varmod-path.subdir + +varmod-path.phony: .PHONY +varmod-path.real: + +all: varmod-path.phony varmod-path.real + @echo ${varmod-path.phony:P} + @echo ${varmod-path.real:P} + @echo ${varmod-path.enoent:P} + +.END: + @rm -rf varmod-path.subdir Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-path.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.mk (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: varmod-quote-dollar.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :q variable modifier, which quotes the string for the shell +# and doubles dollar signs, to prevent them from being interpreted by a +# child process of make. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote-dollar.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-quote.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.exp (revision 367461) @@ -0,0 +1,3 @@ +1 2 3 1 2 3 1 2 3 +1 2 3, SAVED=3 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.mk (revision 367461) @@ -0,0 +1,12 @@ +# $NetBSD: varmod-remember.mk,v 1.3 2020/08/23 15:18:43 rillig Exp $ +# +# Tests for the :_ modifier, which saves the current variable value +# in the _ variable or another, to be used later again. + +# In the parameterized form, having the variable name on the right side of +# the = assignment operator is confusing. In almost all other situations +# the variable name is on the left-hand side of the = operator. Luckily +# this modifier is only rarely needed. +all: + @echo ${1 2 3:L:_:@var@${_}@} + @echo ${1 2 3:L:@var@${var:_=SAVED:}@}, SAVED=${SAVED} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-remember.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.exp (revision 367461) @@ -0,0 +1,10 @@ +root of 'a/b/c' is 'a/b/c' +root of 'def' is 'def' +root of 'a.b.c' is 'a.b' +root of 'a.b/c' is 'a' +root of 'a' is 'a' +root of 'a.a' is 'a' +root of '.gitignore' is '' +root of 'a' is 'a' +root of 'a.a' is 'a' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-root.mk,v 1.3 2020/08/23 15:09:15 rillig Exp $ +# +# Tests for the :R variable modifier, which returns the filename root +# without the extension. + +all: +.for path in a/b/c def a.b.c a.b/c a a.a .gitignore a a.a + @echo "root of '"${path:Q}"' is '"${path:R:Q}"'" +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-root.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-select-words.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :[...] variable modifier, which selects a single word +# or a range of words from a variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-select-words.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-shell.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :sh variable modifier, which runs the shell command +# given by the variable value and returns its output. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-shell.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst-regex.exp (revision 367461) @@ -0,0 +1,23 @@ +make: Regex compilation error: (details omitted) +mod-regex-compile-error: C,word,____,:Q}. +make: No subexpression \1 +make: No subexpression \1 +make: No subexpression \1 +make: No subexpression \1 +mod-regex-limits:11-missing:1 6 +mod-regex-limits:11-ok:1 22 446 +make: No subexpression \2 +make: No subexpression \2 +make: No subexpression \2 +make: No subexpression \2 +mod-regex-limits:22-missing:1 6 +make: No subexpression \2 +make: No subexpression \2 +make: No subexpression \2 +make: No subexpression \2 +mod-regex-limits:22-missing:1 6 +mod-regex-limits:22-ok:1 33 556 +mod-regex-limits:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest +make: Regex compilation error: (details omitted) +mod-regex-errors: +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-subst.exp (revision 367461) @@ -0,0 +1,51 @@ +mod-subst: +:a b b c: +:a b b c: +: b c: +:a c: +:x__ 3 x__ 3: +12345 +mod-subst-delimiter: +1 two 3 horizontal tabulator +1 two 3 space +1 two 3 exclamation mark +1 two 3 double quotes +1 two 3 hash +1 two 3 dollar +1 two 3 percent +1 two 3 apostrophe +1 two 3 opening parenthesis +1 two 3 closing parenthesis +1 two 3 digit +1 two 3 colon +1 two 3 less than sign +1 two 3 equal sign +1 two 3 greater than sign +1 two 3 question mark +1 two 3 at +1 two 3 letter +1 two 3 opening bracket +1 two 3 backslash +1 two 3 closing bracket +1 two 3 caret +1 two 3 opening brace +1 two 3 vertical line +1 two 3 closing brace +1 two 3 tilde +mod-subst-chain: +A B c. +make: Unknown modifier 'i' +. +mod-subst-dollar:$1: +mod-subst-dollar:$2: +mod-subst-dollar:$3: +mod-subst-dollar:$4: +mod-subst-dollar:$5: +mod-subst-dollar:$6: +mod-subst-dollar:$7: +mod-subst-dollar:$8: +mod-subst-dollar:$40: +mod-subst-dollar:U8: +mod-subst-dollar:$$$$: +mod-subst-dollar:$$$good3 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.exp (revision 367461) @@ -0,0 +1,10 @@ +tail (basename) of 'a/b/c' is 'c' +tail (basename) of 'def' is 'def' +tail (basename) of 'a.b.c' is 'a.b.c' +tail (basename) of 'a.b/c' is 'c' +tail (basename) of 'a' is 'a' +tail (basename) of 'a.a' is 'a.a' +tail (basename) of '.gitignore' is '.gitignore' +tail (basename) of 'a' is 'a' +tail (basename) of 'a.a' is 'a.a' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-tail.mk,v 1.3 2020/08/23 15:09:15 rillig Exp $ +# +# Tests for the :T variable modifier, which returns the basename of each of +# the words in the variable value. + +all: +.for path in a/b/c def a.b.c a.b/c a a.a .gitignore a a.a + @echo "tail (basename) of '"${path:Q}"' is '"${path:T:Q}"'" +.endfor Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-tail.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-to-abs.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :tA variable modifier, which returns the absolute path for +# each of the words in the variable value. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-abs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-lower.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-to-many-words.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :tw modifier, which treats the variable as many words, +# to undo a previous :tW modifier. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-many-words.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.mk (revision 367461) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-to-one-word.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :tW variable modifier, which treats the variable value +# as a single word, for all following modifiers. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-one-word.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-to-upper.exp (revision 367461) @@ -0,0 +1,2 @@ +mod-tu-space: A B +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-undefined.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.mk (revision 367461) @@ -0,0 +1,39 @@ +# $NetBSD: varmod-unique.mk,v 1.4 2020/08/31 17:41:38 rillig Exp $ +# +# Tests for the :u variable modifier, which discards adjacent duplicate +# words. + +.if ${:U1 2 1:u} != "1 2 1" +. warning The :u modifier only merges _adjacent_ duplicate words. +.endif + +.if ${:U1 2 2 3:u} != "1 2 3" +. warning The :u modifier must merge adjacent duplicate words. +.endif + +.if ${:U:u} != "" +. warning The :u modifier must do nothing with an empty word list. +.endif + +.if ${:U1:u} != "1" +. warning The :u modifier must do nothing with a single-element word list. +.endif + +.if ${:U1 1 1 1 1 1 1 1:u} != "1" +. warning The :u modifier must merge _all_ adjacent duplicate words. +.endif + +.if ${:U 1 2 1 1 :u} != "1 2 1" +. warning The :u modifier must normalize whitespace between the words. +.endif + +.if ${:U1 1 1 1 2:u} != "1 2" +. warning Duplicate words at the beginning must be merged. +.endif + +.if ${:U1 2 2 2 2:u} != "1 2" +. warning Duplicate words at the end must be merged. +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varmod-unique.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "varname-dollar.mk" line 16: dollar is $. +make: "varname-dollar.mk" line 17: dollar in braces is . +make: "varname-dollar.mk" line 25: dollar is $. +make: "varname-dollar.mk" line 26: dollar in braces is dollar. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.mk (revision 367461) @@ -0,0 +1,29 @@ +# $NetBSD: varname-dollar.mk,v 1.3 2020/08/19 05:40:06 rillig Exp $ +# +# Tests for the expression "$$", which looks as if it referred to a variable, +# but simply expands to a single '$' sign. +# +# If there really were a special variable named '$', the expressions ${${DOLLAR}} +# and $$ would always expand to the same value. + +# Using the dollar sign in variable names is tricky and not recommended. +# To see that using this variable indeed affects the variable '$', run the +# test individually with the -dv option. +DOLLAR= $$ + +# At this point, the variable '$' is not defined. Therefore the second line +# returns an empty string. +.info dollar is $$. +.info dollar in braces is ${${DOLLAR}}. + +# Now overwrite the '$' variable to see whether '$$' really expands to that +# variable, or whether '$$' is handled by the parser. +${DOLLAR}= dollar + +# At this point, the variable '$' is defined, therefore its value is printed +# in the second .info directive. +.info dollar is $$. +.info dollar in braces is ${${DOLLAR}}. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dollar.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.exp (revision 367461) @@ -0,0 +1,4 @@ + +first second source +first second source all .END +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.mk (revision 367461) @@ -0,0 +1,25 @@ +# $NetBSD: varname-dot-alltargets.mk,v 1.3 2020/08/25 22:51:54 rillig Exp $ +# +# Tests for the special .ALLTARGETS variable. + +.MAIN: all + +TARGETS_1:= ${.ALLTARGETS} + +first second: source + +TARGETS_2:= ${.ALLTARGETS} + +all: + # Since the tests are run with the -r option, no targets are + # defined at the beginning. + @echo ${TARGETS_1} + + # Only first and second are "real" targets. + # The .ALLTARGETS variable is not about targets though, but + # about all nodes, therefore source is also included. + @echo ${TARGETS_2} + + # Interestingly, the .END target is also implicitly defined at + # this point. + @echo ${.ALLTARGETS} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-alltargets.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-curdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-includedfromdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .INCLUDEDFROMDIR variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-includedfromfile.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .INCLUDEDFROMFILE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includedfromfile.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.exp (revision 367461) @@ -0,0 +1,2 @@ +.INCLUDES= -I. -I.. +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-includes.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.exp (revision 367461) @@ -0,0 +1,2 @@ +.LIBS= -L. -L.. +exit status 0 Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-libs.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-dependfile.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.DEPENDFILE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-dependfile.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-expand_variables.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.EXPAND_VARIABLES variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-expand_variables.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-exported.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.EXPORTED variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-exported.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-jobs-prefix.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.JOBS.PREFIX variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs-prefix.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-jobs.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.JOBS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-jobs.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-level.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.LEVEL variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-level.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-makefile_preference.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.MAKEFILE_PREFERENCE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefile_preference.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-makefiles.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.MAKEFILES variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-makefiles.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-bailiwick.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.BAILIWICK variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-bailiwick.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-created.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.CREATED variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-created.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-files.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.FILES variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-files.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-ignore_filter.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.IGNORE_FILTER variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_filter.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-ignore_paths.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.IGNORE_PATHS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_paths.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-ignore_patterns.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.IGNORE_PATTERNS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-ignore_patterns.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-meta-prefix.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.META.PREFIX variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-meta-prefix.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-mode.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.MODE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-mode.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-path_filemon.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.PATH_FILEMON variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-path_filemon.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-pid.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.PID variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-pid.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-ppid.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.PPID variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-ppid.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-make-save_dollars.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.SAVE_DOLLARS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-make-save_dollars.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-makeoverrides.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.MAKEOVERRIDES variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-makeoverrides.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-newline.exp (revision 367461) @@ -0,0 +1,4 @@ +make: "varname-dot-newline.mk" line 16: The .newline variable can be overwritten. Just don't do that. +first +second +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-objdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .OBJDIR variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-objdir.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-path.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-targets.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .TARGETS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-dot-targets.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-make.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-make.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-make.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special MAKE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-make.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-makeflags.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special MAKEFLAGS variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-makeflags.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-pwd.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special PWD variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-pwd.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.mk (revision 367461) @@ -0,0 +1,8 @@ +# $NetBSD: varname-vpath.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special VPATH variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varname-vpath.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varname.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varname.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varname.exp (revision 367461) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varparse-dynamic.exp (revision 367461) @@ -0,0 +1,5 @@ +make: "varparse-dynamic.mk" line 8: Malformed conditional (${.TARGEX}) +make: "varparse-dynamic.mk" line 10: Malformed conditional (${.TARGXX}) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/cond-short.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/cond-short.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/cond-short.exp (revision 367461) @@ -0,0 +1,16 @@ +expected and +expected and exists +expected and empty +expected U23 condition +expected VAR23 +expected M pattern +expected or +expected or exists +expected or empty +defined(V42) && 42 > 0: Ok +defined(V66) && ( "" < 42 ): Ok +1 || 42 < 42: Ok +1 || < 42: Ok +0 || 42 <= 42: Ok +0 || < 42: Ok +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/Makefile.config.in =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/Makefile.config.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/Makefile.config.in (revision 367461) @@ -0,0 +1,4 @@ +# $Id: Makefile.config.in,v 1.1 2018/12/30 17:14:24 sjg Exp $ + +srcdir= @srcdir@ +DIFF_FLAGS?= @diff_u@ Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/Makefile.config.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/dollar.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dollar.exp (revision 367461) @@ -0,0 +1,51 @@ + +Printing dollar from literals and variables + +To survive the parser, a dollar character must be doubled. + 1 dollar literal => + 1 dollar literal eol => <> + 2 dollar literal => <$> + 4 dollar literal => <$$> +Some hungry part of make eats all the dollars after a :U modifier. + 1 dollar default => <> + 2 dollar default => <> + 4 dollar default => <> +This works as expected. + 1 dollar variable => <> + 2 dollar variable => <$> + 4 dollar variable => <$$> +Some hungry part of make eats all the dollars after a :U modifier. + 1 dollar var-default => <> + 2 dollar var-default => <$> + 4 dollar var-default => <$$> + +Dollar in :S pattern + + S,$,word, => <$XYword> + S,$X,word, => <$XY> + S,$$X,word, => <$XY> + S,$$$X,word, => <$XY> + S,$X,replaced, => + S,$$X,replaced, => + S,$$$X,replaced, => + +Dollar in :C character class + +The A is replaced because the $$ is reduced to a single $, +which is then resolved to the variable X with the value VAR_X. +The effective character class becomes [VAR_XY]. + C,[$$XY],<&>,g => <$> + +Dollar in :C pattern + +For some reason, multiple dollars are folded into one. + C,$,dollar,g => <> + C,$$,dollar,g => <> + +Dollar in :S replacement + +For some reason, multiple dollars are folded into one. + S,word,a$Xo, => + S,word,a$$Xo, => + S,word,a$$$Xo, => +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dollar.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dollar.mk (revision 367461) @@ -0,0 +1,81 @@ +# $NetBSD: dollar.mk,v 1.3 2020/05/17 09:37:48 rillig Exp $ +# +# Test the various places where a dollar character can appear and +# see what happens. There are lots of surprises here. +# + +LIST= plain 'single' "double" 'mix'"ed" back\ slashed +WORD= word + +DOLLAR1= $ +DOLLAR2= $$ +DOLLAR4= $$$$ + +X= VAR_X +DOLLAR_XY= $$XY +DOLLAR_AXY= $$AXY + +H= @header() { printf '\n%s\n\n' "$$*"; }; header +T= @testcase() { printf '%23s => <%s>\n' "$$@"; }; testcase +C= @comment() { printf '%s\n' "$$*"; }; comment + +# These variable values are not accessed. +# The trailing dollar in the '1 dollar literal eol' test case accesses +# the empty variable instead, which is always guaranteed to be empty. +${:U }= space-var-value +${:U${.newline}}= newline-var-value +# But this one is accessed. +${:U'}= single-quote-var-value' + +all: + $H 'Printing dollar from literals and variables' + + $C 'To survive the parser, a dollar character must be doubled.' + $T '1 dollar literal' '$' + $T '1 dollar literal eol' ''$ + $T '2 dollar literal' '$$' + $T '4 dollar literal' '$$$$' + + $C 'Some hungry part of make eats all the dollars after a :U modifier.' + $T '1 dollar default' ''${:U$:Q} + $T '2 dollar default' ''${:U$$:Q} + $T '4 dollar default' ''${:U$$$$:Q} + + $C 'This works as expected.' + $T '1 dollar variable' ''${DOLLAR1:Q} + $T '2 dollar variable' ''${DOLLAR2:Q} + $T '4 dollar variable' ''${DOLLAR4:Q} + + $C 'Some hungry part of make eats all the dollars after a :U modifier.' + $T '1 dollar var-default' ''${:U${DOLLAR1}:Q} + $T '2 dollar var-default' ''${:U${DOLLAR2}:Q} + $T '4 dollar var-default' ''${:U${DOLLAR4}:Q} + + $H 'Dollar in :S pattern' + + $T 'S,$$,word,' ''${DOLLAR_XY:S,$,word,:Q} + $T 'S,$$X,word,' ''${DOLLAR_XY:S,$X,word,:Q} + $T 'S,$$$$X,word,' ''${DOLLAR_XY:S,$$X,word,:Q} + $T 'S,$$$$$$X,word,' ''${DOLLAR_XY:S,$$$X,word,:Q} + + $T 'S,$$X,replaced,' ''${X:S,$X,replaced,:Q} + $T 'S,$$$$X,replaced,' ''${X:S,$$X,replaced,:Q} + $T 'S,$$$$$$X,replaced,' ''${X:S,$$$X,replaced,:Q} + + $H 'Dollar in :C character class' + + $C 'The A is replaced because the $$$$ is reduced to a single $$,' + $C 'which is then resolved to the variable X with the value VAR_X.' + $C 'The effective character class becomes [VAR_XY].' + $T 'C,[$$$$XY],<&>,g' ''${DOLLAR_AXY:C,[$$XY],<&>,g:Q} + + $H 'Dollar in :C pattern' + $C 'For some reason, multiple dollars are folded into one.' + $T 'C,$$,dollar,g' ''${DOLLAR:C,$,dollar,g:Q} + $T 'C,$$$$,dollar,g' ''${DOLLAR:C,$$,dollar,g:Q} + + $H 'Dollar in :S replacement' + $C 'For some reason, multiple dollars are folded into one.' + $T 'S,word,a$$Xo,' ''${WORD:S,word,a$Xo,:Q} + $T 'S,word,a$$$$Xo,' ''${WORD:S,word,a$$Xo,:Q} + $T 'S,word,a$$$$$$Xo,' ''${WORD:S,word,a$$$Xo,:Q} Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/dollar.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varquote.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varquote.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varquote.mk (revision 367461) @@ -0,0 +1,14 @@ +# $NetBSD: varquote.mk,v 1.4 2018/12/16 18:53:34 christos Exp $ +# +# Test VAR:q modifier + +.if !defined(REPROFLAGS) +REPROFLAGS+= -fdebug-prefix-map=\$$NETBSDSRCDIR=/usr/src +REPROFLAGS+= -fdebug-regex-map='/usr/src/(.*)/obj$$=/usr/obj/\1' +all: + @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:S/\$/&&/g:Q} + @${MAKE} -f ${MAKEFILE} REPROFLAGS=${REPROFLAGS:q} +.else +all: + @printf "%s %s\n" ${REPROFLAGS} +.endif Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/varquote.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/varquote.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varquote.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varquote.exp (revision 367461) @@ -0,0 +1,3 @@ +-fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1 +-fdebug-prefix-map=$NETBSDSRCDIR=/usr/src -fdebug-regex-map=/usr/src/(.*)/obj$=/usr/obj/\1 +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/varcmd.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/varcmd.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/varcmd.exp (revision 367461) @@ -0,0 +1,11 @@ +default FU=fu FOO=foo VAR= +two FU=bar FOO=goo VAR= +immutable FU='bar' +immutable FOO='goo' +three FU=bar FOO=goo VAR= +four FU=bar FOO=goo VAR=Internal +five FU=bar FOO=goo VAR=Internal +five v=is x k=is x +six v=is y k=is y +show-v v=override k=override +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/dotwait.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/dotwait.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/dotwait.exp (revision 367461) @@ -0,0 +1,30 @@ +simple.1 +simple.1 +simple.2 +simple.2 +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.99 +recursive.1.99 +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.99 +recursive.2.99 +shared.0 +shared.0 +shared.1.99 +shared.1.99 +shared.2.1 +shared.2.1 +shared.2.99 +shared.2.99 +cycle.1.99 +cycle.1.99 +make: Graph cycles through `cycle.2.99' +make: Graph cycles through `cycle.2.98' +make: Graph cycles through `cycle.2.97' +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/export-env.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-env.exp (revision 367461) @@ -0,0 +1,11 @@ +make: +UT_TEST=export-env.mk +UT_ENV=not-exported +UT_EXP=not-exported +UT_LIT=literal export-env.mk +env: +UT_TEST=export-env.mk +UT_ENV=exported +UT_EXP=exported +UT_LIT=literal ${UT_TEST} +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/doterror.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/doterror.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/doterror.exp (revision 367461) @@ -0,0 +1,9 @@ +At first, I am +happy +and now: sad +*** Error code 1 + +Stop. +make: stopped in unit-tests +.ERROR: Looks like 'sad' is upset. +exit status 1 Index: vendor/NetBSD/bmake/20201101/unit-tests/escape.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/escape.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/escape.exp (revision 367461) @@ -0,0 +1,104 @@ +var-1bs +printf "%s=:%s:\n" VAR1BS 111\\111; printf "%s=:%s:\n" VAR1BSa 111\\aaa; printf "%s=:%s:\n" VAR1BSA 111\\aaa; printf "%s=:%s:\n" VAR1BSda 111\\\$\{a\}; printf "%s=:%s:\n" VAR1BSdA 111\\\$\{A\}; printf "%s=:%s:\n" VAR1BSc 111\#\ backslash\ escapes\ comment\ char,\ so\ this\ is\ part\ of\ the\ value; printf "%s=:%s:\n" VAR1BSsc 111\\\ ; +VAR1BS=:111\111: +VAR1BSa=:111\aaa: +VAR1BSA=:111\aaa: +VAR1BSda=:111\${a}: +VAR1BSdA=:111\${A}: +VAR1BSc=:111# backslash escapes comment char, so this is part of the value: +VAR1BSsc=:111\ : +var-2bs +printf "%s=:%s:\n" VAR2BS 222\\\\222; printf "%s=:%s:\n" VAR2BSa 222\\\\aaa; printf "%s=:%s:\n" VAR2BSA 222\\\\aaa; printf "%s=:%s:\n" VAR2BSda 222\\\\\$\{a\}; printf "%s=:%s:\n" VAR2BSdA 222\\\\\$\{A\}; printf "%s=:%s:\n" VAR2BSc 222\\\\; printf "%s=:%s:\n" VAR2BSsc 222\\\\; +VAR2BS=:222\\222: +VAR2BSa=:222\\aaa: +VAR2BSA=:222\\aaa: +VAR2BSda=:222\\${a}: +VAR2BSdA=:222\\${A}: +VAR2BSc=:222\\: +VAR2BSsc=:222\\: +var-1bsnl +printf "%s=:%s:\n" VAR1BSNL 111\ 111; printf "%s=:%s:\n" VAR1BSNLa 111\ aaa; printf "%s=:%s:\n" VAR1BSNLA 111\ aaa; printf "%s=:%s:\n" VAR1BSNLda 111\ \$\{a\}; printf "%s=:%s:\n" VAR1BSNLdA 111\ \$\{A\}; printf "%s=:%s:\n" VAR1BSNLc 111; printf "%s=:%s:\n" VAR1BSNLsc 111; +VAR1BSNL=:111 111: +VAR1BSNLa=:111 aaa: +VAR1BSNLA=:111 aaa: +VAR1BSNLda=:111 ${a}: +VAR1BSNLdA=:111 ${A}: +VAR1BSNLc=:111: +VAR1BSNLsc=:111: +var-2bsnl +printf "%s=:%s:\n" VAR2BSNL 222\\\\; printf "%s=:%s:\n" VAR2BSNLa 222\\\\; printf "%s=:%s:\n" VAR2BSNLA 222\\\\; printf "%s=:%s:\n" VAR2BSNLda 222\\\\; printf "%s=:%s:\n" VAR2BSNLdA 222\\\\; printf "%s=:%s:\n" VAR2BSNLc 222\\\\; printf "%s=:%s:\n" VAR2BSNLsc 222\\\\; +VAR2BSNL=:222\\: +VAR2BSNLa=:222\\: +VAR2BSNLA=:222\\: +VAR2BSNLda=:222\\: +VAR2BSNLdA=:222\\: +VAR2BSNLc=:222\\: +VAR2BSNLsc=:222\\: +var-3bsnl +printf "%s=:%s:\n" VAR3BSNL 333\\\\\ 333=; printf "%s=:%s:\n" VAR3BSNLa 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLA 333\\\\\ aaa=; printf "%s=:%s:\n" VAR3BSNLda 333\\\\\ \$\{a\}=; printf "%s=:%s:\n" VAR3BSNLdA 333\\\\\ \$\{A\}=; printf "%s=:%s:\n" VAR3BSNLc 333\\\\; printf "%s=:%s:\n" VAR3BSNLsc 333\\\\; +VAR3BSNL=:333\\ 333=: +VAR3BSNLa=:333\\ aaa=: +VAR3BSNLA=:333\\ aaa=: +VAR3BSNLda=:333\\ ${a}=: +VAR3BSNLdA=:333\\ ${A}=: +VAR3BSNLc=:333\\: +VAR3BSNLsc=:333\\: +var-1bsnl-space +printf "%s=:%s:\n" VAR1BSNL00 first\ line; printf "%s=:%s:\n" VAR1BSNL0 first\ line\ no\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLs first\ line\ one\ space\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLss first\ line\ two\ spaces\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLt first\ line\ one\ tab\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLtt first\ line\ two\ tabs\ on\ second\ line; printf "%s=:%s:\n" VAR1BSNLxx first\ line\ many\ spaces\ and\ tabs\ \[\ \ \ \ \]\ on\ second\ line; +VAR1BSNL00=:first line: +VAR1BSNL0=:first line no space on second line: +VAR1BSNLs=:first line one space on second line: +VAR1BSNLss=:first line two spaces on second line: +VAR1BSNLt=:first line one tab on second line: +VAR1BSNLtt=:first line two tabs on second line: +VAR1BSNLxx=:first line many spaces and tabs [ ] on second line: +cmd-1bsnl +echo :'first line\ +#second line without space\ +third line': +:first line\ +#second line without space\ +third line: +echo :'first line\ + second line spaces should be retained': +:first line\ + second line spaces should be retained: +echo :'first line\ +second line tab should be elided': +:first line\ +second line tab should be elided: +echo :'first line\ + only one tab should be elided, second tab remains' +:first line\ + only one tab should be elided, second tab remains +cmd-1bsnl-eof +echo :'command ending with backslash-newline'; \ + +:command ending with backslash-newline +cmd-2bsnl +echo take one\\ +take one\ +echo take two\\ +take two\ +echo take three\\ +take three\ +cmd-3bsnl +echo :'first line\\\ +#second line without space\\\ +third line': +:first line\\\ +#second line without space\\\ +third line: +echo :'first line\\\ + second line spaces should be retained': +:first line\\\ + second line spaces should be retained: +echo :'first line\\\ +second line tab should be elided': +:first line\\\ +second line tab should be elided: +echo :'first line\\\ + only one tab should be elided, second tab remains' +:first line\\\ + only one tab should be elided, second tab remains +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/export-all.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/export-all.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/export-all.exp (revision 367461) @@ -0,0 +1,12 @@ +UT_ALL=even this gets exported +UT_BADDIR=unit-tests +UT_DOLLAR=This is $UT_FU +UT_F=fine +UT_FOO=foobar is fubar +UT_FU=fubar +UT_NO=all +UT_OK=good +UT_OKDIR=unit-tests +UT_TEST=export-all +UT_ZOO=hoopie +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/forsubst.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/forsubst.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/forsubst.exp (revision 367461) @@ -0,0 +1,2 @@ +.for with :S;... OK +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/order.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/order.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/order.exp (revision 367461) @@ -0,0 +1,4 @@ +Making the.c +Making the.h +Making the.o from the.h the.c +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/order.mk =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/order.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/order.mk (revision 367461) @@ -0,0 +1,20 @@ +# $NetBSD: order.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ + +# Test that .ORDER is handled correctly. +# The explicit dependency the.o: the.h will make us examine the.h +# the .ORDER will prevent us building it immediately, +# we should then examine the.c rather than stop. + +all: the.o + +.ORDER: the.c the.h + +the.c the.h: + @echo Making $@ + +.SUFFIXES: .o .c + +.c.o: + @echo Making $@ from $? + +the.o: the.h Property changes on: vendor/NetBSD/bmake/20201101/unit-tests/order.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/unit-tests/posix.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/posix.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/posix.exp (revision 367461) @@ -0,0 +1,23 @@ +Posix says we should execute the command as if run by system(3) +Expect 'Hello,' and 'World!' +Hello, +World! +a command +a command prefixed by '+' executes even with -n +another command +make -n +echo a command +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +echo another command +make -n -j1 +{ echo a command +} || exit $? +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +{ echo another command +} || exit $? +Now we expect an error... +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20201101/unit-tests/posix1.exp =================================================================== --- vendor/NetBSD/bmake/20201101/unit-tests/posix1.exp (nonexistent) +++ vendor/NetBSD/bmake/20201101/unit-tests/posix1.exp (revision 367461) @@ -0,0 +1,185 @@ +${VAR} = "foo bar baz" +a +b +c +foo baR baz, bar baz, foo bar baz, fooadd baradd bazadd +mkdir -p 'dir' +touch 'dir/obj_1.h' +mkdir -p 'dir' +printf '#include "obj_1.h"\nconst char* obj_1 = "dir/obj_1.c";\n' \ + >'dir/obj_1.c' +Local variables + ${@}="dir/obj_1.o" ${<}="dir/obj_1.c" + ${*}="dir/obj_1" ${?}="dir/obj_1.h dir/obj_1.c" + ${%}="" + +Directory and filename parts of local variables + ${@D}="dir" ${@F}="obj_1.o" + ${'obj_2.c' +mkdir -p '.' +touch 'obj_2.h' +Local variables + ${@}="obj2.o" ${<}="obj_2.c" + ${*}="obj2" ${?}="obj_2.c obj_2.h dir/obj_1.h" + ${%}="" + +Directory and filename parts of local variables + ${@D}="." ${@F}="obj2.o" + ${'obj3.c' +Local variables + ${@}="lib.a" ${<}="obj3.c" + ${*}="obj3" ${?}="obj3.h dir/dummy obj3.c" + ${%}="obj3.o" + +Directory and filename parts of local variables + ${@D}="." ${@F}="lib.a" + ${ +#include +#include +#include + +#include "make.h" + +MAKE_RCSID("$NetBSD: util.c,v 1.64 2020/10/06 21:51:33 rillig Exp $"); + +#if !defined(MAKE_NATIVE) && !defined(HAVE_STRERROR) +extern int errno, sys_nerr; +extern char *sys_errlist[]; + +char * +strerror(int e) +{ + static char buf[100]; + if (e < 0 || e >= sys_nerr) { + snprintf(buf, sizeof(buf), "Unknown error %d", e); + return buf; + } + else + return sys_errlist[e]; +} +#endif + +#if !defined(HAVE_GETENV) || !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) +extern char **environ; + +static char * +findenv(const char *name, int *offset) +{ + size_t i, len; + char *p, *q; + + len = strlen(name); + for (i = 0; (q = environ[i]); i++) { + p = strchr(q, '='); + if (p == NULL || p - q != len) + continue; + if (strncmp(name, q, len) == 0) { + *offset = i; + return q + len + 1; + } + } + *offset = i; + return NULL; +} + +char * +getenv(const char *name) +{ + int offset; + + return findenv(name, &offset); +} + +int +unsetenv(const char *name) +{ + char **p; + int offset; + + if (name == NULL || *name == '\0' || strchr(name, '=') != NULL) { + errno = EINVAL; + return -1; + } + + while (findenv(name, &offset)) { /* if set multiple times */ + for (p = &environ[offset];; ++p) + if (!(*p = *(p + 1))) + break; + } + return 0; +} + +int +setenv(const char *name, const char *value, int rewrite) +{ + char *c, **newenv; + const char *cc; + size_t l_value, size; + int offset; + + if (name == NULL || value == NULL) { + errno = EINVAL; + return -1; + } + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + + /* find if already exists */ + if ((c = findenv(name, &offset))) { + if (!rewrite) + return 0; + if (strlen(c) >= l_value) /* old larger; copy over */ + goto copy; + } else { /* create new slot */ + size = sizeof(char *) * (offset + 2); + if (savedEnv == environ) { /* just increase size */ + if ((newenv = realloc(savedEnv, size)) == NULL) + return -1; + savedEnv = newenv; + } else { /* get new space */ + /* + * We don't free here because we don't know if + * the first allocation is valid on all OS's + */ + if ((savedEnv = malloc(size)) == NULL) + return -1; + (void)memcpy(savedEnv, environ, size - sizeof(char *)); + } + environ = savedEnv; + environ[offset + 1] = NULL; + } + for (cc = name; *cc && *cc != '='; ++cc) /* no `=' in name */ + continue; + size = cc - name; + /* name + `=' + value */ + if ((environ[offset] = malloc(size + l_value + 2)) == NULL) + return -1; + c = environ[offset]; + (void)memcpy(c, name, size); + c += size; + *c++ = '='; +copy: + (void)memcpy(c, value, l_value + 1); + return 0; +} + +#ifdef TEST +int +main(int argc, char *argv[]) +{ + setenv(argv[1], argv[2], 0); + printf("%s\n", getenv(argv[1])); + unsetenv(argv[1]); + printf("%s\n", getenv(argv[1])); + return 0; +} +#endif + +#endif + + +#if defined(__hpux__) || defined(__hpux) +/* strrcpy(): + * Like strcpy, going backwards and returning the new pointer + */ +static char * +strrcpy(char *ptr, char *str) +{ + int len = strlen(str); + + while (len) + *--ptr = str[--len]; + + return ptr; +} /* end strrcpy */ + + +char *sys_siglist[] = { + "Signal 0", + "Hangup", /* SIGHUP */ + "Interrupt", /* SIGINT */ + "Quit", /* SIGQUIT */ + "Illegal instruction", /* SIGILL */ + "Trace/BPT trap", /* SIGTRAP */ + "IOT trap", /* SIGIOT */ + "EMT trap", /* SIGEMT */ + "Floating point exception", /* SIGFPE */ + "Killed", /* SIGKILL */ + "Bus error", /* SIGBUS */ + "Segmentation fault", /* SIGSEGV */ + "Bad system call", /* SIGSYS */ + "Broken pipe", /* SIGPIPE */ + "Alarm clock", /* SIGALRM */ + "Terminated", /* SIGTERM */ + "User defined signal 1", /* SIGUSR1 */ + "User defined signal 2", /* SIGUSR2 */ + "Child exited", /* SIGCLD */ + "Power-fail restart", /* SIGPWR */ + "Virtual timer expired", /* SIGVTALRM */ + "Profiling timer expired", /* SIGPROF */ + "I/O possible", /* SIGIO */ + "Window size changes", /* SIGWINDOW */ + "Stopped (signal)", /* SIGSTOP */ + "Stopped", /* SIGTSTP */ + "Continued", /* SIGCONT */ + "Stopped (tty input)", /* SIGTTIN */ + "Stopped (tty output)", /* SIGTTOU */ + "Urgent I/O condition", /* SIGURG */ + "Remote lock lost (NFS)", /* SIGLOST */ + "Signal 31", /* reserved */ + "DIL signal" /* SIGDIL */ +}; +#endif /* __hpux__ || __hpux */ + +#if defined(__hpux__) || defined(__hpux) +#include +#include +#include +#include +#include +#include +#include + +int +killpg(int pid, int sig) +{ + return kill(-pid, sig); +} + +#if !defined(BSD) && !defined(d_fileno) +# define d_fileno d_ino +#endif + +#ifndef DEV_DEV_COMPARE +# define DEV_DEV_COMPARE(a, b) ((a) == (b)) +#endif +#define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/'))) +#define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1]))) + +char * +getwd(char *pathname) +{ + DIR *dp; + struct dirent *d; + extern int errno; + + struct stat st_root, st_cur, st_next, st_dotdot; + char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2]; + char *pathptr, *nextpathptr, *cur_name_add; + + /* find the inode of root */ + if (stat("/", &st_root) == -1) { + (void)sprintf(pathname, + "getwd: Cannot stat \"/\" (%s)", strerror(errno)); + return NULL; + } + pathbuf[MAXPATHLEN - 1] = '\0'; + pathptr = &pathbuf[MAXPATHLEN - 1]; + nextpathbuf[MAXPATHLEN - 1] = '\0'; + cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1]; + + /* find the inode of the current directory */ + if (lstat(".", &st_cur) == -1) { + (void)sprintf(pathname, + "getwd: Cannot stat \".\" (%s)", strerror(errno)); + return NULL; + } + nextpathptr = strrcpy(nextpathptr, "../"); + + /* Descend to root */ + for (;;) { + + /* look if we found root yet */ + if (st_cur.st_ino == st_root.st_ino && + DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { + (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr); + return pathname; + } + + /* open the parent directory */ + if (stat(nextpathptr, &st_dotdot) == -1) { + (void)sprintf(pathname, + "getwd: Cannot stat directory \"%s\" (%s)", + nextpathptr, strerror(errno)); + return NULL; + } + if ((dp = opendir(nextpathptr)) == NULL) { + (void)sprintf(pathname, + "getwd: Cannot open directory \"%s\" (%s)", + nextpathptr, strerror(errno)); + return NULL; + } + + /* look in the parent for the entry with the same inode */ + if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) { + /* Parent has same device. No need to stat every member */ + for (d = readdir(dp); d != NULL; d = readdir(dp)) + if (d->d_fileno == st_cur.st_ino) + break; + } + else { + /* + * Parent has a different device. This is a mount point so we + * need to stat every member + */ + for (d = readdir(dp); d != NULL; d = readdir(dp)) { + if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) + continue; + (void)strcpy(cur_name_add, d->d_name); + if (lstat(nextpathptr, &st_next) == -1) { + (void)sprintf(pathname, + "getwd: Cannot stat \"%s\" (%s)", + d->d_name, strerror(errno)); + (void)closedir(dp); + return NULL; + } + /* check if we found it yet */ + if (st_next.st_ino == st_cur.st_ino && + DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) + break; + } + } + if (d == NULL) { + (void)sprintf(pathname, + "getwd: Cannot find \".\" in \"..\""); + (void)closedir(dp); + return NULL; + } + st_cur = st_dotdot; + pathptr = strrcpy(pathptr, d->d_name); + pathptr = strrcpy(pathptr, "/"); + nextpathptr = strrcpy(nextpathptr, "../"); + (void)closedir(dp); + *cur_name_add = '\0'; + } +} /* end getwd */ + +#endif /* __hpux */ + +#if !defined(HAVE_GETCWD) +char * +getcwd(path, sz) + char *path; + int sz; +{ + return getwd(path); +} +#endif + +/* force posix signals */ +SignalProc +bmake_signal(int s, SignalProc a) +{ + struct sigaction sa, osa; + + sa.sa_handler = a; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction(s, &sa, &osa) == -1) + return SIG_ERR; + else + return osa.sa_handler; +} + +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_VASPRINTF) +#include +#endif + +#if !defined(HAVE_VSNPRINTF) +#if !defined(__osf__) +#ifdef _IOSTRG +#define STRFLAG (_IOSTRG|_IOWRT) /* no _IOWRT: avoid stdio bug */ +#else +#if 0 +#define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ +#endif +#endif /* _IOSTRG */ +#endif /* __osf__ */ + +int +vsnprintf(char *s, size_t n, const char *fmt, va_list args) +{ +#ifdef STRFLAG + FILE fakebuf; + + fakebuf._flag = STRFLAG; + /* + * Some os's are char * _ptr, others are unsigned char *_ptr... + * We cast to void * to make everyone happy. + */ + fakebuf._ptr = (void *)s; + fakebuf._cnt = n-1; + fakebuf._file = -1; + _doprnt(fmt, args, &fakebuf); + fakebuf._cnt++; + putc('\0', &fakebuf); + if (fakebuf._cnt<0) + fakebuf._cnt = 0; + return n-fakebuf._cnt-1; +#else +#ifndef _PATH_DEVNULL +# define _PATH_DEVNULL "/dev/null" +#endif + /* + * Rats... we don't want to clobber anything... + * do a printf to /dev/null to see how much space we need. + */ + static FILE *nullfp; + int need = 0; /* XXX what's a useful error return? */ + + if (!nullfp) + nullfp = fopen(_PATH_DEVNULL, "w"); + if (nullfp) { + need = vfprintf(nullfp, fmt, args); + if (need < n) + (void)vsprintf(s, fmt, args); + } + return need; +#endif +} +#endif + +#if !defined(HAVE_SNPRINTF) +int +snprintf(char *s, size_t n, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = vsnprintf(s, n, fmt, ap); + va_end(ap); + return rv; +} +#endif + +#if !defined(HAVE_STRFTIME) +size_t +strftime(char *buf, size_t len, const char *fmt, const struct tm *tm) +{ + static char months[][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + size_t s; + char *b = buf; + + while (*fmt) { + if (len == 0) + return buf - b; + if (*fmt != '%') { + *buf++ = *fmt++; + len--; + continue; + } + switch (*fmt++) { + case '%': + *buf++ = '%'; + len--; + if (len == 0) return buf - b; + /*FALLTHROUGH*/ + case '\0': + *buf = '%'; + s = 1; + break; + case 'k': + s = snprintf(buf, len, "%d", tm->tm_hour); + break; + case 'M': + s = snprintf(buf, len, "%02d", tm->tm_min); + break; + case 'S': + s = snprintf(buf, len, "%02d", tm->tm_sec); + break; + case 'b': + if (tm->tm_mon >= 12) + return buf - b; + s = snprintf(buf, len, "%s", months[tm->tm_mon]); + break; + case 'd': + s = snprintf(buf, len, "%02d", tm->tm_mday); + break; + case 'Y': + s = snprintf(buf, len, "%d", 1900 + tm->tm_year); + break; + default: + s = snprintf(buf, len, "Unsupported format %c", + fmt[-1]); + break; + } + buf += s; + len -= s; + } + return buf - b; +} +#endif + +#if !defined(HAVE_KILLPG) +#if !defined(__hpux__) && !defined(__hpux) +int +killpg(int pid, int sig) +{ + return kill(-pid, sig); +} +#endif +#endif + +#if !defined(HAVE_WARNX) +static void +vwarnx(const char *fmt, va_list args) +{ + fprintf(stderr, "%s: ", progname); + if ((fmt)) { + vfprintf(stderr, fmt, args); + fprintf(stderr, ": "); + } +} +#endif + +#if !defined(HAVE_WARN) +static void +vwarn(const char *fmt, va_list args) +{ + vwarnx(fmt, args); + fprintf(stderr, "%s\n", strerror(errno)); +} +#endif + +#if !defined(HAVE_ERR) +static void +verr(int eval, const char *fmt, va_list args) +{ + vwarn(fmt, args); + exit(eval); +} +#endif + +#if !defined(HAVE_ERRX) +static void +verrx(int eval, const char *fmt, va_list args) +{ + vwarnx(fmt, args); + exit(eval); +} +#endif + +#if !defined(HAVE_ERR) +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verr(eval, fmt, ap); + va_end(ap); +} +#endif + +#if !defined(HAVE_ERRX) +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} +#endif + +#if !defined(HAVE_WARN) +void +warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} +#endif + +#if !defined(HAVE_WARNX) +void +warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} +#endif Property changes on: vendor/NetBSD/bmake/20201101/util.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/var.c =================================================================== --- vendor/NetBSD/bmake/20201101/var.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/var.c (revision 367461) @@ -0,0 +1,4086 @@ +/* $NetBSD: var.c,v 1.641 2020/11/01 23:17:40 rillig Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Copyright (c) 1989 by Berkeley Softworks + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam de Boor. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +/* + * Handling of variables and the expressions formed from them. + * + * Variables are set using lines of the form VAR=value. Both the variable + * name and the value can contain references to other variables, by using + * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}. + * + * Interface: + * Var_Init Initialize this module. + * + * Var_End Clean up the module. + * + * Var_Set Set the value of the variable, creating it if + * necessary. + * + * Var_Append Append more characters to the variable, creating it if + * necessary. A space is placed between the old value and + * the new one. + * + * Var_Exists See if a variable exists. + * + * Var_Value Return the unexpanded value of a variable, or NULL if + * the variable is undefined. + * + * Var_Subst Substitute all variable expressions in a string. + * + * Var_Parse Parse a variable expression such as ${VAR:Mpattern}. + * + * Var_Delete Delete a variable. + * + * Var_ExportVars Export some or even all variables to the environment + * of this process and its child processes. + * + * Var_Export Export the variable to the environment of this process + * and its child processes. + * + * Var_UnExport Don't export the variable anymore. + * + * Debugging: + * Var_Stats Print out hashing statistics if in -dh mode. + * + * Var_Dump Print out all variables defined in the given context. + * + * XXX: There's a lot of duplication in these functions. + */ + +#include +#include +#ifndef NO_REGEX +#include +#endif + +#include "make.h" + +#include +#ifdef HAVE_INTTYPES_H +#include +#elif defined(HAVE_STDINT_H) +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include + +#include "dir.h" +#include "job.h" +#include "metachar.h" + +/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ +MAKE_RCSID("$NetBSD: var.c,v 1.641 2020/11/01 23:17:40 rillig Exp $"); + +#define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) +#define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) +#define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) +#define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) + +ENUM_FLAGS_RTTI_3(VarEvalFlags, + VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); + +/* + * This lets us tell if we have replaced the original environ + * (which we cannot free). + */ +char **savedEnv = NULL; + +/* Special return value for Var_Parse, indicating a parse error. It may be + * caused by an undefined variable, a syntax error in a modifier or + * something entirely different. */ +char var_Error[] = ""; + +/* Special return value for Var_Parse, indicating an undefined variable in + * a case where VARE_UNDEFERR is not set. This undefined variable is + * typically a dynamic variable such as ${.TARGET}, whose expansion needs to + * be deferred until it is defined in an actual target. */ +static char varUndefined[] = ""; + +/* Special return value for Var_Parse, just to avoid allocating empty strings. + * In contrast to var_Error and varUndefined, this is not an error marker but + * just an ordinary successful return value. */ +static char emptyString[] = ""; + +/* + * Traditionally this make consumed $$ during := like any other expansion. + * Other make's do not, and this make follows straight since 2016-01-09. + * + * This knob allows controlling the behavior. + * FALSE to consume $$ during := assignment. + * TRUE to preserve $$ during := assignment. + */ +#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" +static Boolean save_dollars = FALSE; + +/* + * Internally, variables are contained in four different contexts. + * 1) the environment. They cannot be changed. If an environment + * variable is appended to, the result is placed in the global + * context. + * 2) the global context. Variables set in the makefiles are located + * here. + * 3) the command-line context. All variables set on the command line + * are placed in this context. + * 4) the local context. Each target has associated with it a context + * list. On this list are located the structures describing such + * local variables as $(@) and $(*) + * The four contexts are searched in the reverse order from which they are + * listed (but see opts.checkEnvFirst). + */ +GNode *VAR_INTERNAL; /* variables from make itself */ +GNode *VAR_GLOBAL; /* variables from the makefile */ +GNode *VAR_CMDLINE; /* variables defined on the command-line */ + +typedef enum VarFlags { + + /* The variable's value is currently being used by Var_Parse or Var_Subst. + * This marker is used to avoid endless recursion. */ + VAR_IN_USE = 0x01, + + /* The variable comes from the environment. + * These variables are not registered in any GNode, therefore they must + * be freed as soon as they are not used anymore. */ + VAR_FROM_ENV = 0x02, + + /* The variable is exported to the environment, to be used by child + * processes. */ + VAR_EXPORTED = 0x10, + + /* At the point where this variable was exported, it contained an + * unresolved reference to another variable. Before any child process is + * started, it needs to be exported again, in the hope that the referenced + * variable can then be resolved. */ + VAR_REEXPORT = 0x20, + + /* The variable came from the command line. */ + VAR_FROM_CMD = 0x40, + + /* The variable value cannot be changed anymore, and the variable cannot + * be deleted. Any attempts to do so are ignored. */ + VAR_READONLY = 0x80 +} VarFlags; + +ENUM_FLAGS_RTTI_6(VarFlags, + VAR_IN_USE, VAR_FROM_ENV, + VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY); + +/* Variables are defined using one of the VAR=value assignments. Their + * value can be queried by expressions such as $V, ${VAR}, or with modifiers + * such as ${VAR:S,from,to,g:Q}. + * + * There are 3 kinds of variables: context variables, environment variables, + * undefined variables. + * + * Context variables are stored in a GNode.context. The only way to undefine + * a context variable is using the .undef directive. In particular, it must + * not be possible to undefine a variable during the evaluation of an + * expression, or Var.name might point nowhere. + * + * Environment variables are temporary. They are returned by VarFind, and + * after using them, they must be freed using VarFreeEnv. + * + * Undefined variables occur during evaluation of variable expressions such + * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers. + */ +typedef struct Var { + /* The name of the variable, once set, doesn't change anymore. + * For context variables, it aliases the corresponding HashEntry name. + * For environment and undefined variables, it is allocated. */ + const char *name; + void *name_freeIt; + + Buffer val; /* its value */ + VarFlags flags; /* miscellaneous status flags */ +} Var; + +/* + * Exporting vars is expensive so skip it if we can + */ +typedef enum VarExportedMode { + VAR_EXPORTED_NONE, + VAR_EXPORTED_SOME, + VAR_EXPORTED_ALL +} VarExportedMode; + +static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE; + +typedef enum VarExportFlags { + /* + * We pass this to Var_Export when doing the initial export + * or after updating an exported var. + */ + VAR_EXPORT_PARENT = 0x01, + /* + * We pass this to Var_Export1 to tell it to leave the value alone. + */ + VAR_EXPORT_LITERAL = 0x02 +} VarExportFlags; + +/* Flags for pattern matching in the :S and :C modifiers */ +typedef enum VarPatternFlags { + VARP_SUB_GLOBAL = 0x01, /* Replace as often as possible ('g') */ + VARP_SUB_ONE = 0x02, /* Replace only once ('1') */ + VARP_ANCHOR_START = 0x04, /* Match at start of word ('^') */ + VARP_ANCHOR_END = 0x08 /* Match at end of word ('$') */ +} VarPatternFlags; + +static Var * +VarNew(const char *name, void *name_freeIt, const char *value, VarFlags flags) +{ + size_t value_len = strlen(value); + Var *var = bmake_malloc(sizeof *var); + var->name = name; + var->name_freeIt = name_freeIt; + Buf_Init(&var->val, value_len + 1); + Buf_AddBytes(&var->val, value, value_len); + var->flags = flags; + return var; +} + +static const char * +CanonicalVarname(const char *name) +{ + if (*name == '.' && ch_isupper(name[1])) { + switch (name[1]) { + case 'A': + if (strcmp(name, ".ALLSRC") == 0) + name = ALLSRC; + if (strcmp(name, ".ARCHIVE") == 0) + name = ARCHIVE; + break; + case 'I': + if (strcmp(name, ".IMPSRC") == 0) + name = IMPSRC; + break; + case 'M': + if (strcmp(name, ".MEMBER") == 0) + name = MEMBER; + break; + case 'O': + if (strcmp(name, ".OODATE") == 0) + name = OODATE; + break; + case 'P': + if (strcmp(name, ".PREFIX") == 0) + name = PREFIX; + break; + case 'S': + if (strcmp(name, ".SHELL") == 0) { + if (!shellPath) + Shell_Init(); + } + break; + case 'T': + if (strcmp(name, ".TARGET") == 0) + name = TARGET; + break; + } + } + + /* GNU make has an additional alias $^ == ${.ALLSRC}. */ + + return name; +} + +static Var * +GNode_FindVar(GNode *ctxt, const char *varname, unsigned int hash) +{ + return HashTable_FindValueHash(&ctxt->context, varname, hash); +} + +/* Find the variable in the context, and maybe in other contexts as well. + * + * Input: + * name name to find, is not expanded any further + * ctxt context in which to look first + * elsewhere TRUE to look in other contexts as well + * + * Results: + * The found variable, or NULL if the variable does not exist. + * If the variable is an environment variable, it must be freed using + * VarFreeEnv after use. + */ +static Var * +VarFind(const char *name, GNode *ctxt, Boolean elsewhere) +{ + Var *var; + unsigned int nameHash; + + /* + * If the variable name begins with a '.', it could very well be one of + * the local ones. We check the name against all the local variables + * and substitute the short version in for 'name' if it matches one of + * them. + */ + name = CanonicalVarname(name); + nameHash = Hash_Hash(name); + + /* First look for the variable in the given context. */ + var = GNode_FindVar(ctxt, name, nameHash); + if (!elsewhere) + return var; + + /* The variable was not found in the given context. Now look for it in + * the other contexts as well. */ + if (var == NULL && ctxt != VAR_CMDLINE) + var = GNode_FindVar(VAR_CMDLINE, name, nameHash); + + if (!opts.checkEnvFirst && var == NULL && ctxt != VAR_GLOBAL) { + var = GNode_FindVar(VAR_GLOBAL, name, nameHash); + if (var == NULL && ctxt != VAR_INTERNAL) { + /* VAR_INTERNAL is subordinate to VAR_GLOBAL */ + var = GNode_FindVar(VAR_INTERNAL, name, nameHash); + } + } + + if (var == NULL) { + char *env; + + if ((env = getenv(name)) != NULL) { + char *varname = bmake_strdup(name); + return VarNew(varname, varname, env, VAR_FROM_ENV); + } + + if (opts.checkEnvFirst && ctxt != VAR_GLOBAL) { + var = GNode_FindVar(VAR_GLOBAL, name, nameHash); + if (var == NULL && ctxt != VAR_INTERNAL) + var = GNode_FindVar(VAR_INTERNAL, name, nameHash); + return var; + } + + return NULL; + } + + return var; +} + +/* If the variable is an environment variable, free it. + * + * Input: + * v the variable + * freeValue true if the variable value should be freed as well + * + * Results: + * TRUE if it is an environment variable, FALSE otherwise. + */ +static Boolean +VarFreeEnv(Var *v, Boolean freeValue) +{ + if (!(v->flags & VAR_FROM_ENV)) + return FALSE; + + free(v->name_freeIt); + Buf_Destroy(&v->val, freeValue); + free(v); + return TRUE; +} + +/* Add a new variable of the given name and value to the given context. + * The name and val arguments are duplicated so they may safely be freed. */ +static void +VarAdd(const char *name, const char *val, GNode *ctxt, VarSet_Flags flags) +{ + HashEntry *he = HashTable_CreateEntry(&ctxt->context, name, NULL); + Var *v = VarNew(he->key /* aliased */, NULL, val, + flags & VAR_SET_READONLY ? VAR_READONLY : 0); + HashEntry_Set(he, v); + if (!(ctxt->flags & INTERNAL)) { + VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val); + } +} + +/* Remove a variable from a context, freeing all related memory as well. + * The variable name is expanded once. */ +void +Var_Delete(const char *name, GNode *ctxt) +{ + char *name_freeIt = NULL; + HashEntry *he; + + if (strchr(name, '$') != NULL) { + (void)Var_Subst(name, VAR_GLOBAL, VARE_WANTRES, &name_freeIt); + /* TODO: handle errors */ + name = name_freeIt; + } + he = HashTable_FindEntry(&ctxt->context, name); + VAR_DEBUG3("%s:delete %s%s\n", + ctxt->name, name, he != NULL ? "" : " (not found)"); + free(name_freeIt); + + if (he != NULL) { + Var *v = HashEntry_Get(he); + if (v->flags & VAR_EXPORTED) + unsetenv(v->name); + if (strcmp(v->name, MAKE_EXPORTED) == 0) + var_exportedVars = VAR_EXPORTED_NONE; + assert(v->name_freeIt == NULL); + HashTable_DeleteEntry(&ctxt->context, he); + Buf_Destroy(&v->val, TRUE); + free(v); + } +} + +static Boolean +MayExport(const char *name) +{ + if (name[0] == '.') + return FALSE; /* skip internals */ + if (name[0] == '-') + return FALSE; /* skip misnamed variables */ + if (name[1] == '\0') { + /* + * A single char. + * If it is one of the vars that should only appear in + * local context, skip it, else we can get Var_Subst + * into a loop. + */ + switch (name[0]) { + case '@': + case '%': + case '*': + case '!': + return FALSE; + } + } + return TRUE; +} + +/* + * Export a single variable. + * We ignore make internal variables (those which start with '.'). + * Also we jump through some hoops to avoid calling setenv + * more than necessary since it can leak. + * We only manipulate flags of vars if 'parent' is set. + */ +static Boolean +Var_Export1(const char *name, VarExportFlags flags) +{ + VarExportFlags parent = flags & VAR_EXPORT_PARENT; + Var *v; + char *val; + + if (!MayExport(name)) + return FALSE; + + v = VarFind(name, VAR_GLOBAL, 0); + if (v == NULL) + return FALSE; + + if (!parent && (v->flags & VAR_EXPORTED) && !(v->flags & VAR_REEXPORT)) + return FALSE; /* nothing to do */ + + val = Buf_GetAll(&v->val, NULL); + if (!(flags & VAR_EXPORT_LITERAL) && strchr(val, '$') != NULL) { + char *expr; + + if (parent) { + /* + * Flag the variable as something we need to re-export. + * No point actually exporting it now though, + * the child process can do it at the last minute. + */ + v->flags |= VAR_EXPORTED | VAR_REEXPORT; + return TRUE; + } + if (v->flags & VAR_IN_USE) { + /* + * We recursed while exporting in a child. + * This isn't going to end well, just skip it. + */ + return FALSE; + } + + /* XXX: name is injected without escaping it */ + expr = str_concat3("${", name, "}"); + (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &val); + /* TODO: handle errors */ + setenv(name, val, 1); + free(val); + free(expr); + } else { + if (parent) + v->flags &= ~(unsigned)VAR_REEXPORT; /* once will do */ + if (parent || !(v->flags & VAR_EXPORTED)) + setenv(name, val, 1); + } + + /* + * This is so Var_Set knows to call Var_Export again... + */ + if (parent) { + v->flags |= VAR_EXPORTED; + } + return TRUE; +} + +/* + * This gets called from our child processes. + */ +void +Var_ExportVars(void) +{ + char *val; + + /* + * Several make's support this sort of mechanism for tracking + * recursion - but each uses a different name. + * We allow the makefiles to update MAKELEVEL and ensure + * children see a correctly incremented value. + */ + char tmp[BUFSIZ]; + snprintf(tmp, sizeof(tmp), "%d", makelevel + 1); + setenv(MAKE_LEVEL_ENV, tmp, 1); + + if (var_exportedVars == VAR_EXPORTED_NONE) + return; + + if (var_exportedVars == VAR_EXPORTED_ALL) { + HashIter hi; + + /* Ouch! Exporting all variables at once is crazy... */ + HashIter_Init(&hi, &VAR_GLOBAL->context); + while (HashIter_Next(&hi) != NULL) { + Var *var = hi.entry->value; + Var_Export1(var->name, 0); + } + return; + } + + (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES, &val); + /* TODO: handle errors */ + if (*val) { + Words words = Str_Words(val, FALSE); + size_t i; + + for (i = 0; i < words.len; i++) + Var_Export1(words.words[i], 0); + Words_Free(words); + } + free(val); +} + +/* + * This is called when .export is seen or .MAKE.EXPORTED is modified. + * + * It is also called when any exported variable is modified. + * XXX: Is it really? + * + * str has the format "[-env|-literal] varname...". + */ +void +Var_Export(const char *str, Boolean isExport) +{ + VarExportFlags flags; + char *val; + + if (isExport && str[0] == '\0') { + var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */ + return; + } + + if (isExport && strncmp(str, "-env", 4) == 0) { + str += 4; + flags = 0; + } else if (isExport && strncmp(str, "-literal", 8) == 0) { + str += 8; + flags = VAR_EXPORT_LITERAL; + } else { + flags = VAR_EXPORT_PARENT; + } + + (void)Var_Subst(str, VAR_GLOBAL, VARE_WANTRES, &val); + /* TODO: handle errors */ + if (val[0] != '\0') { + Words words = Str_Words(val, FALSE); + + size_t i; + for (i = 0; i < words.len; i++) { + const char *name = words.words[i]; + if (Var_Export1(name, flags)) { + if (var_exportedVars == VAR_EXPORTED_NONE) + var_exportedVars = VAR_EXPORTED_SOME; + if (isExport && (flags & VAR_EXPORT_PARENT)) { + Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL); + } + } + } + Words_Free(words); + } + free(val); +} + + +extern char **environ; + +/* + * This is called when .unexport[-env] is seen. + * + * str must have the form "unexport[-env] varname...". + */ +void +Var_UnExport(const char *str) +{ + const char *varnames; + char *varnames_freeIt; + Boolean unexport_env; + + varnames = NULL; + varnames_freeIt = NULL; + + str += strlen("unexport"); + unexport_env = strncmp(str, "-env", 4) == 0; + if (unexport_env) { + const char *cp; + char **newenv; + + cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */ + if (environ == savedEnv) { + /* we have been here before! */ + newenv = bmake_realloc(environ, 2 * sizeof(char *)); + } else { + if (savedEnv) { + free(savedEnv); + savedEnv = NULL; + } + newenv = bmake_malloc(2 * sizeof(char *)); + } + + /* Note: we cannot safely free() the original environ. */ + environ = savedEnv = newenv; + newenv[0] = NULL; + newenv[1] = NULL; + if (cp && *cp) + setenv(MAKE_LEVEL_ENV, cp, 1); + } else { + cpp_skip_whitespace(&str); + if (str[0] != '\0') + varnames = str; + } + + if (varnames == NULL) { + /* Using .MAKE.EXPORTED */ + (void)Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES, + &varnames_freeIt); + /* TODO: handle errors */ + varnames = varnames_freeIt; + } + + { + Var *v; + size_t i; + + Words words = Str_Words(varnames, FALSE); + for (i = 0; i < words.len; i++) { + const char *varname = words.words[i]; + v = VarFind(varname, VAR_GLOBAL, 0); + if (v == NULL) { + VAR_DEBUG1("Not unexporting \"%s\" (not found)\n", varname); + continue; + } + + VAR_DEBUG1("Unexporting \"%s\"\n", varname); + if (!unexport_env && (v->flags & VAR_EXPORTED) && + !(v->flags & VAR_REEXPORT)) + unsetenv(v->name); + v->flags &= ~(unsigned)(VAR_EXPORTED | VAR_REEXPORT); + + /* + * If we are unexporting a list, + * remove each one from .MAKE.EXPORTED. + * If we are removing them all, + * just delete .MAKE.EXPORTED below. + */ + if (varnames == str) { + /* XXX: v->name is injected without escaping it */ + char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}"); + char *cp; + (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &cp); + /* TODO: handle errors */ + Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL); + free(cp); + free(expr); + } + } + Words_Free(words); + if (varnames != str) { + Var_Delete(MAKE_EXPORTED, VAR_GLOBAL); + free(varnames_freeIt); + } + } +} + +/* See Var_Set for documentation. */ +void +Var_Set_with_flags(const char *name, const char *val, GNode *ctxt, + VarSet_Flags flags) +{ + const char *unexpanded_name = name; + char *name_freeIt = NULL; + Var *v; + + assert(val != NULL); + + if (strchr(name, '$') != NULL) { + (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt); + /* TODO: handle errors */ + name = name_freeIt; + } + + if (name[0] == '\0') { + VAR_DEBUG2("Var_Set(\"%s\", \"%s\", ...) " + "name expands to empty string - ignored\n", + unexpanded_name, val); + free(name_freeIt); + return; + } + + if (ctxt == VAR_GLOBAL) { + v = VarFind(name, VAR_CMDLINE, 0); + if (v != NULL) { + if (v->flags & VAR_FROM_CMD) { + VAR_DEBUG3("%s:%s = %s ignored!\n", ctxt->name, name, val); + goto out; + } + VarFreeEnv(v, TRUE); + } + } + + /* + * We only look for a variable in the given context since anything set + * here will override anything in a lower context, so there's not much + * point in searching them all just to save a bit of memory... + */ + v = VarFind(name, ctxt, 0); + if (v == NULL) { + if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT)) { + /* + * This var would normally prevent the same name being added + * to VAR_GLOBAL, so delete it from there if needed. + * Otherwise -V name may show the wrong value. + */ + /* XXX: name is expanded for the second time */ + Var_Delete(name, VAR_GLOBAL); + } + VarAdd(name, val, ctxt, flags); + } else { + if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) { + VAR_DEBUG3("%s:%s = %s ignored (read-only)\n", + ctxt->name, name, val); + goto out; + } + Buf_Empty(&v->val); + Buf_AddStr(&v->val, val); + + VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val); + if (v->flags & VAR_EXPORTED) { + Var_Export1(name, VAR_EXPORT_PARENT); + } + } + /* + * Any variables given on the command line are automatically exported + * to the environment (as per POSIX standard) + * Other than internals. + */ + if (ctxt == VAR_CMDLINE && !(flags & VAR_NO_EXPORT) && name[0] != '.') { + if (v == NULL) + v = VarFind(name, ctxt, 0); /* we just added it */ + v->flags |= VAR_FROM_CMD; + + /* + * If requested, don't export these in the environment + * individually. We still put them in MAKEOVERRIDES so + * that the command-line settings continue to override + * Makefile settings. + */ + if (!opts.varNoExportEnv) + setenv(name, val, 1); + + Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL); + } + if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0) + save_dollars = s2Boolean(val, save_dollars); + +out: + free(name_freeIt); + if (v != NULL) + VarFreeEnv(v, TRUE); +} + +/*- + *----------------------------------------------------------------------- + * Var_Set -- + * Set the variable name to the value val in the given context. + * + * If the variable doesn't yet exist, it is created. + * Otherwise the new value overwrites and replaces the old value. + * + * Input: + * name name of the variable to set, is expanded once + * val value to give to the variable + * ctxt context in which to set it + * + * Notes: + * The variable is searched for only in its context before being + * created in that context. I.e. if the context is VAR_GLOBAL, + * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMDLINE, + * only VAR_CMDLINE->context is searched. This is done to avoid the + * literally thousands of unnecessary strcmp's that used to be done to + * set, say, $(@) or $(<). + * If the context is VAR_GLOBAL though, we check if the variable + * was set in VAR_CMDLINE from the command line and skip it if so. + *----------------------------------------------------------------------- + */ +void +Var_Set(const char *name, const char *val, GNode *ctxt) +{ + Var_Set_with_flags(name, val, ctxt, 0); +} + +/*- + *----------------------------------------------------------------------- + * Var_Append -- + * The variable of the given name has the given value appended to it in + * the given context. + * + * If the variable doesn't exist, it is created. Otherwise the strings + * are concatenated, with a space in between. + * + * Input: + * name name of the variable to modify, is expanded once + * val string to append to it + * ctxt context in which this should occur + * + * Notes: + * Only if the variable is being sought in the global context is the + * environment searched. + * XXX: Knows its calling circumstances in that if called with ctxt + * an actual target, it will only search that context since only + * a local variable could be being appended to. This is actually + * a big win and must be tolerated. + *----------------------------------------------------------------------- + */ +void +Var_Append(const char *name, const char *val, GNode *ctxt) +{ + char *name_freeIt = NULL; + Var *v; + + assert(val != NULL); + + if (strchr(name, '$') != NULL) { + const char *unexpanded_name = name; + (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt); + /* TODO: handle errors */ + name = name_freeIt; + if (name[0] == '\0') { + VAR_DEBUG2("Var_Append(\"%s\", \"%s\", ...) " + "name expands to empty string - ignored\n", + unexpanded_name, val); + free(name_freeIt); + return; + } + } + + v = VarFind(name, ctxt, ctxt == VAR_GLOBAL); + + if (v == NULL) { + /* XXX: name is expanded for the second time */ + Var_Set(name, val, ctxt); + } else if (v->flags & VAR_READONLY) { + VAR_DEBUG1("Ignoring append to %s since it is read-only\n", name); + } else if (ctxt == VAR_CMDLINE || !(v->flags & VAR_FROM_CMD)) { + Buf_AddByte(&v->val, ' '); + Buf_AddStr(&v->val, val); + + VAR_DEBUG3("%s:%s = %s\n", + ctxt->name, name, Buf_GetAll(&v->val, NULL)); + + if (v->flags & VAR_FROM_ENV) { + HashEntry *h; + + /* + * If the original variable came from the environment, we + * have to install it in the global context (we could place + * it in the environment, but then we should provide a way to + * export other variables...) + */ + v->flags &= ~(unsigned)VAR_FROM_ENV; + h = HashTable_CreateEntry(&ctxt->context, name, NULL); + HashEntry_Set(h, v); + } + } + free(name_freeIt); +} + +/* See if the given variable exists, in the given context or in other + * fallback contexts. + * + * Input: + * name Variable to find, is expanded once + * ctxt Context in which to start search + */ +Boolean +Var_Exists(const char *name, GNode *ctxt) +{ + char *name_freeIt = NULL; + Var *v; + + if (strchr(name, '$') != NULL) { + (void)Var_Subst(name, ctxt, VARE_WANTRES, &name_freeIt); + /* TODO: handle errors */ + name = name_freeIt; + } + + v = VarFind(name, ctxt, TRUE); + free(name_freeIt); + if (v == NULL) + return FALSE; + + (void)VarFreeEnv(v, TRUE); + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * Var_Value -- + * Return the unexpanded value of the given variable in the given + * context, or the usual contexts. + * + * Input: + * name name to find, is not expanded any further + * ctxt context in which to search for it + * + * Results: + * The value if the variable exists, NULL if it doesn't. + * If the returned value is not NULL, the caller must free + * out_freeIt when the returned value is no longer needed. + *----------------------------------------------------------------------- + */ +const char * +Var_Value(const char *name, GNode *ctxt, void **out_freeIt) +{ + Var *v = VarFind(name, ctxt, TRUE); + char *value; + + *out_freeIt = NULL; + if (v == NULL) + return NULL; + + value = Buf_GetAll(&v->val, NULL); + if (VarFreeEnv(v, FALSE)) + *out_freeIt = value; + return value; +} + +/* Return the unexpanded variable value from this node, without trying to look + * up the variable in any other context. */ +const char * +Var_ValueDirect(const char *name, GNode *ctxt) +{ + Var *v = VarFind(name, ctxt, FALSE); + return v != NULL ? Buf_GetAll(&v->val, NULL) : NULL; +} + + +/* SepBuf is a string being built from words, interleaved with separators. */ +typedef struct SepBuf { + Buffer buf; + Boolean needSep; + char sep; /* usually ' ', but see the :ts modifier */ +} SepBuf; + +static void +SepBuf_Init(SepBuf *buf, char sep) +{ + Buf_Init(&buf->buf, 32 /* bytes */); + buf->needSep = FALSE; + buf->sep = sep; +} + +static void +SepBuf_Sep(SepBuf *buf) +{ + buf->needSep = TRUE; +} + +static void +SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size) +{ + if (mem_size == 0) + return; + if (buf->needSep && buf->sep != '\0') { + Buf_AddByte(&buf->buf, buf->sep); + buf->needSep = FALSE; + } + Buf_AddBytes(&buf->buf, mem, mem_size); +} + +static void +SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end) +{ + SepBuf_AddBytes(buf, start, (size_t)(end - start)); +} + +static void +SepBuf_AddStr(SepBuf *buf, const char *str) +{ + SepBuf_AddBytes(buf, str, strlen(str)); +} + +static char * +SepBuf_Destroy(SepBuf *buf, Boolean free_buf) +{ + return Buf_Destroy(&buf->buf, free_buf); +} + + +/* This callback for ModifyWords gets a single word from a variable expression + * and typically adds a modification of this word to the buffer. It may also + * do nothing or add several words. + * + * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for + * each word of "a b c". */ +typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data); + + +/* Callback for ModifyWords to implement the :H modifier. + * Add the dirname of the given word to the buffer. */ +static void +ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) +{ + const char *slash = strrchr(word, '/'); + if (slash != NULL) + SepBuf_AddBytesBetween(buf, word, slash); + else + SepBuf_AddStr(buf, "."); +} + +/* Callback for ModifyWords to implement the :T modifier. + * Add the basename of the given word to the buffer. */ +static void +ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) +{ + const char *slash = strrchr(word, '/'); + const char *base = slash != NULL ? slash + 1 : word; + SepBuf_AddStr(buf, base); +} + +/* Callback for ModifyWords to implement the :E modifier. + * Add the filename suffix of the given word to the buffer, if it exists. */ +static void +ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) +{ + const char *dot = strrchr(word, '.'); + if (dot != NULL) + SepBuf_AddStr(buf, dot + 1); +} + +/* Callback for ModifyWords to implement the :R modifier. + * Add the basename of the given word to the buffer. */ +static void +ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) +{ + const char *dot = strrchr(word, '.'); + size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word); + SepBuf_AddBytes(buf, word, len); +} + +/* Callback for ModifyWords to implement the :M modifier. + * Place the word in the buffer if it matches the given pattern. */ +static void +ModifyWord_Match(const char *word, SepBuf *buf, void *data) +{ + const char *pattern = data; + VAR_DEBUG2("VarMatch [%s] [%s]\n", word, pattern); + if (Str_Match(word, pattern)) + SepBuf_AddStr(buf, word); +} + +/* Callback for ModifyWords to implement the :N modifier. + * Place the word in the buffer if it doesn't match the given pattern. */ +static void +ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data) +{ + const char *pattern = data; + if (!Str_Match(word, pattern)) + SepBuf_AddStr(buf, word); +} + +#ifdef SYSVVARSUB +/* Check word against pattern for a match (% is a wildcard). + * + * Input: + * word Word to examine + * pattern Pattern to examine against + * + * Results: + * Returns the start of the match, or NULL. + * out_match_len returns the length of the match, if any. + * out_hasPercent returns whether the pattern contains a percent. + */ +static const char * +SysVMatch(const char *word, const char *pattern, + size_t *out_match_len, Boolean *out_hasPercent) +{ + const char *p = pattern; + const char *w = word; + const char *percent; + size_t w_len; + size_t p_len; + const char *w_tail; + + *out_hasPercent = FALSE; + percent = strchr(p, '%'); + if (percent != NULL) { /* ${VAR:...%...=...} */ + *out_hasPercent = TRUE; + if (*w == '\0') + return NULL; /* empty word does not match pattern */ + + /* check that the prefix matches */ + for (; p != percent && *w != '\0' && *w == *p; w++, p++) + continue; + if (p != percent) + return NULL; /* No match */ + + p++; /* Skip the percent */ + if (*p == '\0') { + /* No more pattern, return the rest of the string */ + *out_match_len = strlen(w); + return w; + } + } + + /* Test whether the tail matches */ + w_len = strlen(w); + p_len = strlen(p); + if (w_len < p_len) + return NULL; + + w_tail = w + w_len - p_len; + if (memcmp(p, w_tail, p_len) != 0) + return NULL; + + *out_match_len = (size_t)(w_tail - w); + return w; +} + +struct ModifyWord_SYSVSubstArgs { + GNode *ctx; + const char *lhs; + const char *rhs; +}; + +/* Callback for ModifyWords to implement the :%.from=%.to modifier. */ +static void +ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data) +{ + const struct ModifyWord_SYSVSubstArgs *args = data; + char *rhs_expanded; + const char *rhs; + const char *percent; + + size_t match_len; + Boolean lhsPercent; + const char *match = SysVMatch(word, args->lhs, &match_len, &lhsPercent); + if (match == NULL) { + SepBuf_AddStr(buf, word); + return; + } + + /* Append rhs to the buffer, substituting the first '%' with the + * match, but only if the lhs had a '%' as well. */ + + (void)Var_Subst(args->rhs, args->ctx, VARE_WANTRES, &rhs_expanded); + /* TODO: handle errors */ + + rhs = rhs_expanded; + percent = strchr(rhs, '%'); + + if (percent != NULL && lhsPercent) { + /* Copy the prefix of the replacement pattern */ + SepBuf_AddBytesBetween(buf, rhs, percent); + rhs = percent + 1; + } + if (percent != NULL || !lhsPercent) + SepBuf_AddBytes(buf, match, match_len); + + /* Append the suffix of the replacement pattern */ + SepBuf_AddStr(buf, rhs); + + free(rhs_expanded); +} +#endif + + +struct ModifyWord_SubstArgs { + const char *lhs; + size_t lhsLen; + const char *rhs; + size_t rhsLen; + VarPatternFlags pflags; + Boolean matched; +}; + +/* Callback for ModifyWords to implement the :S,from,to, modifier. + * Perform a string substitution on the given word. */ +static void +ModifyWord_Subst(const char *word, SepBuf *buf, void *data) +{ + size_t wordLen = strlen(word); + struct ModifyWord_SubstArgs *args = data; + const char *match; + + if ((args->pflags & VARP_SUB_ONE) && args->matched) + goto nosub; + + if (args->pflags & VARP_ANCHOR_START) { + if (wordLen < args->lhsLen || + memcmp(word, args->lhs, args->lhsLen) != 0) + goto nosub; + + if ((args->pflags & VARP_ANCHOR_END) && wordLen != args->lhsLen) + goto nosub; + + /* :S,^prefix,replacement, or :S,^whole$,replacement, */ + SepBuf_AddBytes(buf, args->rhs, args->rhsLen); + SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen); + args->matched = TRUE; + return; + } + + if (args->pflags & VARP_ANCHOR_END) { + const char *start; + + if (wordLen < args->lhsLen) + goto nosub; + + start = word + (wordLen - args->lhsLen); + if (memcmp(start, args->lhs, args->lhsLen) != 0) + goto nosub; + + /* :S,suffix$,replacement, */ + SepBuf_AddBytesBetween(buf, word, start); + SepBuf_AddBytes(buf, args->rhs, args->rhsLen); + args->matched = TRUE; + return; + } + + if (args->lhs[0] == '\0') + goto nosub; + + /* unanchored case, may match more than once */ + while ((match = strstr(word, args->lhs)) != NULL) { + SepBuf_AddBytesBetween(buf, word, match); + SepBuf_AddBytes(buf, args->rhs, args->rhsLen); + args->matched = TRUE; + wordLen -= (size_t)(match - word) + args->lhsLen; + word += (size_t)(match - word) + args->lhsLen; + if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL)) + break; + } +nosub: + SepBuf_AddBytes(buf, word, wordLen); +} + +#ifndef NO_REGEX +/* Print the error caused by a regcomp or regexec call. */ +static void +VarREError(int reerr, regex_t *pat, const char *str) +{ + size_t errlen = regerror(reerr, pat, 0, 0); + char *errbuf = bmake_malloc(errlen); + regerror(reerr, pat, errbuf, errlen); + Error("%s: %s", str, errbuf); + free(errbuf); +} + +struct ModifyWord_SubstRegexArgs { + regex_t re; + size_t nsub; + char *replace; + VarPatternFlags pflags; + Boolean matched; +}; + +/* Callback for ModifyWords to implement the :C/from/to/ modifier. + * Perform a regex substitution on the given word. */ +static void +ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data) +{ + struct ModifyWord_SubstRegexArgs *args = data; + int xrv; + const char *wp = word; + char *rp; + int flags = 0; + regmatch_t m[10]; + + if ((args->pflags & VARP_SUB_ONE) && args->matched) + goto nosub; + +tryagain: + xrv = regexec(&args->re, wp, args->nsub, m, flags); + + switch (xrv) { + case 0: + args->matched = TRUE; + SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so); + + for (rp = args->replace; *rp; rp++) { + if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) { + SepBuf_AddBytes(buf, rp + 1, 1); + rp++; + continue; + } + + if (*rp == '&') { + SepBuf_AddBytesBetween(buf, wp + m[0].rm_so, wp + m[0].rm_eo); + continue; + } + + if (*rp != '\\' || !ch_isdigit(rp[1])) { + SepBuf_AddBytes(buf, rp, 1); + continue; + } + + { /* \0 to \9 backreference */ + size_t n = (size_t)(rp[1] - '0'); + rp++; + + if (n >= args->nsub) { + Error("No subexpression \\%zu", n); + } else if (m[n].rm_so == -1) { + Error("No match for subexpression \\%zu", n); + } else { + SepBuf_AddBytesBetween(buf, wp + m[n].rm_so, + wp + m[n].rm_eo); + } + } + } + + wp += m[0].rm_eo; + if (args->pflags & VARP_SUB_GLOBAL) { + flags |= REG_NOTBOL; + if (m[0].rm_so == 0 && m[0].rm_eo == 0) { + SepBuf_AddBytes(buf, wp, 1); + wp++; + } + if (*wp) + goto tryagain; + } + if (*wp) { + SepBuf_AddStr(buf, wp); + } + break; + default: + VarREError(xrv, &args->re, "Unexpected regex error"); + /* FALLTHROUGH */ + case REG_NOMATCH: + nosub: + SepBuf_AddStr(buf, wp); + break; + } +} +#endif + + +struct ModifyWord_LoopArgs { + GNode *ctx; + char *tvar; /* name of temporary variable */ + char *str; /* string to expand */ + VarEvalFlags eflags; +}; + +/* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */ +static void +ModifyWord_Loop(const char *word, SepBuf *buf, void *data) +{ + const struct ModifyWord_LoopArgs *args; + char *s; + + if (word[0] == '\0') + return; + + args = data; + Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT); + (void)Var_Subst(args->str, args->ctx, args->eflags, &s); + /* TODO: handle errors */ + + VAR_DEBUG4("ModifyWord_Loop: " + "in \"%s\", replace \"%s\" with \"%s\" to \"%s\"\n", + word, args->tvar, args->str, s); + + if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n')) + buf->needSep = FALSE; + SepBuf_AddStr(buf, s); + free(s); +} + + +/* The :[first..last] modifier selects words from the expression. + * It can also reverse the words. */ +static char * +VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first, + int last) +{ + Words words; + int len, start, end, step; + int i; + + SepBuf buf; + SepBuf_Init(&buf, sep); + + if (oneBigWord) { + /* fake what Str_Words() would do if there were only one word */ + words.len = 1; + words.words = bmake_malloc((words.len + 1) * sizeof(char *)); + words.freeIt = bmake_strdup(str); + words.words[0] = words.freeIt; + words.words[1] = NULL; + } else { + words = Str_Words(str, FALSE); + } + + /* + * Now sanitize the given range. + * If first or last are negative, convert them to the positive equivalents + * (-1 gets converted to ac, -2 gets converted to (ac - 1), etc.). + */ + len = (int)words.len; + if (first < 0) + first += len + 1; + if (last < 0) + last += len + 1; + + /* + * We avoid scanning more of the list than we need to. + */ + if (first > last) { + start = (first > len ? len : first) - 1; + end = last < 1 ? 0 : last - 1; + step = -1; + } else { + start = first < 1 ? 0 : first - 1; + end = last > len ? len : last; + step = 1; + } + + for (i = start; (step < 0) == (i >= end); i += step) { + SepBuf_AddStr(&buf, words.words[i]); + SepBuf_Sep(&buf); + } + + Words_Free(words); + + return SepBuf_Destroy(&buf, FALSE); +} + + +/* Callback for ModifyWords to implement the :tA modifier. + * Replace each word with the result of realpath() if successful. */ +static void +ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) +{ + struct stat st; + char rbuf[MAXPATHLEN]; + + const char *rp = cached_realpath(word, rbuf); + if (rp != NULL && *rp == '/' && stat(rp, &st) == 0) + word = rp; + + SepBuf_AddStr(buf, word); +} + +/* Modify each of the words of the passed string using the given function. + * + * Input: + * str String whose words should be modified + * modifyWord Function that modifies a single word + * modifyWord_args Custom arguments for modifyWord + * + * Results: + * A string of all the words modified appropriately. + *----------------------------------------------------------------------- + */ +static char * +ModifyWords(const char *str, + ModifyWordsCallback modifyWord, void *modifyWord_args, + Boolean oneBigWord, char sep) +{ + SepBuf result; + Words words; + size_t i; + + if (oneBigWord) { + SepBuf_Init(&result, sep); + modifyWord(str, &result, modifyWord_args); + return SepBuf_Destroy(&result, FALSE); + } + + SepBuf_Init(&result, sep); + + words = Str_Words(str, FALSE); + + VAR_DEBUG2("ModifyWords: split \"%s\" into %zu words\n", str, words.len); + + for (i = 0; i < words.len; i++) { + modifyWord(words.words[i], &result, modifyWord_args); + if (Buf_Len(&result.buf) > 0) + SepBuf_Sep(&result); + } + + Words_Free(words); + + return SepBuf_Destroy(&result, FALSE); +} + + +static char * +Words_JoinFree(Words words) +{ + Buffer buf; + size_t i; + + Buf_Init(&buf, 0); + + for (i = 0; i < words.len; i++) { + if (i != 0) + Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */ + Buf_AddStr(&buf, words.words[i]); + } + + Words_Free(words); + + return Buf_Destroy(&buf, FALSE); +} + +/* Remove adjacent duplicate words. */ +static char * +VarUniq(const char *str) +{ + Words words = Str_Words(str, FALSE); + + if (words.len > 1) { + size_t i, j; + for (j = 0, i = 1; i < words.len; i++) + if (strcmp(words.words[i], words.words[j]) != 0 && (++j != i)) + words.words[j] = words.words[i]; + words.len = j + 1; + } + + return Words_JoinFree(words); +} + + +/* Quote shell meta-characters and space characters in the string. + * If quoteDollar is set, also quote and double any '$' characters. */ +static char * +VarQuote(const char *str, Boolean quoteDollar) +{ + Buffer buf; + Buf_Init(&buf, 0); + + for (; *str != '\0'; str++) { + if (*str == '\n') { + const char *newline = Shell_GetNewline(); + if (newline == NULL) + newline = "\\\n"; + Buf_AddStr(&buf, newline); + continue; + } + if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str)) + Buf_AddByte(&buf, '\\'); + Buf_AddByte(&buf, *str); + if (quoteDollar && *str == '$') + Buf_AddStr(&buf, "\\$"); + } + + return Buf_Destroy(&buf, FALSE); +} + +/* Compute the 32-bit hash of the given string, using the MurmurHash3 + * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */ +static char * +VarHash(const char *str) +{ + static const char hexdigits[16] = "0123456789abcdef"; + const unsigned char *ustr = (const unsigned char *)str; + + uint32_t h = 0x971e137bU; + uint32_t c1 = 0x95543787U; + uint32_t c2 = 0x2ad7eb25U; + size_t len2 = strlen(str); + + char *buf; + size_t i; + + size_t len; + for (len = len2; len; ) { + uint32_t k = 0; + switch (len) { + default: + k = ((uint32_t)ustr[3] << 24) | + ((uint32_t)ustr[2] << 16) | + ((uint32_t)ustr[1] << 8) | + (uint32_t)ustr[0]; + len -= 4; + ustr += 4; + break; + case 3: + k |= (uint32_t)ustr[2] << 16; + /* FALLTHROUGH */ + case 2: + k |= (uint32_t)ustr[1] << 8; + /* FALLTHROUGH */ + case 1: + k |= (uint32_t)ustr[0]; + len = 0; + } + c1 = c1 * 5 + 0x7b7d159cU; + c2 = c2 * 5 + 0x6bce6396U; + k *= c1; + k = (k << 11) ^ (k >> 21); + k *= c2; + h = (h << 13) ^ (h >> 19); + h = h * 5 + 0x52dce729U; + h ^= k; + } + h ^= (uint32_t)len2; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + buf = bmake_malloc(9); + for (i = 0; i < 8; i++) { + buf[i] = hexdigits[h & 0x0f]; + h >>= 4; + } + buf[8] = '\0'; + return buf; +} + +static char * +VarStrftime(const char *fmt, Boolean zulu, time_t tim) +{ + char buf[BUFSIZ]; + + if (!tim) + time(&tim); + if (!*fmt) + fmt = "%c"; + strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&tim) : localtime(&tim)); + + buf[sizeof(buf) - 1] = '\0'; + return bmake_strdup(buf); +} + +/* The ApplyModifier functions all work in the same way. They get the + * current parsing position (pp) and parse the modifier from there. The + * modifier typically lasts until the next ':', or a closing '}' or ')' + * (taken from st->endc), or the end of the string (parse error). + * + * The high-level behavior of these functions is: + * + * 1. parse the modifier + * 2. evaluate the modifier + * 3. housekeeping + * + * Parsing the modifier + * + * If parsing succeeds, the parsing position *pp is updated to point to the + * first character following the modifier, which typically is either ':' or + * st->endc. + * + * If parsing fails because of a missing delimiter (as in the :S, :C or :@ + * modifiers), return AMR_CLEANUP. + * + * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to + * try the SysV modifier ${VAR:from=to} as fallback. This should only be + * done as long as there have been no side effects from evaluating nested + * variables, to avoid evaluating them more than once. In this case, the + * parsing position must not be updated. (XXX: Why not? The original parsing + * position is well-known in ApplyModifiers.) + * + * If parsing fails and the SysV modifier ${VAR:from=to} should not be used + * as a fallback, either issue an error message using Error or Parse_Error + * and then return AMR_CLEANUP, or return AMR_BAD for the default error + * message. Both of these return values will stop processing the variable + * expression. (XXX: As of 2020-08-23, evaluation of the whole string + * continues nevertheless after skipping a few bytes, which essentially is + * undefined behavior. Not in the sense of C, but still it's impossible to + * predict what happens in the parser.) + * + * Evaluating the modifier + * + * After parsing, the modifier is evaluated. The side effects from evaluating + * nested variable expressions in the modifier text often already happen + * during parsing though. + * + * Evaluating the modifier usually takes the current value of the variable + * expression from st->val, or the variable name from st->v->name and stores + * the result in st->newVal. + * + * If evaluating fails (as of 2020-08-23), an error message is printed using + * Error. This function has no side-effects, it really just prints the error + * message. Processing the expression continues as if everything were ok. + * XXX: This should be fixed by adding proper error handling to Var_Subst, + * Var_Parse, ApplyModifiers and ModifyWords. + * + * Housekeeping + * + * Some modifiers such as :D and :U turn undefined expressions into defined + * expressions (see VEF_UNDEF, VEF_DEF). + * + * Some modifiers need to free some memory. + */ + +typedef enum VarExprFlags { + /* The variable expression is based on an undefined variable. */ + VEF_UNDEF = 0x01, + /* The variable expression started as an undefined expression, but one + * of the modifiers (such as :D or :U) has turned the expression from + * undefined to defined. */ + VEF_DEF = 0x02 +} VarExprFlags; + +ENUM_FLAGS_RTTI_2(VarExprFlags, + VEF_UNDEF, VEF_DEF); + + +typedef struct ApplyModifiersState { + const char startc; /* '\0' or '{' or '(' */ + const char endc; /* '\0' or '}' or ')' */ + Var * const v; + GNode * const ctxt; + const VarEvalFlags eflags; + + char *val; /* The old value of the expression, + * before applying the modifier, never NULL */ + char *newVal; /* The new value of the expression, + * after applying the modifier, never NULL */ + char sep; /* Word separator in expansions + * (see the :ts modifier) */ + Boolean oneBigWord; /* TRUE if some modifiers that otherwise split + * the variable value into words, like :S and + * :C, treat the variable value as a single big + * word, possibly containing spaces. */ + VarExprFlags exprFlags; +} ApplyModifiersState; + +static void +ApplyModifiersState_Define(ApplyModifiersState *st) +{ + if (st->exprFlags & VEF_UNDEF) + st->exprFlags |= VEF_DEF; +} + +typedef enum ApplyModifierResult { + AMR_OK, /* Continue parsing */ + AMR_UNKNOWN, /* Not a match, try other modifiers as well */ + AMR_BAD, /* Error out with "Bad modifier" message */ + AMR_CLEANUP /* Error out without error message */ +} ApplyModifierResult; + +/* Allow backslashes to escape the delimiter, $, and \, but don't touch other + * backslashes. */ +static Boolean +IsEscapedModifierPart(const char *p, char delim, + struct ModifyWord_SubstArgs *subst) +{ + if (p[0] != '\\') + return FALSE; + if (p[1] == delim || p[1] == '\\' || p[1] == '$') + return TRUE; + return p[1] == '&' && subst != NULL; +} + +/* + * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or + * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and + * including the next unescaped delimiter. The delimiter, as well as the + * backslash or the dollar, can be escaped with a backslash. + * + * Return the parsed (and possibly expanded) string, or NULL if no delimiter + * was found. On successful return, the parsing position pp points right + * after the delimiter. The delimiter is not included in the returned + * value though. + */ +static VarParseResult +ParseModifierPart( + const char **pp, /* The parsing position, updated upon return */ + char delim, /* Parsing stops at this delimiter */ + VarEvalFlags eflags, /* Flags for evaluating nested variables; + * if VARE_WANTRES is not set, the text is + * only parsed */ + ApplyModifiersState *st, + char **out_part, + size_t *out_length, /* Optionally stores the length of the returned + * string, just to save another strlen call. */ + VarPatternFlags *out_pflags,/* For the first part of the :S modifier, + * sets the VARP_ANCHOR_END flag if the last + * character of the pattern is a $. */ + struct ModifyWord_SubstArgs *subst + /* For the second part of the :S modifier, + * allow ampersands to be escaped and replace + * unescaped ampersands with subst->lhs. */ +) { + Buffer buf; + const char *p; + + Buf_Init(&buf, 0); + + /* + * Skim through until the matching delimiter is found; pick up variable + * expressions on the way. + */ + p = *pp; + while (*p != '\0' && *p != delim) { + const char *varstart; + + if (IsEscapedModifierPart(p, delim, subst)) { + Buf_AddByte(&buf, p[1]); + p += 2; + continue; + } + + if (*p != '$') { /* Unescaped, simple text */ + if (subst != NULL && *p == '&') + Buf_AddBytes(&buf, subst->lhs, subst->lhsLen); + else + Buf_AddByte(&buf, *p); + p++; + continue; + } + + if (p[1] == delim) { /* Unescaped $ at end of pattern */ + if (out_pflags != NULL) + *out_pflags |= VARP_ANCHOR_END; + else + Buf_AddByte(&buf, *p); + p++; + continue; + } + + if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ + const char *nested_p = p; + const char *nested_val; + void *nested_val_freeIt; + VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN; + + (void)Var_Parse(&nested_p, st->ctxt, nested_eflags, + &nested_val, &nested_val_freeIt); + /* TODO: handle errors */ + Buf_AddStr(&buf, nested_val); + free(nested_val_freeIt); + p += nested_p - p; + continue; + } + + /* XXX: This whole block is very similar to Var_Parse without + * VARE_WANTRES. There may be subtle edge cases though that are + * not yet covered in the unit tests and that are parsed differently, + * depending on whether they are evaluated or not. + * + * This subtle difference is not documented in the manual page, + * neither is the difference between parsing :D and :M documented. + * No code should ever depend on these details, but who knows. */ + + varstart = p; /* Nested variable, only parsed */ + if (p[1] == '(' || p[1] == '{') { + /* + * Find the end of this variable reference + * and suck it in without further ado. + * It will be interpreted later. + */ + char startc = p[1]; + int endc = startc == '(' ? ')' : '}'; + int depth = 1; + + for (p += 2; *p != '\0' && depth > 0; p++) { + if (p[-1] != '\\') { + if (*p == startc) + depth++; + if (*p == endc) + depth--; + } + } + Buf_AddBytesBetween(&buf, varstart, p); + } else { + Buf_AddByte(&buf, *varstart); + p++; + } + } + + if (*p != delim) { + *pp = p; + Error("Unfinished modifier for %s ('%c' missing)", st->v->name, delim); + *out_part = NULL; + return VPR_PARSE_MSG; + } + + *pp = ++p; + if (out_length != NULL) + *out_length = Buf_Len(&buf); + + *out_part = Buf_Destroy(&buf, FALSE); + VAR_DEBUG1("Modifier part: \"%s\"\n", *out_part); + return VPR_OK; +} + +/* Test whether mod starts with modname, followed by a delimiter. */ +static Boolean +ModMatch(const char *mod, const char *modname, char endc) +{ + size_t n = strlen(modname); + return strncmp(mod, modname, n) == 0 && + (mod[n] == endc || mod[n] == ':'); +} + +/* Test whether mod starts with modname, followed by a delimiter or '='. */ +static inline Boolean +ModMatchEq(const char *mod, const char *modname, char endc) +{ + size_t n = strlen(modname); + return strncmp(mod, modname, n) == 0 && + (mod[n] == endc || mod[n] == ':' || mod[n] == '='); +} + +static Boolean +TryParseIntBase0(const char **pp, int *out_num) +{ + char *end; + long n; + + errno = 0; + n = strtol(*pp, &end, 0); + if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE) + return FALSE; + if (n < INT_MIN || n > INT_MAX) + return FALSE; + + *pp = end; + *out_num = (int)n; + return TRUE; +} + +static Boolean +TryParseSize(const char **pp, size_t *out_num) +{ + char *end; + unsigned long n; + + if (!ch_isdigit(**pp)) + return FALSE; + + errno = 0; + n = strtoul(*pp, &end, 10); + if (n == ULONG_MAX && errno == ERANGE) + return FALSE; + if (n > SIZE_MAX) + return FALSE; + + *pp = end; + *out_num = (size_t)n; + return TRUE; +} + +static Boolean +TryParseChar(const char **pp, int base, char *out_ch) +{ + char *end; + unsigned long n; + + if (!ch_isalnum(**pp)) + return FALSE; + + errno = 0; + n = strtoul(*pp, &end, base); + if (n == ULONG_MAX && errno == ERANGE) + return FALSE; + if (n > UCHAR_MAX) + return FALSE; + + *pp = end; + *out_ch = (char)n; + return TRUE; +} + +/* :@var@...${var}...@ */ +static ApplyModifierResult +ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) +{ + struct ModifyWord_LoopArgs args; + char prev_sep; + VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES; + VarParseResult res; + + args.ctx = st->ctxt; + + (*pp)++; /* Skip the first '@' */ + res = ParseModifierPart(pp, '@', eflags, st, + &args.tvar, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + if (DEBUG(LINT) && strchr(args.tvar, '$') != NULL) { + Parse_Error(PARSE_FATAL, + "In the :@ modifier of \"%s\", the variable name \"%s\" " + "must not contain a dollar.", + st->v->name, args.tvar); + return AMR_CLEANUP; + } + + res = ParseModifierPart(pp, '@', eflags, st, + &args.str, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES); + prev_sep = st->sep; + st->sep = ' '; /* XXX: should be st->sep for consistency */ + st->newVal = ModifyWords(st->val, ModifyWord_Loop, &args, + st->oneBigWord, st->sep); + st->sep = prev_sep; + Var_Delete(args.tvar, st->ctxt); + free(args.tvar); + free(args.str); + return AMR_OK; +} + +/* :Ddefined or :Uundefined */ +static ApplyModifierResult +ApplyModifier_Defined(const char **pp, ApplyModifiersState *st) +{ + Buffer buf; + const char *p; + + VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES; + if (st->eflags & VARE_WANTRES) { + if ((**pp == 'D') == !(st->exprFlags & VEF_UNDEF)) + eflags |= VARE_WANTRES; + } + + Buf_Init(&buf, 0); + p = *pp + 1; + while (*p != st->endc && *p != ':' && *p != '\0') { + + /* Escaped delimiter or other special character */ + if (*p == '\\') { + char c = p[1]; + if (c == st->endc || c == ':' || c == '$' || c == '\\') { + Buf_AddByte(&buf, c); + p += 2; + continue; + } + } + + /* Nested variable expression */ + if (*p == '$') { + const char *nested_val; + void *nested_val_freeIt; + + (void)Var_Parse(&p, st->ctxt, eflags, + &nested_val, &nested_val_freeIt); + /* TODO: handle errors */ + Buf_AddStr(&buf, nested_val); + free(nested_val_freeIt); + continue; + } + + /* Ordinary text */ + Buf_AddByte(&buf, *p); + p++; + } + *pp = p; + + ApplyModifiersState_Define(st); + + if (eflags & VARE_WANTRES) { + st->newVal = Buf_Destroy(&buf, FALSE); + } else { + st->newVal = st->val; + Buf_Destroy(&buf, TRUE); + } + return AMR_OK; +} + +/* :L */ +static ApplyModifierResult +ApplyModifier_Literal(const char **pp, ApplyModifiersState *st) +{ + ApplyModifiersState_Define(st); + st->newVal = bmake_strdup(st->v->name); + (*pp)++; + return AMR_OK; +} + +static Boolean +TryParseTime(const char **pp, time_t *out_time) +{ + char *end; + unsigned long n; + + if (!ch_isdigit(**pp)) + return FALSE; + + errno = 0; + n = strtoul(*pp, &end, 10); + if (n == ULONG_MAX && errno == ERANGE) + return FALSE; + + *pp = end; + *out_time = (time_t)n; /* ignore possible truncation for now */ + return TRUE; +} + +/* :gmtime */ +static ApplyModifierResult +ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st) +{ + time_t utc; + + const char *mod = *pp; + if (!ModMatchEq(mod, "gmtime", st->endc)) + return AMR_UNKNOWN; + + if (mod[6] == '=') { + const char *arg = mod + 7; + if (!TryParseTime(&arg, &utc)) { + Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 7); + return AMR_CLEANUP; + } + *pp = arg; + } else { + utc = 0; + *pp = mod + 6; + } + st->newVal = VarStrftime(st->val, TRUE, utc); + return AMR_OK; +} + +/* :localtime */ +static ApplyModifierResult +ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st) +{ + time_t utc; + + const char *mod = *pp; + if (!ModMatchEq(mod, "localtime", st->endc)) + return AMR_UNKNOWN; + + if (mod[9] == '=') { + const char *arg = mod + 10; + if (!TryParseTime(&arg, &utc)) { + Parse_Error(PARSE_FATAL, "Invalid time value: %s\n", mod + 10); + return AMR_CLEANUP; + } + *pp = arg; + } else { + utc = 0; + *pp = mod + 9; + } + st->newVal = VarStrftime(st->val, FALSE, utc); + return AMR_OK; +} + +/* :hash */ +static ApplyModifierResult +ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) +{ + if (!ModMatch(*pp, "hash", st->endc)) + return AMR_UNKNOWN; + + st->newVal = VarHash(st->val); + *pp += 4; + return AMR_OK; +} + +/* :P */ +static ApplyModifierResult +ApplyModifier_Path(const char **pp, ApplyModifiersState *st) +{ + GNode *gn; + char *path; + + ApplyModifiersState_Define(st); + + gn = Targ_FindNode(st->v->name); + if (gn == NULL || gn->type & OP_NOPATH) { + path = NULL; + } else if (gn->path != NULL) { + path = bmake_strdup(gn->path); + } else { + SearchPath *searchPath = Suff_FindPath(gn); + path = Dir_FindFile(st->v->name, searchPath); + } + if (path == NULL) + path = bmake_strdup(st->v->name); + st->newVal = path; + + (*pp)++; + return AMR_OK; +} + +/* :!cmd! */ +static ApplyModifierResult +ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st) +{ + char *cmd; + const char *errfmt; + VarParseResult res; + + (*pp)++; + res = ParseModifierPart(pp, '!', st->eflags, st, + &cmd, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + errfmt = NULL; + if (st->eflags & VARE_WANTRES) + st->newVal = Cmd_Exec(cmd, &errfmt); + else + st->newVal = emptyString; + free(cmd); + + if (errfmt != NULL) + Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ + + ApplyModifiersState_Define(st); + return AMR_OK; +} + +/* The :range modifier generates an integer sequence as long as the words. + * The :range=7 modifier generates an integer sequence from 1 to 7. */ +static ApplyModifierResult +ApplyModifier_Range(const char **pp, ApplyModifiersState *st) +{ + size_t n; + Buffer buf; + size_t i; + + const char *mod = *pp; + if (!ModMatchEq(mod, "range", st->endc)) + return AMR_UNKNOWN; + + if (mod[5] == '=') { + const char *p = mod + 6; + if (!TryParseSize(&p, &n)) { + Parse_Error(PARSE_FATAL, "Invalid number: %s\n", mod + 6); + return AMR_CLEANUP; + } + *pp = p; + } else { + n = 0; + *pp = mod + 5; + } + + if (n == 0) { + Words words = Str_Words(st->val, FALSE); + n = words.len; + Words_Free(words); + } + + Buf_Init(&buf, 0); + + for (i = 0; i < n; i++) { + if (i != 0) + Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */ + Buf_AddInt(&buf, 1 + (int)i); + } + + st->newVal = Buf_Destroy(&buf, FALSE); + return AMR_OK; +} + +/* :Mpattern or :Npattern */ +static ApplyModifierResult +ApplyModifier_Match(const char **pp, ApplyModifiersState *st) +{ + const char *mod = *pp; + Boolean copy = FALSE; /* pattern should be, or has been, copied */ + Boolean needSubst = FALSE; + const char *endpat; + char *pattern; + ModifyWordsCallback callback; + + /* + * In the loop below, ignore ':' unless we are at (or back to) the + * original brace level. + * XXX This will likely not work right if $() and ${} are intermixed. + */ + int nest = 0; + const char *p; + for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) { + if (*p == '\\' && + (p[1] == ':' || p[1] == st->endc || p[1] == st->startc)) { + if (!needSubst) + copy = TRUE; + p++; + continue; + } + if (*p == '$') + needSubst = TRUE; + if (*p == '(' || *p == '{') + nest++; + if (*p == ')' || *p == '}') { + nest--; + if (nest < 0) + break; + } + } + *pp = p; + endpat = p; + + if (copy) { + char *dst; + const char *src; + + /* Compress the \:'s out of the pattern. */ + pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1); + dst = pattern; + src = mod + 1; + for (; src < endpat; src++, dst++) { + if (src[0] == '\\' && src + 1 < endpat && + /* XXX: st->startc is missing here; see above */ + (src[1] == ':' || src[1] == st->endc)) + src++; + *dst = *src; + } + *dst = '\0'; + endpat = dst; + } else { + pattern = bmake_strsedup(mod + 1, endpat); + } + + if (needSubst) { + /* pattern contains embedded '$', so use Var_Subst to expand it. */ + char *old_pattern = pattern; + (void)Var_Subst(pattern, st->ctxt, st->eflags, &pattern); + /* TODO: handle errors */ + free(old_pattern); + } + + VAR_DEBUG3("Pattern[%s] for [%s] is [%s]\n", st->v->name, st->val, pattern); + + callback = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; + st->newVal = ModifyWords(st->val, callback, pattern, + st->oneBigWord, st->sep); + free(pattern); + return AMR_OK; +} + +/* :S,from,to, */ +static ApplyModifierResult +ApplyModifier_Subst(const char **pp, ApplyModifiersState *st) +{ + struct ModifyWord_SubstArgs args; + char *lhs, *rhs; + Boolean oneBigWord; + VarParseResult res; + + char delim = (*pp)[1]; + if (delim == '\0') { + Error("Missing delimiter for :S modifier"); + (*pp)++; + return AMR_CLEANUP; + } + + *pp += 2; + + args.pflags = 0; + args.matched = FALSE; + + /* + * If pattern begins with '^', it is anchored to the + * start of the word -- skip over it and flag pattern. + */ + if (**pp == '^') { + args.pflags |= VARP_ANCHOR_START; + (*pp)++; + } + + res = ParseModifierPart(pp, delim, st->eflags, st, + &lhs, &args.lhsLen, &args.pflags, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + args.lhs = lhs; + + res = ParseModifierPart(pp, delim, st->eflags, st, + &rhs, &args.rhsLen, NULL, &args); + if (res != VPR_OK) + return AMR_CLEANUP; + args.rhs = rhs; + + oneBigWord = st->oneBigWord; + for (;; (*pp)++) { + switch (**pp) { + case 'g': + args.pflags |= VARP_SUB_GLOBAL; + continue; + case '1': + args.pflags |= VARP_SUB_ONE; + continue; + case 'W': + oneBigWord = TRUE; + continue; + } + break; + } + + st->newVal = ModifyWords(st->val, ModifyWord_Subst, &args, + oneBigWord, st->sep); + + free(lhs); + free(rhs); + return AMR_OK; +} + +#ifndef NO_REGEX + +/* :C,from,to, */ +static ApplyModifierResult +ApplyModifier_Regex(const char **pp, ApplyModifiersState *st) +{ + char *re; + struct ModifyWord_SubstRegexArgs args; + Boolean oneBigWord; + int error; + VarParseResult res; + + char delim = (*pp)[1]; + if (delim == '\0') { + Error("Missing delimiter for :C modifier"); + (*pp)++; + return AMR_CLEANUP; + } + + *pp += 2; + + res = ParseModifierPart(pp, delim, st->eflags, st, + &re, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + res = ParseModifierPart(pp, delim, st->eflags, st, + &args.replace, NULL, NULL, NULL); + if (args.replace == NULL) { + free(re); + return AMR_CLEANUP; + } + + args.pflags = 0; + args.matched = FALSE; + oneBigWord = st->oneBigWord; + for (;; (*pp)++) { + switch (**pp) { + case 'g': + args.pflags |= VARP_SUB_GLOBAL; + continue; + case '1': + args.pflags |= VARP_SUB_ONE; + continue; + case 'W': + oneBigWord = TRUE; + continue; + } + break; + } + + error = regcomp(&args.re, re, REG_EXTENDED); + free(re); + if (error) { + VarREError(error, &args.re, "Regex compilation error"); + free(args.replace); + return AMR_CLEANUP; + } + + args.nsub = args.re.re_nsub + 1; + if (args.nsub > 10) + args.nsub = 10; + st->newVal = ModifyWords(st->val, ModifyWord_SubstRegex, &args, + oneBigWord, st->sep); + regfree(&args.re); + free(args.replace); + return AMR_OK; +} +#endif + +/* :Q, :q */ +static ApplyModifierResult +ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) +{ + if ((*pp)[1] == st->endc || (*pp)[1] == ':') { + st->newVal = VarQuote(st->val, **pp == 'q'); + (*pp)++; + return AMR_OK; + } else + return AMR_UNKNOWN; +} + +static void +ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) +{ + SepBuf_AddStr(buf, word); +} + +/* :ts */ +static ApplyModifierResult +ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) +{ + const char *sep = *pp + 2; + + /* ":ts" or ":ts:" */ + if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) { + st->sep = sep[0]; + *pp = sep + 1; + goto ok; + } + + /* ":ts" or ":ts:" */ + if (sep[0] == st->endc || sep[0] == ':') { + st->sep = '\0'; /* no separator */ + *pp = sep; + goto ok; + } + + /* ":ts". */ + if (sep[0] != '\\') { + (*pp)++; /* just for backwards compatibility */ + return AMR_BAD; + } + + /* ":ts\n" */ + if (sep[1] == 'n') { + st->sep = '\n'; + *pp = sep + 2; + goto ok; + } + + /* ":ts\t" */ + if (sep[1] == 't') { + st->sep = '\t'; + *pp = sep + 2; + goto ok; + } + + /* ":ts\x40" or ":ts\100" */ + { + const char *p = sep + 1; + int base = 8; /* assume octal */ + + if (sep[1] == 'x') { + base = 16; + p++; + } else if (!ch_isdigit(sep[1])) { + (*pp)++; /* just for backwards compatibility */ + return AMR_BAD; /* ":ts". */ + } + + if (!TryParseChar(&p, base, &st->sep)) { + Parse_Error(PARSE_FATAL, "Invalid character number: %s\n", p); + return AMR_CLEANUP; + } + if (*p != ':' && *p != st->endc) { + (*pp)++; /* just for backwards compatibility */ + return AMR_BAD; + } + + *pp = p; + } + +ok: + st->newVal = ModifyWords(st->val, ModifyWord_Copy, NULL, + st->oneBigWord, st->sep); + return AMR_OK; +} + +/* :tA, :tu, :tl, :ts, etc. */ +static ApplyModifierResult +ApplyModifier_To(const char **pp, ApplyModifiersState *st) +{ + const char *mod = *pp; + assert(mod[0] == 't'); + + if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') { + *pp = mod + 1; + return AMR_BAD; /* Found ":t" or ":t:". */ + } + + if (mod[1] == 's') + return ApplyModifier_ToSep(pp, st); + + if (mod[2] != st->endc && mod[2] != ':') { + *pp = mod + 1; + return AMR_BAD; /* Found ":t". */ + } + + /* Check for two-character options: ":tu", ":tl" */ + if (mod[1] == 'A') { /* absolute path */ + st->newVal = ModifyWords(st->val, ModifyWord_Realpath, NULL, + st->oneBigWord, st->sep); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'u') { /* :tu */ + size_t i; + size_t len = strlen(st->val); + st->newVal = bmake_malloc(len + 1); + for (i = 0; i < len + 1; i++) + st->newVal[i] = ch_toupper(st->val[i]); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'l') { /* :tl */ + size_t i; + size_t len = strlen(st->val); + st->newVal = bmake_malloc(len + 1); + for (i = 0; i < len + 1; i++) + st->newVal[i] = ch_tolower(st->val[i]); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ + st->oneBigWord = mod[1] == 'W'; + st->newVal = st->val; + *pp = mod + 2; + return AMR_OK; + } + + /* Found ":t:" or ":t". */ + *pp = mod + 1; + return AMR_BAD; +} + +/* :[#], :[1], :[-1..1], etc. */ +static ApplyModifierResult +ApplyModifier_Words(const char **pp, ApplyModifiersState *st) +{ + char *estr; + int first, last; + VarParseResult res; + const char *p; + + (*pp)++; /* skip the '[' */ + res = ParseModifierPart(pp, ']', st->eflags, st, + &estr, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + /* now *pp points just after the closing ']' */ + if (**pp != ':' && **pp != st->endc) + goto bad_modifier; /* Found junk after ']' */ + + if (estr[0] == '\0') + goto bad_modifier; /* empty square brackets in ":[]". */ + + if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ + if (st->oneBigWord) { + st->newVal = bmake_strdup("1"); + } else { + Buffer buf; + + Words words = Str_Words(st->val, FALSE); + size_t ac = words.len; + Words_Free(words); + + Buf_Init(&buf, 4); /* 3 digits + '\0' is usually enough */ + Buf_AddInt(&buf, (int)ac); + st->newVal = Buf_Destroy(&buf, FALSE); + } + goto ok; + } + + if (estr[0] == '*' && estr[1] == '\0') { + /* Found ":[*]" */ + st->oneBigWord = TRUE; + st->newVal = st->val; + goto ok; + } + + if (estr[0] == '@' && estr[1] == '\0') { + /* Found ":[@]" */ + st->oneBigWord = FALSE; + st->newVal = st->val; + goto ok; + } + + /* + * We expect estr to contain a single integer for :[N], or two integers + * separated by ".." for :[start..end]. + */ + p = estr; + if (!TryParseIntBase0(&p, &first)) + goto bad_modifier; /* Found junk instead of a number */ + + if (p[0] == '\0') { /* Found only one integer in :[N] */ + last = first; + } else if (p[0] == '.' && p[1] == '.' && p[2] != '\0') { + /* Expecting another integer after ".." */ + p += 2; + if (!TryParseIntBase0(&p, &last) || *p != '\0') + goto bad_modifier; /* Found junk after ".." */ + } else + goto bad_modifier; /* Found junk instead of ".." */ + + /* + * Now first and last are properly filled in, but we still have to check + * for 0 as a special case. + */ + if (first == 0 && last == 0) { + /* ":[0]" or perhaps ":[0..0]" */ + st->oneBigWord = TRUE; + st->newVal = st->val; + goto ok; + } + + /* ":[0..N]" or ":[N..0]" */ + if (first == 0 || last == 0) + goto bad_modifier; + + /* Normal case: select the words described by first and last. */ + st->newVal = VarSelectWords(st->sep, st->oneBigWord, st->val, first, last); + +ok: + free(estr); + return AMR_OK; + +bad_modifier: + free(estr); + return AMR_BAD; +} + +static int +str_cmp_asc(const void *a, const void *b) +{ + return strcmp(*(const char * const *)a, *(const char * const *)b); +} + +static int +str_cmp_desc(const void *a, const void *b) +{ + return strcmp(*(const char * const *)b, *(const char * const *)a); +} + +/* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */ +static ApplyModifierResult +ApplyModifier_Order(const char **pp, ApplyModifiersState *st) +{ + const char *mod = (*pp)++; /* skip past the 'O' in any case */ + + Words words = Str_Words(st->val, FALSE); + + if (mod[1] == st->endc || mod[1] == ':') { + /* :O sorts ascending */ + qsort(words.words, words.len, sizeof(char *), str_cmp_asc); + + } else if ((mod[1] == 'r' || mod[1] == 'x') && + (mod[2] == st->endc || mod[2] == ':')) { + (*pp)++; + + if (mod[1] == 'r') { + /* :Or sorts descending */ + qsort(words.words, words.len, sizeof(char *), str_cmp_desc); + + } else { + /* :Ox shuffles + * + * We will use [ac..2] range for mod factors. This will produce + * random numbers in [(ac-1)..0] interval, and minimal + * reasonable value for mod factor is 2 (the mod 1 will produce + * 0 with probability 1). + */ + size_t i; + for (i = words.len - 1; i > 0; i--) { + size_t rndidx = (size_t)random() % (i + 1); + char *t = words.words[i]; + words.words[i] = words.words[rndidx]; + words.words[rndidx] = t; + } + } + } else { + Words_Free(words); + return AMR_BAD; + } + + st->newVal = Words_JoinFree(words); + return AMR_OK; +} + +/* :? then : else */ +static ApplyModifierResult +ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st) +{ + char *then_expr, *else_expr; + VarParseResult res; + + Boolean value = FALSE; + VarEvalFlags then_eflags = st->eflags & ~(unsigned)VARE_WANTRES; + VarEvalFlags else_eflags = st->eflags & ~(unsigned)VARE_WANTRES; + + int cond_rc = COND_PARSE; /* anything other than COND_INVALID */ + if (st->eflags & VARE_WANTRES) { + cond_rc = Cond_EvalCondition(st->v->name, &value); + if (cond_rc != COND_INVALID && value) + then_eflags |= VARE_WANTRES; + if (cond_rc != COND_INVALID && !value) + else_eflags |= VARE_WANTRES; + } + + (*pp)++; /* skip past the '?' */ + res = ParseModifierPart(pp, ':', then_eflags, st, + &then_expr, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + res = ParseModifierPart(pp, st->endc, else_eflags, st, + &else_expr, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + (*pp)--; + if (cond_rc == COND_INVALID) { + Error("Bad conditional expression `%s' in %s?%s:%s", + st->v->name, st->v->name, then_expr, else_expr); + return AMR_CLEANUP; + } + + if (value) { + st->newVal = then_expr; + free(else_expr); + } else { + st->newVal = else_expr; + free(then_expr); + } + ApplyModifiersState_Define(st); + return AMR_OK; +} + +/* + * The ::= modifiers actually assign a value to the variable. + * Their main purpose is in supporting modifiers of .for loop + * iterators and other obscure uses. They always expand to + * nothing. In a target rule that would otherwise expand to an + * empty line they can be preceded with @: to keep make happy. + * Eg. + * + * foo: .USE + * .for i in ${.TARGET} ${.TARGET:R}.gz + * @: ${t::=$i} + * @echo blah ${t:T} + * .endfor + * + * ::= Assigns as the new value of variable. + * ::?= Assigns as value of variable if + * it was not already set. + * ::+= Appends to variable. + * ::!= Assigns output of as the new value of + * variable. + */ +static ApplyModifierResult +ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) +{ + GNode *v_ctxt; + char delim; + char *val; + VarParseResult res; + + const char *mod = *pp; + const char *op = mod + 1; + + if (op[0] == '=') + goto ok; + if ((op[0] == '!' || op[0] == '+' || op[0] == '?') && op[1] == '=') + goto ok; + return AMR_UNKNOWN; /* "::" */ +ok: + + if (st->v->name[0] == '\0') { + *pp = mod + 1; + return AMR_BAD; + } + + v_ctxt = st->ctxt; /* context where v belongs */ + if (!(st->exprFlags & VEF_UNDEF) && st->ctxt != VAR_GLOBAL) { + Var *gv = VarFind(st->v->name, st->ctxt, 0); + if (gv == NULL) + v_ctxt = VAR_GLOBAL; + else + VarFreeEnv(gv, TRUE); + } + + switch (op[0]) { + case '+': + case '?': + case '!': + *pp = mod + 3; + break; + default: + *pp = mod + 2; + break; + } + + delim = st->startc == '(' ? ')' : '}'; + res = ParseModifierPart(pp, delim, st->eflags, st, &val, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + (*pp)--; + + if (st->eflags & VARE_WANTRES) { + switch (op[0]) { + case '+': + Var_Append(st->v->name, val, v_ctxt); + break; + case '!': { + const char *errfmt; + char *cmd_output = Cmd_Exec(val, &errfmt); + if (errfmt) + Error(errfmt, val); + else + Var_Set(st->v->name, cmd_output, v_ctxt); + free(cmd_output); + break; + } + case '?': + if (!(st->exprFlags & VEF_UNDEF)) + break; + /* FALLTHROUGH */ + default: + Var_Set(st->v->name, val, v_ctxt); + break; + } + } + free(val); + st->newVal = emptyString; + return AMR_OK; +} + +/* :_=... + * remember current value */ +static ApplyModifierResult +ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) +{ + const char *mod = *pp; + if (!ModMatchEq(mod, "_", st->endc)) + return AMR_UNKNOWN; + + if (mod[1] == '=') { + size_t n = strcspn(mod + 2, ":)}"); + char *name = bmake_strldup(mod + 2, n); + Var_Set(name, st->val, st->ctxt); + free(name); + *pp = mod + 2 + n; + } else { + Var_Set("_", st->val, st->ctxt); + *pp = mod + 1; + } + st->newVal = st->val; + return AMR_OK; +} + +/* Apply the given function to each word of the variable value, + * for a single-letter modifier such as :H, :T. */ +static ApplyModifierResult +ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, + ModifyWordsCallback modifyWord) +{ + char delim = (*pp)[1]; + if (delim != st->endc && delim != ':') + return AMR_UNKNOWN; + + st->newVal = ModifyWords(st->val, modifyWord, NULL, + st->oneBigWord, st->sep); + (*pp)++; + return AMR_OK; +} + +static ApplyModifierResult +ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) +{ + if ((*pp)[1] == st->endc || (*pp)[1] == ':') { + st->newVal = VarUniq(st->val); + (*pp)++; + return AMR_OK; + } else + return AMR_UNKNOWN; +} + +#ifdef SYSVVARSUB +/* :from=to */ +static ApplyModifierResult +ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) +{ + char *lhs, *rhs; + VarParseResult res; + + const char *mod = *pp; + Boolean eqFound = FALSE; + + /* + * First we make a pass through the string trying to verify it is a + * SysV-make-style translation. It must be: = + */ + int depth = 1; + const char *p = mod; + while (*p != '\0' && depth > 0) { + if (*p == '=') { /* XXX: should also test depth == 1 */ + eqFound = TRUE; + /* continue looking for st->endc */ + } else if (*p == st->endc) + depth--; + else if (*p == st->startc) + depth++; + if (depth > 0) + p++; + } + if (*p != st->endc || !eqFound) + return AMR_UNKNOWN; + + *pp = mod; + res = ParseModifierPart(pp, '=', st->eflags, st, + &lhs, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + /* The SysV modifier lasts until the end of the variable expression. */ + res = ParseModifierPart(pp, st->endc, st->eflags, st, + &rhs, NULL, NULL, NULL); + if (res != VPR_OK) + return AMR_CLEANUP; + + (*pp)--; + if (lhs[0] == '\0' && st->val[0] == '\0') { + st->newVal = st->val; /* special case */ + } else { + struct ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs}; + st->newVal = ModifyWords(st->val, ModifyWord_SYSVSubst, &args, + st->oneBigWord, st->sep); + } + free(lhs); + free(rhs); + return AMR_OK; +} +#endif + +#ifdef SUNSHCMD +/* :sh */ +static ApplyModifierResult +ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) +{ + const char *p = *pp; + if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) { + if (st->eflags & VARE_WANTRES) { + const char *errfmt; + st->newVal = Cmd_Exec(st->val, &errfmt); + if (errfmt) + Error(errfmt, st->val); + } else + st->newVal = emptyString; + *pp = p + 2; + return AMR_OK; + } else + return AMR_UNKNOWN; +} +#endif + +static void +LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc) +{ + char eflags_str[VarEvalFlags_ToStringSize]; + char vflags_str[VarFlags_ToStringSize]; + char exprflags_str[VarExprFlags_ToStringSize]; + Boolean is_single_char = mod[0] != '\0' && + (mod[1] == endc || mod[1] == ':'); + + /* At this point, only the first character of the modifier can + * be used since the end of the modifier is not yet known. */ + debug_printf("Applying ${%s:%c%s} to \"%s\" (%s, %s, %s)\n", + st->v->name, mod[0], is_single_char ? "" : "...", st->val, + Enum_FlagsToString(eflags_str, sizeof eflags_str, + st->eflags, VarEvalFlags_ToStringSpecs), + Enum_FlagsToString(vflags_str, sizeof vflags_str, + st->v->flags, VarFlags_ToStringSpecs), + Enum_FlagsToString(exprflags_str, sizeof exprflags_str, + st->exprFlags, + VarExprFlags_ToStringSpecs)); +} + +static void +LogAfterApply(ApplyModifiersState *st, const char *p, const char *mod) +{ + char eflags_str[VarEvalFlags_ToStringSize]; + char vflags_str[VarFlags_ToStringSize]; + char exprflags_str[VarExprFlags_ToStringSize]; + const char *quot = st->newVal == var_Error ? "" : "\""; + const char *newVal = st->newVal == var_Error ? "error" : st->newVal; + + debug_printf("Result of ${%s:%.*s} is %s%s%s (%s, %s, %s)\n", + st->v->name, (int)(p - mod), mod, quot, newVal, quot, + Enum_FlagsToString(eflags_str, sizeof eflags_str, + st->eflags, VarEvalFlags_ToStringSpecs), + Enum_FlagsToString(vflags_str, sizeof vflags_str, + st->v->flags, VarFlags_ToStringSpecs), + Enum_FlagsToString(exprflags_str, sizeof exprflags_str, + st->exprFlags, + VarExprFlags_ToStringSpecs)); +} + +static ApplyModifierResult +ApplyModifier(const char **pp, ApplyModifiersState *st) +{ + switch (**pp) { + case ':': + return ApplyModifier_Assign(pp, st); + case '@': + return ApplyModifier_Loop(pp, st); + case '_': + return ApplyModifier_Remember(pp, st); + case 'D': + case 'U': + return ApplyModifier_Defined(pp, st); + case 'L': + return ApplyModifier_Literal(pp, st); + case 'P': + return ApplyModifier_Path(pp, st); + case '!': + return ApplyModifier_ShellCommand(pp, st); + case '[': + return ApplyModifier_Words(pp, st); + case 'g': + return ApplyModifier_Gmtime(pp, st); + case 'h': + return ApplyModifier_Hash(pp, st); + case 'l': + return ApplyModifier_Localtime(pp, st); + case 't': + return ApplyModifier_To(pp, st); + case 'N': + case 'M': + return ApplyModifier_Match(pp, st); + case 'S': + return ApplyModifier_Subst(pp, st); + case '?': + return ApplyModifier_IfElse(pp, st); +#ifndef NO_REGEX + case 'C': + return ApplyModifier_Regex(pp, st); +#endif + case 'q': + case 'Q': + return ApplyModifier_Quote(pp, st); + case 'T': + return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail); + case 'H': + return ApplyModifier_WordFunc(pp, st, ModifyWord_Head); + case 'E': + return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix); + case 'R': + return ApplyModifier_WordFunc(pp, st, ModifyWord_Root); + case 'r': + return ApplyModifier_Range(pp, st); + case 'O': + return ApplyModifier_Order(pp, st); + case 'u': + return ApplyModifier_Unique(pp, st); +#ifdef SUNSHCMD + case 's': + return ApplyModifier_SunShell(pp, st); +#endif + default: + return AMR_UNKNOWN; + } +} + +static char *ApplyModifiers(const char **, char *, char, char, Var *, + VarExprFlags *, GNode *, VarEvalFlags, void **); + +typedef enum ApplyModifiersIndirectResult { + AMIR_CONTINUE, + AMIR_APPLY_MODS, + AMIR_OUT +} ApplyModifiersIndirectResult; + +/* While expanding a variable expression, expand and apply indirect + * modifiers. */ +static ApplyModifiersIndirectResult +ApplyModifiersIndirect( + ApplyModifiersState *const st, + const char **inout_p, + void **const out_freeIt +) { + const char *p = *inout_p; + const char *nested_p = p; + void *freeIt; + const char *rval; + char c; + + (void)Var_Parse(&nested_p, st->ctxt, st->eflags, &rval, &freeIt); + /* TODO: handle errors */ + + /* + * If we have not parsed up to st->endc or ':', we are not + * interested. This means the expression ${VAR:${M_1}${M_2}} + * is not accepted, but ${VAR:${M_1}:${M_2}} is. + */ + if (rval[0] != '\0' && + (c = *nested_p) != '\0' && c != ':' && c != st->endc) { + if (DEBUG(LINT)) + Parse_Error(PARSE_FATAL, + "Missing delimiter ':' after indirect modifier \"%.*s\"", + (int)(nested_p - p), p); + + free(freeIt); + /* XXX: apply_mods doesn't sound like "not interested". */ + /* XXX: Why is the indirect modifier parsed again by + * apply_mods? If any, p should be advanced to nested_p. */ + return AMIR_APPLY_MODS; + } + + VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n", + rval, (int)(size_t)(nested_p - p), p); + + p = nested_p; + + if (rval[0] != '\0') { + const char *rval_pp = rval; + st->val = ApplyModifiers(&rval_pp, st->val, '\0', '\0', st->v, + &st->exprFlags, st->ctxt, st->eflags, out_freeIt); + if (st->val == var_Error + || (st->val == varUndefined && !(st->eflags & VARE_UNDEFERR)) + || *rval_pp != '\0') { + free(freeIt); + *inout_p = p; + return AMIR_OUT; /* error already reported */ + } + } + free(freeIt); + + if (*p == ':') + p++; + else if (*p == '\0' && st->endc != '\0') { + Error("Unclosed variable specification after complex " + "modifier (expecting '%c') for %s", st->endc, st->v->name); + *inout_p = p; + return AMIR_OUT; + } + + *inout_p = p; + return AMIR_CONTINUE; +} + +/* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ +static char * +ApplyModifiers( + const char **pp, /* the parsing position, updated upon return */ + char *const val, /* the current value of the expression */ + char const startc, /* '(' or '{', or '\0' for indirect modifiers */ + char const endc, /* ')' or '}', or '\0' for indirect modifiers */ + Var * const v, + VarExprFlags *exprFlags, + GNode * const ctxt, /* for looking up and modifying variables */ + VarEvalFlags const eflags, + void ** const out_freeIt /* free this after using the return value */ +) { + ApplyModifiersState st = { + startc, endc, v, ctxt, eflags, + val, /* .val */ + var_Error, /* .newVal */ + ' ', /* .sep */ + FALSE, /* .oneBigWord */ + *exprFlags /* .exprFlags */ + }; + const char *p; + const char *mod; + ApplyModifierResult res; + + assert(startc == '(' || startc == '{' || startc == '\0'); + assert(endc == ')' || endc == '}' || endc == '\0'); + assert(val != NULL); + + p = *pp; + while (*p != '\0' && *p != endc) { + + if (*p == '$') { + ApplyModifiersIndirectResult amir; + amir = ApplyModifiersIndirect(&st, &p, out_freeIt); + if (amir == AMIR_CONTINUE) + continue; + if (amir == AMIR_OUT) + goto out; + } + st.newVal = var_Error; /* default value, in case of errors */ + mod = p; + + if (DEBUG(VAR)) + LogBeforeApply(&st, mod, endc); + + res = ApplyModifier(&p, &st); + +#ifdef SYSVVARSUB + if (res == AMR_UNKNOWN) { + assert(p == mod); + res = ApplyModifier_SysV(&p, &st); + } +#endif + + if (res == AMR_UNKNOWN) { + Error("Unknown modifier '%c'", *mod); + for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++) + continue; + st.newVal = var_Error; + } + if (res == AMR_CLEANUP) + goto cleanup; + if (res == AMR_BAD) + goto bad_modifier; + + if (DEBUG(VAR)) + LogAfterApply(&st, p, mod); + + if (st.newVal != st.val) { + if (*out_freeIt) { + free(st.val); + *out_freeIt = NULL; + } + st.val = st.newVal; + if (st.val != var_Error && st.val != varUndefined && + st.val != emptyString) { + *out_freeIt = st.val; + } + } + if (*p == '\0' && st.endc != '\0') { + Error("Unclosed variable specification (expecting '%c') " + "for \"%s\" (value \"%s\") modifier %c", + st.endc, st.v->name, st.val, *mod); + } else if (*p == ':') { + p++; + } else if (DEBUG(LINT) && *p != '\0' && *p != endc) { + Parse_Error(PARSE_FATAL, + "Missing delimiter ':' after modifier \"%.*s\"", + (int)(p - mod), mod); + } + } +out: + *pp = p; + assert(st.val != NULL); /* Use var_Error or varUndefined instead. */ + *exprFlags = st.exprFlags; + return st.val; + +bad_modifier: + Error("Bad modifier `:%.*s' for %s", + (int)strcspn(mod, ":)}"), mod, st.v->name); + +cleanup: + *pp = p; + free(*out_freeIt); + *out_freeIt = NULL; + *exprFlags = st.exprFlags; + return var_Error; +} + +/* Only four of the local variables are treated specially as they are the + * only four that will be set when dynamic sources are expanded. */ +static Boolean +VarnameIsDynamic(const char *name, size_t len) +{ + if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) { + switch (name[0]) { + case '@': + case '%': + case '*': + case '!': + return TRUE; + } + return FALSE; + } + + if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) { + return strcmp(name, ".TARGET") == 0 || + strcmp(name, ".ARCHIVE") == 0 || + strcmp(name, ".PREFIX") == 0 || + strcmp(name, ".MEMBER") == 0; + } + + return FALSE; +} + +static const char * +UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags) +{ + if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) { + /* + * If substituting a local variable in a non-local context, + * assume it's for dynamic source stuff. We have to handle + * this specially and return the longhand for the variable + * with the dollar sign escaped so it makes it back to the + * caller. Only four of the local variables are treated + * specially as they are the only four that will be set + * when dynamic sources are expanded. + */ + switch (varname) { + case '@': + return "$(.TARGET)"; + case '%': + return "$(.MEMBER)"; + case '*': + return "$(.PREFIX)"; + case '!': + return "$(.ARCHIVE)"; + } + } + return eflags & VARE_UNDEFERR ? var_Error : varUndefined; +} + +/* Parse a variable name, until the end character or a colon, whichever + * comes first. */ +static char * +ParseVarname(const char **pp, char startc, char endc, + GNode *ctxt, VarEvalFlags eflags, + size_t *out_varname_len) +{ + Buffer buf; + const char *p = *pp; + int depth = 1; + + Buf_Init(&buf, 0); + + while (*p != '\0') { + /* Track depth so we can spot parse errors. */ + if (*p == startc) + depth++; + if (*p == endc) { + if (--depth == 0) + break; + } + if (*p == ':' && depth == 1) + break; + + /* A variable inside a variable, expand. */ + if (*p == '$') { + void *freeIt; + const char *rval; + (void)Var_Parse(&p, ctxt, eflags, &rval, &freeIt); + /* TODO: handle errors */ + Buf_AddStr(&buf, rval); + free(freeIt); + } else { + Buf_AddByte(&buf, *p); + p++; + } + } + *pp = p; + *out_varname_len = Buf_Len(&buf); + return Buf_Destroy(&buf, FALSE); +} + +static Boolean +ValidShortVarname(char varname, const char *start) +{ + switch (varname) { + case '\0': + case ')': + case '}': + case ':': + case '$': + break; /* and continue below */ + default: + return TRUE; + } + + if (!DEBUG(LINT)) + return FALSE; + + if (varname == '$') + Parse_Error(PARSE_FATAL, + "To escape a dollar, use \\$, not $$, at \"%s\"", start); + else if (varname == '\0') + Parse_Error(PARSE_FATAL, "Dollar followed by nothing"); + else + Parse_Error(PARSE_FATAL, + "Invalid variable name '%c', at \"%s\"", varname, start); + + return FALSE; +} + +/* Parse a single-character variable name such as $V or $@. + * Return whether to continue parsing. */ +static Boolean +ParseVarnameShort( + char startc, + const char **pp, + GNode *ctxt, + VarEvalFlags eflags, + VarParseResult *out_FALSE_res, + const char **out_FALSE_val, + Var **out_TRUE_var +) { + char name[2]; + Var *v; + + /* + * If it's not bounded by braces of some sort, life is much simpler. + * We just need to check for the first character and return the + * value if it exists. + */ + + if (!ValidShortVarname(startc, *pp)) { + (*pp)++; + *out_FALSE_val = var_Error; + *out_FALSE_res = VPR_PARSE_MSG; + return FALSE; + } + + name[0] = startc; + name[1] = '\0'; + v = VarFind(name, ctxt, TRUE); + if (v == NULL) { + *pp += 2; + + *out_FALSE_val = UndefinedShortVarValue(startc, ctxt, eflags); + if (DEBUG(LINT) && *out_FALSE_val == var_Error) { + Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", name); + *out_FALSE_res = VPR_UNDEF_MSG; + return FALSE; + } + *out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF_SILENT : VPR_OK; + return FALSE; + } + + *out_TRUE_var = v; + return TRUE; +} + +/* Parse a long variable name enclosed in braces or parentheses such as $(VAR) + * or ${VAR}, up to the closing brace or parenthesis, or in the case of + * ${VAR:Modifiers}, up to the ':' that starts the modifiers. + * Return whether to continue parsing. */ +static Boolean +ParseVarnameLong( + const char **pp, + char startc, + GNode *ctxt, + VarEvalFlags eflags, + + VarParseResult *out_FALSE_res, + const char **out_FALSE_val, + void **out_FALSE_freePtr, + + char *out_TRUE_endc, + const char **out_TRUE_p, + Var **out_TRUE_v, + Boolean *out_TRUE_haveModifier, + const char **out_TRUE_extraModifiers, + Boolean *out_TRUE_dynamic, + VarExprFlags *out_TRUE_exprFlags +) { + size_t namelen; + char *varname; + Var *v; + Boolean haveModifier; + Boolean dynamic = FALSE; + + const char *const start = *pp; + char endc = startc == '(' ? ')' : '}'; + + const char *p = start + 2; + varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen); + + if (*p == ':') { + haveModifier = TRUE; + } else if (*p == endc) { + haveModifier = FALSE; + } else { + Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname); + *pp = p; + free(varname); + *out_FALSE_val = var_Error; + *out_FALSE_res = VPR_PARSE_MSG; + return FALSE; + } + + v = VarFind(varname, ctxt, TRUE); + + /* At this point, p points just after the variable name, + * either at ':' or at endc. */ + + /* + * Check also for bogus D and F forms of local variables since we're + * in a local context and the name is the right length. + */ + if (v == NULL && ctxt != VAR_CMDLINE && ctxt != VAR_GLOBAL && + namelen == 2 && (varname[1] == 'F' || varname[1] == 'D') && + strchr("@%?*!<>", varname[0]) != NULL) + { + /* + * Well, it's local -- go look for it. + */ + char name[] = { varname[0], '\0' }; + v = VarFind(name, ctxt, 0); + + if (v != NULL) { + if (varname[1] == 'D') { + *out_TRUE_extraModifiers = "H:"; + } else { /* F */ + *out_TRUE_extraModifiers = "T:"; + } + } + } + + if (v == NULL) { + /* Defer expansion of dynamic variables if they appear in non-local + * context since they are not defined there. */ + dynamic = VarnameIsDynamic(varname, namelen) && + (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL); + + if (!haveModifier) { + p++; /* skip endc */ + *pp = p; + if (dynamic) { + char *pstr = bmake_strsedup(start, p); + free(varname); + *out_FALSE_res = VPR_OK; + *out_FALSE_freePtr = pstr; + *out_FALSE_val = pstr; + return FALSE; + } + + if ((eflags & VARE_UNDEFERR) && (eflags & VARE_WANTRES) && + DEBUG(LINT)) + { + Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", + varname); + free(varname); + *out_FALSE_res = VPR_UNDEF_MSG; + *out_FALSE_val = var_Error; + return FALSE; + } + + if (eflags & VARE_UNDEFERR) { + free(varname); + *out_FALSE_res = VPR_UNDEF_SILENT; + *out_FALSE_val = var_Error; + return FALSE; + } + + free(varname); + *out_FALSE_res = VPR_OK; + *out_FALSE_val = varUndefined; + return FALSE; + } + + /* The variable expression is based on an undefined variable. + * Nevertheless it needs a Var, for modifiers that access the + * variable name, such as :L or :?. + * + * Most modifiers leave this expression in the "undefined" state + * (VEF_UNDEF), only a few modifiers like :D, :U, :L, :P turn this + * undefined expression into a defined expression (VEF_DEF). + * + * At the end, after applying all modifiers, if the expression + * is still undefined, Var_Parse will return an empty string + * instead of the actually computed value. */ + v = VarNew(varname, varname, "", 0); + *out_TRUE_exprFlags = VEF_UNDEF; + } else + free(varname); + + *out_TRUE_endc = endc; + *out_TRUE_p = p; + *out_TRUE_v = v; + *out_TRUE_haveModifier = haveModifier; + *out_TRUE_dynamic = dynamic; + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * Var_Parse -- + * Given the start of a variable expression (such as $v, $(VAR), + * ${VAR:Mpattern}), extract the variable name, possibly some + * modifiers and find its value by applying the modifiers to the + * original value. + * + * When parsing a condition in ParseEmptyArg, pp may also point to + * the "y" of "empty(VARNAME:Modifiers)", which is syntactically + * identical. + * + * Input: + * str The string to parse + * ctxt The context for the variable + * flags Select the exact details of parsing + * out_val_freeIt Must be freed by the caller after using out_val + * + * Results: + * Returns the value of the variable expression, never NULL. + * Returns var_Error if there was a parse error and VARE_UNDEFERR was + * set. + * Returns varUndefined if there was an undefined variable and + * VARE_UNDEFERR was not set. + * + * Parsing should continue at *pp. + * TODO: Document the value of *pp on parse errors. It might be advanced + * by 0, or +1, or the index of the parse error, or the guessed end of the + * variable expression. + * + * If var_Error is returned, a diagnostic may or may not have been + * printed. XXX: This is inconsistent. + * + * If varUndefined is returned, a diagnostic may or may not have been + * printed. XXX: This is inconsistent. + * + * After using the returned value, *out_val_freeIt must be freed, + * preferably using bmake_free since it is NULL in most cases. + * + * Side Effects: + * Any effects from the modifiers, such as :!cmd! or ::=value. + *----------------------------------------------------------------------- + */ +/* coverity[+alloc : arg-*4] */ +VarParseResult +Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, + const char **out_val, void **out_val_freeIt) +{ + const char *const start = *pp; + const char *p; + Boolean haveModifier; /* TRUE if have modifiers for the variable */ + char startc; /* Starting character if variable in parens + * or braces */ + char endc; /* Ending character if variable in parens + * or braces */ + Boolean dynamic; /* TRUE if the variable is local and we're + * expanding it in a non-local context. This + * is done to support dynamic sources. The + * result is just the expression, unaltered */ + const char *extramodifiers; + Var *v; + char *nstr; + char eflags_str[VarEvalFlags_ToStringSize]; + VarExprFlags exprFlags = 0; + + VAR_DEBUG2("Var_Parse: %s with %s\n", start, + Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags, + VarEvalFlags_ToStringSpecs)); + + *out_val_freeIt = NULL; + extramodifiers = NULL; /* extra modifiers to apply first */ + dynamic = FALSE; + + /* Appease GCC, which thinks that the variable might not be + * initialized. */ + endc = '\0'; + + startc = start[1]; + if (startc != '(' && startc != '{') { + VarParseResult res; + if (!ParseVarnameShort(startc, pp, ctxt, eflags, &res, out_val, &v)) + return res; + haveModifier = FALSE; + p = start + 1; + } else { + VarParseResult res; + if (!ParseVarnameLong(pp, startc, ctxt, eflags, + &res, out_val, out_val_freeIt, + &endc, &p, &v, &haveModifier, &extramodifiers, + &dynamic, &exprFlags)) + return res; + } + + if (v->flags & VAR_IN_USE) + Fatal("Variable %s is recursive.", v->name); + + /* + * Before doing any modification, we have to make sure the value + * has been fully expanded. If it looks like recursion might be + * necessary (there's a dollar sign somewhere in the variable's value) + * we just call Var_Subst to do any other substitutions that are + * necessary. Note that the value returned by Var_Subst will have + * been dynamically-allocated, so it will need freeing when we + * return. + */ + nstr = Buf_GetAll(&v->val, NULL); + if (strchr(nstr, '$') != NULL && (eflags & VARE_WANTRES)) { + VarEvalFlags nested_eflags = eflags; + if (DEBUG(LINT)) + nested_eflags &= ~(unsigned)VARE_UNDEFERR; + v->flags |= VAR_IN_USE; + (void)Var_Subst(nstr, ctxt, nested_eflags, &nstr); + v->flags &= ~(unsigned)VAR_IN_USE; + /* TODO: handle errors */ + *out_val_freeIt = nstr; + } + + if (haveModifier || extramodifiers != NULL) { + void *extraFree; + + extraFree = NULL; + if (extramodifiers != NULL) { + const char *em = extramodifiers; + nstr = ApplyModifiers(&em, nstr, '(', ')', + v, &exprFlags, ctxt, eflags, &extraFree); + } + + if (haveModifier) { + /* Skip initial colon. */ + p++; + + nstr = ApplyModifiers(&p, nstr, startc, endc, + v, &exprFlags, ctxt, eflags, out_val_freeIt); + free(extraFree); + } else { + *out_val_freeIt = extraFree; + } + } + + if (*p != '\0') /* Skip past endc if possible. */ + p++; + + *pp = p; + + if (v->flags & VAR_FROM_ENV) { + /* Free the environment variable now since we own it, + * but don't free the variable value if it will be returned. */ + Boolean keepValue = nstr == Buf_GetAll(&v->val, NULL); + if (keepValue) + *out_val_freeIt = nstr; + (void)VarFreeEnv(v, !keepValue); + + } else if (exprFlags & VEF_UNDEF) { + if (!(exprFlags & VEF_DEF)) { + if (*out_val_freeIt != NULL) { + free(*out_val_freeIt); + *out_val_freeIt = NULL; + } + if (dynamic) { + nstr = bmake_strsedup(start, p); + *out_val_freeIt = nstr; + } else { + /* The expression is still undefined, therefore discard the + * actual value and return an error marker instead. */ + nstr = (eflags & VARE_UNDEFERR) ? var_Error : varUndefined; + } + } + if (nstr != Buf_GetAll(&v->val, NULL)) + Buf_Destroy(&v->val, TRUE); + free(v->name_freeIt); + free(v); + } + *out_val = nstr; + return VPR_UNKNOWN; +} + +/* Substitute for all variables in the given string in the given context. + * + * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined + * variable is encountered. + * + * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=, + * :sh or !cmd! take place. + * + * Input: + * str the string which to substitute + * ctxt the context wherein to find variables + * eflags VARE_UNDEFERR if undefineds are an error + * VARE_WANTRES if we actually want the result + * VARE_ASSIGN if we are in a := assignment + * + * Results: + * The resulting string. + */ +VarParseResult +Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags, char **out_res) +{ + const char *p = str; + Buffer buf; /* Buffer for forming things */ + + /* Set true if an error has already been reported, + * to prevent a plethora of messages when recursing */ + static Boolean errorReported; + + Buf_Init(&buf, 0); + errorReported = FALSE; + + while (*p != '\0') { + if (p[0] == '$' && p[1] == '$') { + /* A dollar sign may be escaped with another dollar sign. */ + if (save_dollars && (eflags & VARE_ASSIGN)) + Buf_AddByte(&buf, '$'); + Buf_AddByte(&buf, '$'); + p += 2; + } else if (*p != '$') { + /* + * Skip as many characters as possible -- either to the end of + * the string or to the next dollar sign (variable expression). + */ + const char *plainStart = p; + + for (p++; *p != '$' && *p != '\0'; p++) + continue; + Buf_AddBytesBetween(&buf, plainStart, p); + } else { + const char *nested_p = p; + void *freeIt; + const char *val; + (void)Var_Parse(&nested_p, ctxt, eflags, &val, &freeIt); + /* TODO: handle errors */ + + if (val == var_Error || val == varUndefined) { + /* + * If performing old-time variable substitution, skip over + * the variable and continue with the substitution. Otherwise, + * store the dollar sign and advance str so we continue with + * the string... + */ + if (oldVars) { + p = nested_p; + } else if ((eflags & VARE_UNDEFERR) || val == var_Error) { + /* + * If variable is undefined, complain and skip the + * variable. The complaint will stop us from doing anything + * when the file is parsed. + */ + if (!errorReported) { + Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", + (int)(size_t)(nested_p - p), p); + } + p = nested_p; + errorReported = TRUE; + } else { + /* Copy the initial '$' of the undefined expression, + * thereby deferring expansion of the expression, but + * expand nested expressions if already possible. + * See unit-tests/varparse-undef-partial.mk. */ + Buf_AddByte(&buf, *p); + p++; + } + } else { + p = nested_p; + Buf_AddStr(&buf, val); + } + free(freeIt); + freeIt = NULL; + } + } + + *out_res = Buf_DestroyCompact(&buf); + return VPR_OK; +} + +/* Initialize the variables module. */ +void +Var_Init(void) +{ + VAR_INTERNAL = Targ_NewGN("Internal"); + VAR_GLOBAL = Targ_NewGN("Global"); + VAR_CMDLINE = Targ_NewGN("Command"); +} + +/* Clean up the variables module. */ +void +Var_End(void) +{ + Var_Stats(); +} + +void +Var_Stats(void) +{ + HashTable_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL"); +} + +/* Print all variables in a context, sorted by name. */ +void +Var_Dump(GNode *ctxt) +{ + Vector /* of const char * */ vec; + HashIter hi; + size_t i; + const char **varnames; + + Vector_Init(&vec, sizeof(const char *)); + + HashIter_Init(&hi, &ctxt->context); + while (HashIter_Next(&hi) != NULL) + *(const char **)Vector_Push(&vec) = hi.entry->key; + varnames = vec.items; + + qsort(varnames, vec.len, sizeof varnames[0], str_cmp_asc); + + for (i = 0; i < vec.len; i++) { + const char *varname = varnames[i]; + Var *var = HashTable_FindValue(&ctxt->context, varname); + debug_printf("%-16s = %s\n", varname, Buf_GetAll(&var->val, NULL)); + } + + Vector_Done(&vec); +} Property changes on: vendor/NetBSD/bmake/20201101/var.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/LICENSE =================================================================== --- vendor/NetBSD/bmake/20201101/LICENSE (nonexistent) +++ vendor/NetBSD/bmake/20201101/LICENSE (revision 367461) @@ -0,0 +1,60 @@ +The individual files in this distribution are copyright their +original contributors or assignees. +Including: + + Copyright (c) 1993-2020, Simon J Gerraty + Copyright (c) 2020, Roland Illig + Copyright (c) 2009-2016, Juniper Networks, Inc. + Copyright (c) 2009, John Birrell. + Copyright (c) 1997-2020 The NetBSD Foundation, Inc. + Copyright (c) 1998 Todd C. Miller + Copyright (c) 1989 by Berkeley Softworks + Copyright (c) 1988, 1989, 1990, 1992, 1993 + The Regents of the University of California. + Copyright (c) 1988, 1989 by Adam de Boor + +With the exception of the GNU configure script, which states: + + # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. + # + # This configure script is free software; the Free Software Foundation + # gives unlimited permission to copy, distribute and modify it. + +The license for this distribution is considered to be: + + SPDX-License-Identifier: BSD-3-Clause + +example (from https://opensource.org/licenses/BSD-3-Clause): + + Copyright + + 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. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + 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. + Index: vendor/NetBSD/bmake/20201101/bsd.after-import.mk =================================================================== --- vendor/NetBSD/bmake/20201101/bsd.after-import.mk (nonexistent) +++ vendor/NetBSD/bmake/20201101/bsd.after-import.mk (revision 367461) @@ -0,0 +1,126 @@ +# $Id: bsd.after-import.mk,v 1.16 2020/07/12 03:39:01 sjg Exp $ + +# This makefile is for use when integrating bmake into a BSD build +# system. Use this makefile after importing bmake. +# It will bootstrap the new version, +# capture the generated files we need, and add an after-import +# target to allow the process to be easily repeated. + +# The goal is to allow the benefits of autoconf without +# the overhead of running configure. + +all: _makefile _utmakefile +all: after-import + +# we rely on bmake +.if !defined(.PARSEDIR) +.error this makefile requires bmake +.endif + +_this := ${MAKEFILE:tA} +BMAKE_SRC := ${.PARSEDIR} + +# it helps to know where the top of the tree is. +.if !defined(SRCTOP) +srctop := ${.MAKE.MAKEFILES:M*src/share/mk/sys.mk:H:H:H} +.if empty(srctop) +# likely locations? +.for d in contrib/bmake external/bsd/bmake/dist +.if ${BMAKE_SRC:M*/$d} != "" +srctop := ${BMAKE_SRC:tA:S,/$d,,} +.endif +.endfor +.endif +.if !empty(srctop) +SRCTOP := ${srctop} +.endif +.endif + +# This lets us match what boot-strap does +.if defined(.MAKE.OS) +HOST_OS:= ${.MAKE.OS} +.elif !defined(HOST_OS) +HOST_OS!= uname +.endif + +BOOTSTRAP_ARGS = \ + --prefix /usr \ + --share /usr/share + +.if !empty(DEFAULT_SYS_PATH) +BOOTSTRAP_ARGS += --with-default-sys-path='${DEFAULT_SYS_PATH}' +.endif + +# run boot-strap with minimal influence +bootstrap: ${BMAKE_SRC}/boot-strap ${MAKEFILE} + HOME=/ ${BMAKE_SRC}/boot-strap -o ${HOST_OS} ${BOOTSTRAP_ARGS} ${BOOTSTRAP_XTRAS} + touch ${.TARGET} + +# Makefiles need a little more tweaking than say config.h +MAKEFILE_SED = sed -e '/^MACHINE/d' \ + -e '/include.*VERSION/d' \ + -e '/^PROG/ { s,=,?=,;s,bmake,$${.CURDIR:T},; }' \ + -e 's,^.-include,.sinclude,' \ + -e '/^\..*include * ${.CURDIR}/$f +.endfor +.for f in ${configured_files:M*Makefile*} + @echo Capturing $f + @mkdir -p ${${.CURDIR}/$f:L:H} + @(echo '# This is a generated file, do NOT edit!'; \ + echo '# See ${_this:S,${SRCTOP}/,,}'; \ + echo '#'; echo '# $$${HOST_OS}$$'; echo; \ + echo 'SRCTOP?= $${.CURDIR:${${.CURDIR}/$f:L:H:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; echo; \ + ${MAKEFILE_SED} ${HOST_OS}/$f ) > ${.CURDIR}/$f +.endfor + +# this needs the most work +_makefile: bootstrap ${MAKEFILE} + @echo Generating ${.CURDIR}/Makefile + @(echo '# This is a generated file, do NOT edit!'; \ + echo '# See ${_this:S,${SRCTOP}/,,}'; \ + echo '#'; echo '# $$${HOST_OS}$$'; \ + echo; echo 'SRCTOP?= $${.CURDIR:${.CURDIR:S,${SRCTOP}/,,:C,[^/]+,H,g:S,/,:,g}}'; \ + echo; echo '# look here first for config.h'; \ + echo 'CFLAGS+= -I$${.CURDIR}'; echo; \ + echo '# for after-import'; \ + echo 'CLEANDIRS+= ${HOST_OS}'; \ + echo 'CLEANFILES+= bootstrap'; echo; \ + ${MAKEFILE_SED} \ + ${1 2:L:@n@-e '/start-delete$n/,/end-delete$n/d'@} \ + ${BMAKE_SRC}/Makefile; \ + echo; echo '# override some simple things'; \ + echo 'BINDIR= /usr/bin'; \ + echo 'MANDIR= ${MANDIR:U/usr/share/man}'; \ + echo; echo '# make sure we get this'; \ + echo 'CFLAGS+= $${COPTS.$${.IMPSRC:T}}'; \ + echo; echo 'after-import: ${_this:S,${SRCTOP},\${SRCTOP},}'; \ + echo ' cd $${.CURDIR} && $${.MAKE} -f ${_this:S,${SRCTOP},\${SRCTOP},}'; \ + echo ) > ${.TARGET} + @cmp -s ${.TARGET} ${.CURDIR}/Makefile || \ + mv ${.TARGET} ${.CURDIR}/Makefile + +_utmakefile: bootstrap ${MAKEFILE} + @echo Generating ${.CURDIR}/unit-tests/Makefile + @mkdir -p ${.CURDIR}/unit-tests + @(echo '# This is a generated file, do NOT edit!'; \ + echo '# See ${_this:S,${SRCTOP}/,,}'; \ + echo '#'; echo '# $$${HOST_OS}$$'; \ + ${MAKEFILE_SED} \ + -e '/^UNIT_TESTS/s,=.*,= $${srcdir},' \ + ${BMAKE_SRC}/unit-tests/Makefile ) > ${.TARGET} + @cmp -s ${.TARGET} ${.CURDIR}/unit-tests/Makefile || \ + mv ${.TARGET} ${.CURDIR}/unit-tests/Makefile + + +.include + Property changes on: vendor/NetBSD/bmake/20201101/bsd.after-import.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/os.sh =================================================================== --- vendor/NetBSD/bmake/20201101/os.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/os.sh (revision 367461) @@ -0,0 +1,258 @@ +: +# NAME: +# os.sh - operating system specifics +# +# DESCRIPTION: +# This file is included at the start of processing. Its role is +# to set the variables OS, OSREL, OSMAJOR, MACHINE and MACHINE_ARCH to +# reflect the current system. +# +# It also sets variables such as MAILER, LOCAL_FS, PS_AXC to hide +# certain aspects of different UNIX flavours. +# +# SEE ALSO: +# site.sh,funcs.sh +# +# AUTHOR: +# Simon J. Gerraty + +# RCSid: +# $Id: os.sh,v 1.56 2020/08/05 23:25:22 sjg Exp $ +# +# @(#) Copyright (c) 1994 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +# this lets us skip sourcing it again +_OS_SH=: + +OS=`uname` +OSREL=`uname -r` +OSMAJOR=`IFS=.; set $OSREL; echo $1` +MACHINE=`uname -m` +MACHINE_ARCH=`uname -p 2>/dev/null || echo $MACHINE` + +# there is at least one case of `uname -p` outputting +# a bunch of usless drivel +case "$MACHINE_ARCH" in +unknown|*[!A-Za-z0-9_-]*) MACHINE_ARCH="$MACHINE";; +esac + +# we need this here, and it is not always available... +Which() { + case "$1" in + -*) t=$1; shift;; + *) t=-x;; + esac + case "$1" in + /*) test $t $1 && echo $1;; + *) + # some shells cannot correctly handle `IFS` + # in conjunction with the for loop. + _dirs=`IFS=:; echo ${2:-$PATH}` + for d in $_dirs + do + test $t $d/$1 && { echo $d/$1; break; } + done + ;; + esac +} + +# tr is insanely non-portable wrt char classes, so we need to +# spell out the alphabet. sed y/// would work too. +toUpper() { + ${TR:-tr} abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ +} + +toLower() { + ${TR:-tr} ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz +} + +K= +case $OS in +AIX) # everyone loves to be different... + OSMAJOR=`uname -v` + OSREL="$OSMAJOR.`uname -r`" + LOCAL_FS=jfs + PS_AXC=-e + SHARE_ARCH=$OS/$OSMAJOR.X + ;; +Darwin) # a bit like BSD + HOST_ARCH=$MACHINE + ;; +SunOS) + CHOWN=`Which chown /usr/etc:/usr/bin` + export CHOWN + + # Great! Solaris keeps moving arch(1) + # should just bite the bullet and use uname -p + arch=`Which arch /usr/bin:/usr/ucb` + + MAILER=/usr/ucb/Mail + LOCAL_FS=4.2 + + case "$OSREL" in + 4.0*) + # uname -m just says sun which could be anything + # so use arch(1). + MACHINE_ARCH=`arch` + MACHINE=$MACHINE_ARCH + ;; + 4*) + MACHINE_ARCH=`arch` + ;; + 5*) + K=-k + LOCAL_FS=ufs + MAILER=mailx + PS_AXC=-e + # can you believe that ln on Solaris defaults to + # overwriting an existing file!!!!! We want one that works! + test -x /usr/xpg4/bin/ln && LN=${LN:-/usr/xpg4/bin/ln} + # wonderful, 5.8's tr again require's []'s + # but /usr/xpg4/bin/tr causes problems if LC_COLLATE is set! + # use toUpper/toLower instead. + ;; + esac + case "$OS/$MACHINE_ARCH" in + *sun386) SHARE_ARCH=$MACHINE_ARCH;; + esac + ;; +*BSD) + K=-k + MAILER=/usr/bin/Mail + LOCAL_FS=local + : $-,$ENV + case "$-,$ENV" in + *i*,*) ;; + *,|*ENVFILE*) ;; + *) ENV=;; + esac + # NetBSD at least has good backward compatibility + # so NetBSD/i386 is good enough + case $OS in + NetBSD) + LOCALBASE=/usr/pkg + HOST_ARCH=$MACHINE + SHARE_ARCH=$OS/$HOST_ARCH + ;; + OpenBSD) + arch=`Which arch /usr/bin:/usr/ucb:$PATH` + MACHINE_ARCH=`$arch -s` + ;; + esac + NAWK=awk + export NAWK + ;; +HP-UX) + TMP_DIRS="/tmp /usr/tmp" + LOCAL_FS=hfs + MAILER=mailx + # don't rely on /bin/sh, its broken + _shell=/bin/ksh; ENV= + # also, no one would be interested in OSMAJOR=A + case "$OSREL" in + ?.09*) OSMAJOR=9; PS_AXC=-e;; + ?.10*) OSMAJOR=10; PS_AXC=-e;; + esac + ;; +IRIX) + LOCAL_FS=efs + ;; +Interix) + MACHINE=i386 + MACHINE_ARCH=i386 + ;; +UnixWare) + OSREL=`uname -v` + OSMAJOR=`IFS=.; set $OSREL; echo $1` + MACHINE_ARCH=`uname -m` + ;; +Linux) + # Not really any such thing as Linux, but + # this covers red-hat and hopefully others. + case $MACHINE in + i?86) MACHINE_ARCH=i386;; # we don't care about i686 vs i586 + esac + LOCAL_FS=ext2 + PS_AXC=axc + [ -x /usr/bin/md5sum ] && { MD5=/usr/bin/md5sum; export MD5; } + ;; +QNX) + case $MACHINE in + x86pc) MACHINE_ARCH=i386;; + esac + ;; +Haiku) + case $MACHINE in + BeBox) MACHINE_ARCH=powerpc;; + BeMac) MACHINE_ARCH=powerpc;; + BePC) MACHINE_ARCH=i386;; + esac + ;; +esac +LOCALBASE=${LOCALBASE:-/usr/local} + +HOSTNAME=${HOSTNAME:-`( hostname ) 2>/dev/null`} +HOSTNAME=${HOSTNAME:-`( uname -n ) 2>/dev/null`} +case "$HOSTNAME" in +*.*) HOST=`IFS=.; set -- $HOSTNAME; echo $1`;; +*) HOST=$HOSTNAME;; +esac + +TMP_DIRS=${TMP_DIRS:-"/tmp /var/tmp"} +MACHINE_ARCH=${MACHINE_ARCH:-$MACHINE} +HOST_ARCH=${HOST_ARCH:-$MACHINE_ARCH} +case "$HOST_ARCH" in +x86*64|amd64) MACHINE32_ARCH=i386;; +*64) MACHINE32_ARCH=`echo $MACHINE_ARCH | sed 's,64,32,'`;; +*) MACHINE32_ARCH=$MACHINE_ARCH;; +esac +HOST_ARCH32=${HOST_ARCH32:-$MACHINE32_ARCH} +# we mount server:/share/arch/$SHARE_ARCH as /usr/local +SHARE_ARCH_DEFAULT=$OS/$OSMAJOR.X/$HOST_ARCH +SHARE_ARCH=${SHARE_ARCH:-$SHARE_ARCH_DEFAULT} +LN=${LN:-ln} +TR=${TR:-tr} + +# Some people like have /share/$HOST_TARGET/bin etc. +HOST_TARGET=`echo ${OS}${OSMAJOR}-$HOST_ARCH | tr -d / | toLower` +HOST_TARGET32=`echo ${OS}${OSMAJOR}-$HOST_ARCH32 | tr -d / | toLower` +export HOST_TARGET HOST_TARGET32 + +case `echo -n .` in -n*) N=; C="\c";; *) N=-n; C=;; esac + +Echo() { + case "$1" in + -n) _n=$N _c=$C; shift;; + *) _n= _c=;; + esac + echo $_n "$@" $_c +} + +export HOSTNAME HOST +export OS MACHINE MACHINE_ARCH OSREL OSMAJOR LOCAL_FS TMP_DIRS MAILER N C K PS_AXC +export LN SHARE_ARCH TR +export LOCALBASE + +case /$0 in +*/os.sh) + for v in $* + do + eval vv=\$$v + echo "$v='$vv'" + done + ;; +*/host_target32) echo $HOST_TARGET32;; +*/host_target) echo $HOST_TARGET;; +esac + Property changes on: vendor/NetBSD/bmake/20201101/os.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/dirname.c =================================================================== --- vendor/NetBSD/bmake/20201101/dirname.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/dirname.c (revision 367461) @@ -0,0 +1,125 @@ +/* $NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $ */ + +/*- + * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein and Jason R. Thorpe. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#ifndef HAVE_DIRNAME + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: dirname.c,v 1.14 2018/09/27 00:45:34 kre Exp $"); +#endif /* !LIBC_SCCS && !lint */ + +#include +#ifdef HAVE_LIBGEN_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif +#ifndef MIN +# define MIN(a, b) ((a < b) ? a : b) +#endif + + +static size_t +xdirname_r(const char *path, char *buf, size_t buflen) +{ + const char *endp; + size_t len; + + /* + * If `path' is a null pointer or points to an empty string, + * return a pointer to the string ".". + */ + if (path == NULL || *path == '\0') { + path = "."; + len = 1; + goto out; + } + + /* Strip trailing slashes, if any. */ + endp = path + strlen(path) - 1; + while (endp != path && *endp == '/') + endp--; + + /* Find the start of the dir */ + while (endp > path && *endp != '/') + endp--; + + if (endp == path) { + path = *endp == '/' ? "/" : "."; + len = 1; + goto out; + } + + do + endp--; + while (endp > path && *endp == '/'); + + len = endp - path + 1; +out: + if (buf != NULL && buflen != 0) { + buflen = MIN(len, buflen - 1); + if (buf != path) + memcpy(buf, path, buflen); + buf[buflen] = '\0'; + } + return len; +} + +char * +dirname(char *path) +{ + static char result[PATH_MAX]; + (void)xdirname_r(path, result, sizeof(result)); + return result; +} + +#ifdef MAIN +#include +#include + +int +main(int argc, char *argv[]) +{ + printf("%s\n", dirname(argv[1])); + exit(0); +} +#endif +#endif Property changes on: vendor/NetBSD/bmake/20201101/dirname.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/Makefile.config.in =================================================================== --- vendor/NetBSD/bmake/20201101/Makefile.config.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/Makefile.config.in (revision 367461) @@ -0,0 +1,22 @@ +# things set by configure + +_MAKE_VERSION?=@_MAKE_VERSION@ + +prefix?= @prefix@ +srcdir= @srcdir@ +CC?= @CC@ +MACHINE?= @machine@ +MACHINE_ARCH?= @machine_arch@ +DEFAULT_SYS_PATH?= @default_sys_path@ + +CPPFLAGS+= @CPPFLAGS@ +CFLAGS+= ${CPPFLAGS} @DEFS@ +LDFLAGS+= @LDFLAGS@ +LIBOBJS+= @LIBOBJS@ +LDADD+= @LIBS@ +USE_META?= @use_meta@ +USE_FILEMON?= @use_filemon@ +FILEMON_H?= @filemon_h@ +BMAKE_PATH_MAX?= @bmake_path_max@ +# used if MAXPATHLEN not defined +CPPFLAGS+= -DBMAKE_PATH_MAX=${BMAKE_PATH_MAX} Property changes on: vendor/NetBSD/bmake/20201101/Makefile.config.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/config.h.in =================================================================== --- vendor/NetBSD/bmake/20201101/config.h.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/config.h.in (revision 367461) @@ -0,0 +1,344 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Path of default shell */ +#undef DEFSHELL_CUSTOM + +/* Shell spec to use by default */ +#undef DEFSHELL_INDEX + +/* Define to 1 if you have the header file. */ +#undef HAVE_AR_H + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#undef HAVE_DECL_SYS_SIGLIST + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the `dirname' function. */ +#undef HAVE_DIRNAME + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the `err' function. */ +#undef HAVE_ERR + +/* Define to 1 if you have the `errx' function. */ +#undef HAVE_ERRX + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getenv' function. */ +#undef HAVE_GETENV + +/* Define to 1 if you have the `getopt' function. */ +#undef HAVE_GETOPT + +/* Define to 1 if you have the `getwd' function. */ +#undef HAVE_GETWD + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `killpg' function. */ +#undef HAVE_KILLPG + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define to 1 if you have the header file. */ +#undef HAVE_RANLIB_H + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setpgid' function. */ +#undef HAVE_SETPGID + +/* Define to 1 if you have the `setsid' function. */ +#undef HAVE_SETSID + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `sigvec' function. */ +#undef HAVE_SIGVEC + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `stresep' function. */ +#undef HAVE_STRESEP + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strsep' function. */ +#undef HAVE_STRSEP + +/* Define to 1 if you have the `strtod' function. */ +#undef HAVE_STRTOD + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if `st_rdev' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_RDEV + +/* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use + `HAVE_STRUCT_STAT_ST_RDEV' instead. */ +#undef HAVE_ST_RDEV + +/* Define to 1 if you have the `sysctl' function. */ +#undef HAVE_SYSCTL + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `wait3' function. */ +#undef HAVE_WAIT3 + +/* Define to 1 if you have the `wait4' function. */ +#undef HAVE_WAIT4 + +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + +/* Define to 1 if you have the `warn' function. */ +#undef HAVE_WARN + +/* Define to 1 if you have the `warnx' function. */ +#undef HAVE_WARNX + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* define if your compiler has __attribute__ */ +#undef HAVE___ATTRIBUTE__ + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* C99 function name */ +#undef __func__ + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork Property changes on: vendor/NetBSD/bmake/20201101/config.h.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/aclocal.m4 =================================================================== --- vendor/NetBSD/bmake/20201101/aclocal.m4 (nonexistent) +++ vendor/NetBSD/bmake/20201101/aclocal.m4 (revision 367461) @@ -0,0 +1,82 @@ +dnl RCSid: +dnl $Id: aclocal.m4,v 1.6 2017/11/26 22:39:20 sjg Exp $ +dnl + +dnl +dnl AC_CHECK_HEADER_HAS(HEADER, PATTERN, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])) + +AC_DEFUN(AC_CHECK_HEADER_HAS, +[dnl first check if header exists and if so, see if it contains PATTERN +ac_has_hdr=`echo "ac_cv_header_$1" | sed 'y%./+-%__p_%'` +ac_has_it=`echo "ac_cv_header_$1"_$2 | sed 'y%./+-%__p_%'` +if eval "test \"`echo x'$'$ac_has_hdr`\" = x"; then + AC_CHECK_HEADER($1) +fi +if eval "test \"`echo '$'$ac_has_hdr`\" = yes"; then + ac_x=HAVE_`echo "$1" | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + AC_DEFINE_UNQUOTED($ac_x) + AC_MSG_CHECKING([if $1 has $2]) + AC_CACHE_VAL($ac_has_it, + [eval $ac_has_it=no + AC_EGREP_HEADER($2, $1, eval "$ac_has_it=yes")]) + + if eval "test \"`echo '$'$ac_has_it`\" = yes"; then + AC_MSG_RESULT(yes) + ac_x=HAVE_`echo "$1"_$2 | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + AC_DEFINE_UNQUOTED($ac_x) + ifelse([$3], , :, [$3]) + else + AC_MSG_RESULT(no) + ifelse([$4], , , [$4 +])dnl + fi +fi +]) + +dnl AC_EGREP(PATTERN, FILE, ACTION-IF-FOUND [, +dnl ACTION-IF-NOT-FOUND]) +AC_DEFUN(AC_EGREP, +[ +dnl Prevent m4 from eating character classes: +changequote(, )dnl +if egrep "$1" $2 >/dev/null 2>&1; then +changequote([, ])dnl + ifelse([$3], , :, [$3]) +ifelse([$4], , , [else + $4 +])dnl +fi +]) + +dnl +dnl Test for __attribute__ +dnl + +AC_DEFUN(AC_C___ATTRIBUTE__, [ +AC_MSG_CHECKING(for __attribute__) +AC_CACHE_VAL(ac_cv___attribute__, [ +AC_LINK_IFELSE([ +#include + +static void foo(void) __attribute__ ((noreturn)); + +static void +foo(void) +{ + exit(1); +} + +int +main(int argc, char **argv) +{ + foo(); +} +], +ac_cv___attribute__=yes, +ac_cv___attribute__=no)]) +if test "$ac_cv___attribute__" = "yes"; then + AC_DEFINE(HAVE___ATTRIBUTE__, 1, [define if your compiler has __attribute__]) +fi +AC_MSG_RESULT($ac_cv___attribute__) +]) + Index: vendor/NetBSD/bmake/20201101/stresep.c =================================================================== --- vendor/NetBSD/bmake/20201101/stresep.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/stresep.c (revision 367461) @@ -0,0 +1,93 @@ +/* $NetBSD: stresep.c,v 1.4 2017/08/23 10:27:41 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include + +#if !defined(HAVE_STRESEP) +char * stresep(char **stringp, const char *delim, int esc); +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. If esc is not NUL, then + * the characters followed by esc are ignored and are not taken into account + * when splitting the string. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, stresep returns NULL. + */ +char * +stresep(char **stringp, const char *delim, int esc) +{ + char *s; + const char *spanp; + int c, sc; + size_t l; + char *tok; + + if (stringp == NULL || delim == NULL) + return NULL; + + if ((s = *stringp) == NULL) + return NULL; + l = strlen(s) + 1; + for (tok = s;;) { + c = *s++; + l--; + while (esc != '\0' && c == esc) { + memmove(s - 1, s, l); + c = *s++; + l--; + } + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == '\0') + s = NULL; + else + s[-1] = '\0'; + *stringp = s; + return tok; + } + } while (sc != '\0'); + } +} +#endif + Property changes on: vendor/NetBSD/bmake/20201101/stresep.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/machine.sh =================================================================== --- vendor/NetBSD/bmake/20201101/machine.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/machine.sh (revision 367461) @@ -0,0 +1,106 @@ +: +# derrived from /etc/rc_d/os.sh + +# RCSid: +# $Id: machine.sh,v 1.18 2017/08/13 19:11:28 sjg Exp $ +# +# @(#) Copyright (c) 1994-2002 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@crufty.net +# + +OS=`uname` +OSREL=`uname -r` +OSMAJOR=`IFS=.; set $OSREL; echo $1` +machine=`uname -p 2>/dev/null || uname -m` +MACHINE= + +# there is at least one case of `uname -p` outputting +# a bunch of usless drivel +case "$machine" in +unknown|*[!A-Za-z0-9_-]*) + machine=`uname -m` + ;; +esac + +# Great! Solaris keeps moving arch(1) +# we need this here, and it is not always available... +Which() { + # some shells cannot correctly handle `IFS` + # in conjunction with the for loop. + _dirs=`IFS=:; echo ${2:-$PATH}` + for d in $_dirs + do + test -x $d/$1 && { echo $d/$1; break; } + done +} + +case $OS in +AIX) # from http://gnats.netbsd.org/29386 + OSMAJOR=`uname -v` + OSMINOR=`uname -r` + MACHINE=$OS$OSMAJOR.$OSMINOR + MACHINE_ARCH=`bootinfo -T` + ;; +OpenBSD) + MACHINE=$OS$OSMAJOR.$machine + arch=`Which arch /usr/bin:/usr/ucb:$PATH` + MACHINE_ARCH=`$arch -s`; + ;; +Bitrig) + MACHINE=$OS$OSMAJOR.$machine + MACHINE_ARCH=`uname -m`; + ;; +*BSD) + MACHINE=$OS$OSMAJOR.$machine + ;; +SunOS) + arch=`Which arch /usr/bin:/usr/ucb:$PATH` + test "$arch" && machine_arch=`$arch` + + case "$OSREL" in + 4.0*) MACHINE_ARCH=$machine_arch MACHINE=$machine_arch;; + 4*) MACHINE_ARCH=$machine_arch;; + esac + ;; +HP-UX) + MACHINE_ARCH=`IFS="/-."; set $machine; echo $1` + ;; +Interix) + MACHINE=i386 + MACHINE_ARCH=i386 + ;; +UnixWare) + OSREL=`uname -v` + OSMAJOR=`IFS=.; set $OSREL; echo $1` + MACHINE_ARCH=`uname -m` + ;; +Linux) + case "$machine" in + i?86) MACHINE_ARCH=i386;;# does anyone really care about 686 vs 586? + esac + ;; +esac + +MACHINE=${MACHINE:-$OS$OSMAJOR} +MACHINE_ARCH=${MACHINE_ARCH:-$machine} + +( +case "$0" in +arch*) echo $MACHINE_ARCH;; +*) + case "$1" in + "") echo $MACHINE;; + *) echo $MACHINE_ARCH;; + esac + ;; +esac +) | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz Property changes on: vendor/NetBSD/bmake/20201101/machine.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/PSD.doc/tutorial.ms =================================================================== --- vendor/NetBSD/bmake/20201101/PSD.doc/tutorial.ms (nonexistent) +++ vendor/NetBSD/bmake/20201101/PSD.doc/tutorial.ms (revision 367461) @@ -0,0 +1,3794 @@ +.\" $NetBSD: tutorial.ms,v 1.13 2017/03/01 13:05:11 kre Exp $ +.\" Copyright (c) 1988, 1989, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Adam de Boor. +.\" +.\" 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. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" Copyright (c) 1988, 1989 by Adam de Boor +.\" Copyright (c) 1989 by Berkeley Softworks +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Adam de Boor. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)tutorial.ms 8.1 (Berkeley) 8/18/93 +.\" +.EH 'PSD:12-%''PMake \*- A Tutorial' +.OH 'PMake \*- A Tutorial''PSD:12-%' +.\" Ix is an indexing macro similar to .IX but I've disabled it for now +.\" Since that would require 2 passes and I am not in the mood for that. +.de Ix +.. +.\" Rd is section (region) define and Rm is region mention? Again disable for +.\" now. +.de Rd +.. +.de Rm +.. +.\" xH is a macro to provide numbered headers that are automatically stuffed +.\" into a table-of-contents, properly indented, etc. If the first argument +.\" is numeric, it is taken as the depth for numbering (as for .NH), else +.\" the default (1) is assumed. +.\" +.\" @P The initial paragraph distance. +.\" @Q The piece of section number to increment (or 0 if none given) +.\" @R Section header. +.\" @S Indent for toc entry +.\" @T Argument to NH (can't use @Q b/c giving 0 to NH resets the counter) +.de xH +.NH \\$1 +\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 +.nr PD .1v +.XS \\n% +.ta 0.6i +\\*(SN \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 +.XE +.nr PD .3v +.. +.\" CW is used to place a string in fixed-width or switch to a +.\" fixed-width font. +.\" C is a typewriter font for a laserwriter. Use something else if +.\" you don't have one... +.de CW +.ie !\\n(.$ .ft C +.el \&\\$3\fC\\$1\fP\\$2 +.. +.\" Anything I put in a display I want to be in fixed-width +.am DS +.CW +.. +.\" The stuff in .No produces a little stop sign in the left margin +.\" that says NOTE in it. Unfortunately, it does cause a break, but +.\" hey. Can't have everything. In case you're wondering how I came +.\" up with such weird commands, they came from running grn on a +.\" gremlin file... +.de No +.br +.ne 0.5i +.ie n \{\ +.nr g3 \w'NOTE ' +.po -\\n(g3u +.br +NOTE +.br +.po +\\n(g3u +.\} +.el \{\ +.po -0.5i +.br +.mk +.nr g3 \\n(.f +.nr g4 \\n(.s +.sp -1 +.\" .st cf +\D't 5u' +.sp -1 +\h'50u' +.sp -1 +\D't 3u' +.sp -1 +.sp 7u +\h'53u' +\d\D'p -0.19i 0.0i 0.0i -0.13i 0.30i 0.0i 0.0i 0.13i' +.sp -1 +.ft R +.ps 6 +.nr g8 \\n(.d +.ds g9 "NOTE +.sp 74u +\h'85u'\v'0.85n'\h-\w\\*(g9u/2u\&\\*(g9 +.sp |\\n(g8u +.sp 166u +\D't 3u' +.br +.po +.rt +.ft \\n(g3 +.ps \\n(g4 +.\} +.. +.de Bp +.ie !\\n(.$ .IP \(bu 2 +.el .IP "\&" 2 +.. +.ie n .po +\w'NOTE 'u +.el .po +.3i +.TL +PMake \*- A Tutorial +.AU +Adam de Boor +.AI +Berkeley Softworks +2150 Shattuck Ave, Penthouse +Berkeley, CA 94704 +adam@bsw.uu.net +\&...!uunet!bsw!adam +.FS +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appears in all copies. +The University of California, Berkeley Softworks, and Adam de Boor make no +representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. +.FE +.PP +.xH 1 Introduction +.LP +PMake is a program for creating other programs, or anything else you +can think of for it to do. The basic idea behind PMake is that, for +any given system, be it a program or a document or whatever, there +will be some files that depend on the state of other files (on when +they were last modified). PMake takes these dependencies, which you +must specify, and uses them to build whatever it is you want it to +build. +.LP +PMake is almost fully-compatible with Make, with which you may already +be familiar. PMake's most important feature is its ability to run +several different jobs at once, making the creation of systems +considerably faster. It also has a great deal more functionality than +Make. Throughout the text, whenever something is mentioned that is an +important difference between PMake and Make (i.e. something that will +cause a makefile to fail if you don't do something about it), or is +simply important, it will be flagged with a little sign in the left +margin, like this: +.No +.LP +This tutorial is divided into three main sections corresponding to basic, +intermediate and advanced PMake usage. If you already know Make well, +you will only need to skim chapter 2 (there are some aspects of +PMake that I consider basic to its use that didn't exist in Make). +Things in chapter 3 make life much easier, while those in chapter 4 +are strictly for those who know what they are doing. Chapter 5 has +definitions for the jargon I use and chapter 6 contains possible +solutions to the problems presented throughout the tutorial. +.xH 1 The Basics of PMake +.LP +PMake takes as input a file that tells a) which files depend on which +other files to be complete and b) what to do about files that are +``out-of-date.'' This file is known as a ``makefile'' and is usually +.Ix 0 def makefile +kept in the top-most directory of the system to be built. While you +can call the makefile anything you want, PMake will look for +.CW Makefile +and +.CW makefile +(in that order) in the current directory if you don't tell it +otherwise. +.Ix 0 def makefile default +To specify a different makefile, use the +.B \-f +flag (e.g. +.CW "pmake -f program.mk" ''). `` +.Ix 0 ref flags -f +.Ix 0 ref makefile other +.LP +A makefile has four different types of lines in it: +.RS +.IP \(bu 2 +File dependency specifications +.IP \(bu 2 +Creation commands +.IP \(bu 2 +Variable assignments +.IP \(bu 2 +Comments, include statements and conditional directives +.RE +.LP +Any line may be continued over multiple lines by ending it with a +backslash. +.Ix 0 def "continuation line" +The backslash, following newline and any initial whitespace +on the following line are compressed into a single space before the +input line is examined by PMake. +.xH 2 Dependency Lines +.LP +As mentioned in the introduction, in any system, there are +dependencies between the files that make up the system. For instance, +in a program made up of several C source files and one header file, +the C files will need to be re-compiled should the header file be +changed. For a document of several chapters and one macro file, the +chapters will need to be reprocessed if any of the macros changes. +.Ix 0 def "dependency" +These are dependencies and are specified by means of dependency lines in +the makefile. +.LP +.Ix 0 def "dependency line" +On a dependency line, there are targets and sources, separated by a +one- or two-character operator. +The targets ``depend'' on the sources and are usually created from +them. +.Ix 0 def target +.Ix 0 def source +.Ix 0 ref operator +Any number of targets and sources may be specified on a dependency line. +All the targets in the line are made to depend on all the sources. +Targets and sources need not be actual files, but every source must be +either an actual file or another target in the makefile. +If you run out of room, use a backslash at the end of the line to continue onto +the next one. +.LP +Any file may be a target and any file may be a source, but the +relationship between the two (or however many) is determined by the +``operator'' that separates them. +.Ix 0 def operator +Three types of operators exist: one specifies that the datedness of a +target is determined by the state of its sources, while another +specifies other files (the sources) that need to be dealt with before +the target can be re-created. The third operator is very similar to +the first, with the additional condition that the target is +out-of-date if it has no sources. These operations are represented by +the colon, the exclamation point and the double-colon, respectively, and are +mutually exclusive. Their exact semantics are as follows: +.IP ":" +.Ix 0 def operator colon +.Ix 0 def : +If a colon is used, a target on the line is considered to be +``out-of-date'' (and in need of creation) if +.RS +.IP \(bu 2 +any of the sources has been modified more recently than the target, or +.IP \(bu 2 +the target doesn't exist. +.RE +.Ix 0 def out-of-date +.IP "\&" +Under this operation, steps will be taken to re-create the target only +if it is found to be out-of-date by using these two rules. +.IP "!" +.Ix 0 def operator force +.Ix 0 def ! +If an exclamation point is used, the target will always be re-created, +but this will not happen until all of its sources have been examined +and re-created, if necessary. +.IP "::" +.Ix 0 def operator double-colon +.Ix 0 def :: +If a double-colon is used, a target is out-of-date if: +.RS +.IP \(bu 2 +any of the sources has been modified more recently than the target, or +.IP \(bu 2 +the target doesn't exist, or +.IP \(bu 2 +the target has no sources. +.RE +.IP "\&" +If the target is out-of-date according to these rules, it will be re-created. +This operator also does something else to the targets, but I'll go +into that in the next section (``Shell Commands''). +.LP +Enough words, now for an example. Take that C program I mentioned +earlier. Say there are three C files +.CW a.c , ( +.CW b.c +and +.CW c.c ) +each of which +includes the file +.CW defs.h . +The dependencies between the files could then be expressed as follows: +.DS +program : a.o b.o c.o +a.o b.o c.o : defs.h +a.o : a.c +b.o : b.c +c.o : c.c +.DE +.LP +You may be wondering at this point, where +.CW a.o , +.CW b.o +and +.CW c.o +came in and why +.I they +depend on +.CW defs.h +and the C files don't. The reason is quite simple: +.CW program +cannot be made by linking together .c files \*- it must be +made from .o files. Likewise, if you change +.CW defs.h , +it isn't the .c files that need to be re-created, it's the .o files. +If you think of dependencies in these terms \*- which files (targets) +need to be created from which files (sources) \*- you should have no problems. +.LP +An important thing to notice about the above example, is that all the +\&.o files appear as targets on more than one line. This is perfectly +all right: the target is made to depend on all the sources mentioned +on all the dependency lines. E.g. +.CW a.o +depends on both +.CW defs.h +and +.CW a.c . +.Ix 0 ref dependency +.No +.LP +The order of the dependency lines in the makefile is +important: the first target on the first dependency line in the +makefile will be the one that gets made if you don't say otherwise. +That's why +.CW program +comes first in the example makefile, above. +.LP +Both targets and sources may contain the standard C-Shell wildcard +characters +.CW { , ( +.CW } , +.CW * , +.CW ? , +.CW [ , +and +.CW ] ), +but the non-curly-brace ones may only appear in the final component +(the file portion) of the target or source. The characters mean the +following things: +.IP \fB{}\fP +These enclose a comma-separated list of options and cause the pattern +to be expanded once for each element of the list. Each expansion +contains a different element. For example, +.CW src/{whiffle,beep,fish}.c +expands to the three words +.CW src/whiffle.c , +.CW src/beep.c , +and +.CW src/fish.c . +These braces may be nested and, unlike the other wildcard characters, +the resulting words need not be actual files. All other wildcard +characters are expanded using the files that exist when PMake is +started. +.IP \fB*\fP +This matches zero or more characters of any sort. +.CW src/*.c +will expand to the same three words as above as long as +.CW src +contains those three files (and no other files that end in +.CW .c ). +.IP \fB?\fP +Matches any single character. +.IP \fB[]\fP +This is known as a character class and contains either a list of +single characters, or a series of character ranges +.CW a-z , ( +for example means all characters between a and z), or both. It matches +any single character contained in the list. E.g. +.CW [A-Za-z] +will match all letters, while +.CW [0123456789] +will match all numbers. +.xH 2 Shell Commands +.LP +``Isn't that nice,'' you say to yourself, ``but how are files +actually `re-created,' as he likes to spell it?'' +The re-creation is accomplished by commands you place in the makefile. +These commands are passed to the Bourne shell (better known as +``/bin/sh'') to be executed and are +.Ix 0 ref shell +.Ix 0 ref re-creation +.Ix 0 ref update +expected to do what's necessary to update the target file (PMake +doesn't actually check to see if the target was created. It just +assumes it's there). +.Ix 0 ref target +.LP +Shell commands in a makefile look a lot like shell commands you would +type at a terminal, with one important exception: each command in a +makefile +.I must +be preceded by at least one tab. +.LP +Each target has associated with it a shell script made up of +one or more of these shell commands. The creation script for a target +should immediately follow the dependency line for that target. While +any given target may appear on more than one dependency line, only one +of these dependency lines may be followed by a creation script, unless +the `::' operator was used on the dependency line. +.Ix 0 ref operator double-colon +.Ix 0 ref :: +.No +.LP +If the double-colon was used, each dependency line for the target +may be followed by a shell script. That script will only be executed +if the target on the associated dependency line is out-of-date with +respect to the sources on that line, according to the rules I gave +earlier. +I'll give you a good example of this later on. +.LP +To expand on the earlier makefile, you might add commands as follows: +.DS +program : a.o b.o c.o + cc a.o b.o c.o \-o program +a.o b.o c.o : defs.h +a.o : a.c + cc \-c a.c +b.o : b.c + cc \-c b.c +c.o : c.c + cc \-c c.c +.DE +.LP +Something you should remember when writing a makefile is, the +commands will be executed if the +.I target +on the dependency line is out-of-date, not the sources. +.Ix 0 ref target +.Ix 0 ref source +.Ix 0 ref out-of-date +In this example, the command +.CW "cc \-c a.c" '' `` +will be executed if +.CW a.o +is out-of-date. Because of the `:' operator, +.Ix 0 ref : +.Ix 0 ref operator colon +this means that should +.CW a.c +.I or +.CW defs.h +have been modified more recently than +.CW a.o , +the command will be executed +.CW a.o "\&" ( +will be considered out-of-date). +.Ix 0 ref out-of-date +.LP +Remember how I said the only difference between a makefile shell +command and a regular shell command was the leading tab? I lied. There +is another way in which makefile commands differ from regular ones. +The first two characters after the initial whitespace are treated +specially. +If they are any combination of `@' and `\-', they cause PMake to do +different things. +.LP +In most cases, shell commands are printed before they're +actually executed. This is to keep you informed of what's going on. If +an `@' appears, however, this echoing is suppressed. In the case of an +.CW echo +command, say +.CW "echo Linking index" ,'' `` +it would be +rather silly to see +.DS +echo Linking index +Linking index +.DE +.LP +so PMake allows you to place an `@' before the command +.CW "@echo Linking index" '') (`` +to prevent the command from being printed. +.LP +The other special character is the `\-'. In case you didn't know, +shell commands finish with a certain ``exit status.'' This status is +made available by the operating system to whatever program invoked the +command. Normally this status will be 0 if everything went ok and +non-zero if something went wrong. For this reason, PMake will consider +an error to have occurred if one of the shells it invokes returns a non-zero +status. When it detects an error, PMake's usual action is to abort +whatever it's doing and exit with a non-zero status itself (any other +targets that were being created will continue being made, but nothing +new will be started. PMake will exit after the last job finishes). +This behavior can be altered, however, by placing a `\-' at the front +of a command +.CW "\-mv index index.old" ''), (`` +certain command-line arguments, +or doing other things, to be detailed later. In such +a case, the non-zero status is simply ignored and PMake keeps chugging +along. +.No +.LP +Because all the commands are given to a single shell to execute, such +things as setting shell variables, changing directories, etc., last +beyond the command in which they are found. This also allows shell +compound commands (like +.CW for +loops) to be entered in a natural manner. +Since this could cause problems for some makefiles that depend on +each command being executed by a single shell, PMake has a +.B \-B +.Ix 0 ref compatibility +.Ix 0 ref flags -B +flag (it stands for backwards-compatible) that forces each command to +be given to a separate shell. It also does several other things, all +of which I discourage since they are now old-fashioned.\|.\|.\|. +.No +.LP +A target's shell script is fed to the shell on its (the shell's) input stream. +This means that any commands, such as +.CW ci +that need to get input from the terminal won't work right \*- they'll +get the shell's input, something they probably won't find to their +liking. A simple way around this is to give a command like this: +.DS +ci $(SRCS) < /dev/tty +.DE +This would force the program's input to come from the terminal. If you +can't do this for some reason, your only other alternative is to use +PMake in its fullest compatibility mode. See +.B Compatibility +in chapter 4. +.Ix 0 ref compatibility +.LP +.xH 2 Variables +.LP +PMake, like Make before it, has the ability to save text in variables +to be recalled later at your convenience. Variables in PMake are used +much like variables in the shell and, by tradition, consist of +all upper-case letters (you don't +.I have +to use all upper-case letters. +In fact there's nothing to stop you from calling a variable +.CW @^&$%$ . +Just tradition). Variables are assigned-to using lines of the form +.Ix 0 def variable assignment +.DS +VARIABLE = value +.DE +.Ix 0 def variable assignment +appended-to by +.DS +VARIABLE += value +.DE +.Ix 0 def variable appending +.Ix 0 def variable assignment appended +.Ix 0 def += +conditionally assigned-to (if the variable isn't already defined) by +.DS +VARIABLE ?= value +.DE +.Ix 0 def variable assignment conditional +.Ix 0 def ?= +and assigned-to with expansion (i.e. the value is expanded (see below) +before being assigned to the variable\*-useful for placing a value at +the beginning of a variable, or other things) by +.DS +VARIABLE := value +.DE +.Ix 0 def variable assignment expanded +.Ix 0 def := +.LP +Any whitespace before +.I value +is stripped off. When appending, a space is placed between the old +value and the stuff being appended. +.LP +The final way a variable may be assigned to is using +.DS +VARIABLE != shell-command +.DE +.Ix 0 def variable assignment shell-output +.Ix 0 def != +In this case, +.I shell-command +has all its variables expanded (see below) and is passed off to a +shell to execute. The output of the shell is then placed in the +variable. Any newlines (other than the final one) are replaced by +spaces before the assignment is made. This is typically used to find +the current directory via a line like: +.DS +CWD != pwd +.DE +.LP +.B Note: +this is intended to be used to execute commands that produce small amounts +of output (e.g. ``pwd''). The implementation is less than intelligent and will +likely freeze if you execute something that produces thousands of +bytes of output (8 Kb is the limit on many UNIX systems). +.LP +The value of a variable may be retrieved by enclosing the variable +name in parentheses or curly braces and preceding the whole thing +with a dollar sign. +.LP +For example, to set the variable CFLAGS to the string +.CW "\-I/sprite/src/lib/libc \-O" ,'' `` +you would place a line +.DS +CFLAGS = \-I/sprite/src/lib/libc \-O +.DE +in the makefile and use the word +.CW "$(CFLAGS)" +wherever you would like the string +.CW "\-I/sprite/src/lib/libc \-O" +to appear. This is called variable expansion. +.Ix 0 def variable expansion +.No +.LP +Unlike Make, PMake will not expand a variable unless it knows +the variable exists. E.g. if you have a +.CW "${i}" +in a shell command and you have not assigned a value to the variable +.CW i +(the empty string is considered a value, by the way), where Make would have +substituted the empty string, PMake will leave the +.CW "${i}" +alone. +To keep PMake from substituting for a variable it knows, precede the +dollar sign with another dollar sign. +(e.g. to pass +.CW "${HOME}" +to the shell, use +.CW "$${HOME}" ). +This causes PMake, in effect, to expand the +.CW $ +macro, which expands to a single +.CW $ . +For compatibility, Make's style of variable expansion will be used +if you invoke PMake with any of the compatibility flags (\c +.B \-V , +.B \-B +or +.B \-M . +The +.B \-V +flag alters just the variable expansion). +.Ix 0 ref flags -V +.Ix 0 ref flags -B +.Ix 0 ref flags -M +.Ix 0 ref compatibility +.LP +.Ix 0 ref variable expansion +There are two different times at which variable expansion occurs: +When parsing a dependency line, the expansion occurs immediately +upon reading the line. If any variable used on a dependency line is +undefined, PMake will print a message and exit. +Variables in shell commands are expanded when the command is +executed. +Variables used inside another variable are expanded whenever the outer +variable is expanded (the expansion of an inner variable has no effect +on the outer variable. I.e. if the outer variable is used on a dependency +line and in a shell command, and the inner variable changes value +between when the dependency line is read and the shell command is +executed, two different values will be substituted for the outer +variable). +.Ix 0 def variable types +.LP +Variables come in four flavors, though they are all expanded the same +and all look about the same. They are (in order of expanding scope): +.RS +.IP \(bu 2 +Local variables. +.Ix 0 ref variable local +.IP \(bu 2 +Command-line variables. +.Ix 0 ref variable command-line +.IP \(bu 2 +Global variables. +.Ix 0 ref variable global +.IP \(bu 2 +Environment variables. +.Ix 0 ref variable environment +.RE +.LP +The classification of variables doesn't matter much, except that the +classes are searched from the top (local) to the bottom (environment) +when looking up a variable. The first one found wins. +.xH 3 Local Variables +.LP +.Ix 0 def variable local +Each target can have as many as seven local variables. These are +variables that are only ``visible'' within that target's shell script +and contain such things as the target's name, all of its sources (from +all its dependency lines), those sources that were out-of-date, etc. +Four local variables are defined for all targets. They are: +.RS +.IP ".TARGET" +.Ix 0 def variable local .TARGET +.Ix 0 def .TARGET +The name of the target. +.IP ".OODATE" +.Ix 0 def variable local .OODATE +.Ix 0 def .OODATE +The list of the sources for the target that were considered out-of-date. +The order in the list is not guaranteed to be the same as the order in +which the dependencies were given. +.IP ".ALLSRC" +.Ix 0 def variable local .ALLSRC +.Ix 0 def .ALLSRC +The list of all sources for this target in the order in which they +were given. +.IP ".PREFIX" +.Ix 0 def variable local .PREFIX +.Ix 0 def .PREFIX +The target without its suffix and without any leading path. E.g. for +the target +.CW ../../lib/compat/fsRead.c , +this variable would contain +.CW fsRead . +.RE +.LP +Three other local variables are set only for certain targets under +special circumstances. These are the ``.IMPSRC,'' +.Ix 0 ref variable local .IMPSRC +.Ix 0 ref .IMPSRC +``.ARCHIVE,'' +.Ix 0 ref variable local .ARCHIVE +.Ix 0 ref .ARCHIVE +and ``.MEMBER'' +.Ix 0 ref variable local .MEMBER +.Ix 0 ref .MEMBER +variables. When they are set and how they are used is described later. +.LP +Four of these variables may be used in sources as well as in shell +scripts. +.Ix 0 def "dynamic source" +.Ix 0 def source dynamic +These are ``.TARGET'', ``.PREFIX'', ``.ARCHIVE'' and ``.MEMBER''. The +variables in the sources are expanded once for each target on the +dependency line, providing what is known as a ``dynamic source,'' +.Rd 0 +allowing you to specify several dependency lines at once. For example, +.DS +$(OBJS) : $(.PREFIX).c +.DE +will create a dependency between each object file and its +corresponding C source file. +.xH 3 Command-line Variables +.LP +.Ix 0 def variable command-line +Command-line variables are set when PMake is first invoked by giving a +variable assignment as one of the arguments. For example, +.DS +pmake "CFLAGS = -I/sprite/src/lib/libc -O" +.DE +would make +.CW CFLAGS +be a command-line variable with the given value. Any assignments to +.CW CFLAGS +in the makefile will have no effect, because once it +is set, there is (almost) nothing you can do to change a command-line +variable (the search order, you see). Command-line variables may be +set using any of the four assignment operators, though only +.CW = +and +.CW ?= +behave as you would expect them to, mostly because assignments to +command-line variables are performed before the makefile is read, thus +the values set in the makefile are unavailable at the time. +.CW += +.Ix 0 ref += +.Ix 0 ref variable assignment appended +is the same as +.CW = , +because the old value of the variable is sought only in the scope in +which the assignment is taking place (for reasons of efficiency that I +won't get into here). +.CW := +and +.CW ?= +.Ix 0 ref := +.Ix 0 ref ?= +.Ix 0 ref variable assignment expanded +.Ix 0 ref variable assignment conditional +will work if the only variables used are in the environment. +.CW != +is sort of pointless to use from the command line, since the same +effect can no doubt be accomplished using the shell's own command +substitution mechanisms (backquotes and all that). +.xH 3 Global Variables +.LP +.Ix 0 def variable global +Global variables are those set or appended-to in the makefile. +There are two classes of global variables: those you set and those PMake sets. +As I said before, the ones you set can have any name you want them to have, +except they may not contain a colon or an exclamation point. +The variables PMake sets (almost) always begin with a +period and always contain upper-case letters, only. The variables are +as follows: +.RS +.IP .PMAKE +.Ix 0 def variable global .PMAKE +.Ix 0 def .PMAKE +.Ix 0 def variable global MAKE +.Ix 0 def MAKE +The name by which PMake was invoked is stored in this variable. For +compatibility, the name is also stored in the MAKE variable. +.IP .MAKEFLAGS +.Ix 0 def variable global .MAKEFLAGS +.Ix 0 def .MAKEFLAGS variable +.Ix 0 def variable global MFLAGS +.Ix 0 def MFLAGS +All the relevant flags with which PMake was invoked. This does not +include such things as +.B \-f +or variable assignments. Again for compatibility, this value is stored +in the MFLAGS variable as well. +.RE +.LP +Two other variables, ``.INCLUDES'' and ``.LIBS,'' are covered in the +section on special targets in chapter 3. +.Ix 0 ref variable global .INCLUDES +.Ix 0 ref variable global .LIBS +.LP +Global variables may be deleted using lines of the form: +.Ix 0 def #undef +.Ix 0 def variable deletion +.DS +#undef \fIvariable\fP +.DE +The +.CW # ' ` +must be the first character on the line. Note that this may only be +done on global variables. +.xH 3 Environment Variables +.LP +.Ix 0 def variable environment +Environment variables are passed by the shell that invoked PMake and +are given by PMake to each shell it invokes. They are expanded like +any other variable, but they cannot be altered in any way. +.LP +One special environment variable, +.CW PMAKE , +.Ix 0 def variable environment PMAKE +is examined by PMake for command-line flags, variable assignments, +etc., it should always use. This variable is examined before the +actual arguments to PMake are. In addition, all flags given to PMake, +either through the +.CW PMAKE +variable or on the command line, are placed in this environment +variable and exported to each shell PMake executes. Thus recursive +invocations of PMake automatically receive the same flags as the +top-most one. +.LP +Using all these variables, you can compress the sample makefile even more: +.DS +OBJS = a.o b.o c.o +program : $(OBJS) + cc $(.ALLSRC) \-o $(.TARGET) +$(OBJS) : defs.h +a.o : a.c + cc \-c a.c +b.o : b.c + cc \-c b.c +c.o : c.c + cc \-c c.c +.DE +.Ix 0 ref variable local .ALLSRC +.Ix 0 ref .ALLSRC +.Ix 0 ref variable local .TARGET +.Ix 0 ref .TARGET +.Rd 3 +.xH 2 Comments +.LP +.Ix 0 def comments +Comments in a makefile start with a `#' character and extend to the +end of the line. They may appear +anywhere you want them, except in a shell command (though the shell +will treat it as a comment, too). If, for some reason, you need to use the `#' +in a variable or on a dependency line, put a backslash in front of it. +PMake will compress the two into a single `#' (Note: this isn't true +if PMake is operating in full-compatibility mode). +.Ix 0 ref flags -M +.Ix 0 ref compatibility +.xH 2 Parallelism +.No +.LP +PMake was specifically designed to re-create several targets at once, +when possible. You do not have to do anything special to cause this to +happen (unless PMake was configured to not act in parallel, in which +case you will have to make use of the +.B \-L +and +.B \-J +flags (see below)), +.Ix 0 ref flags -L +.Ix 0 ref flags -J +but you do have to be careful at times. +.LP +There are several problems you are likely to encounter. One is +that some makefiles (and programs) are written in such a way that it is +impossible for two targets to be made at once. The program +.CW xstr , +for example, +always modifies the files +.CW strings +and +.CW x.c . +There is no way to change it. Thus you cannot run two of them at once +without something being trashed. Similarly, if you have commands +in the makefile that always send output to the same file, you will not +be able to make more than one target at once unless you change the +file you use. You can, for instance, add a +.CW $$$$ +to the end of the file name to tack on the process ID of the shell +executing the command (each +.CW $$ +expands to a single +.CW $ , +thus giving you the shell variable +.CW $$ ). +Since only one shell is used for all the +commands, you'll get the same file name for each command in the +script. +.LP +The other problem comes from improperly-specified dependencies that +worked in Make because of its sequential, depth-first way of examining +them. While I don't want to go into depth on how PMake +works (look in chapter 4 if you're interested), I will warn you that +files in two different ``levels'' of the dependency tree may be +examined in a different order in PMake than they were in Make. For +example, given the makefile +.DS +a : b c +b : d +.DE +PMake will examine the targets in the order +.CW c , +.CW d , +.CW b , +.CW a . +If the makefile's author expected PMake to abort before making +.CW c +if an error occurred while making +.CW b , +or if +.CW b +needed to exist before +.CW c +was made, +s/he will be sorely disappointed. The dependencies are +incomplete, since in both these cases, +.CW c +would depend on +.CW b . +So watch out. +.LP +Another problem you may face is that, while PMake is set up to handle the +output from multiple jobs in a graceful fashion, the same is not so for input. +It has no way to regulate input to different jobs, +so if you use the redirection from +.CW /dev/tty +I mentioned earlier, you must be careful not to run two of the jobs at once. +.xH 2 Writing and Debugging a Makefile +.LP +Now you know most of what's in a makefile, what do you do next? There +are two choices: (1) use one of the uncommonly-available makefile +generators or (2) write your own makefile (I leave out the third choice of +ignoring PMake and doing everything by hand as being beyond the bounds +of common sense). +.LP +When faced with the writing of a makefile, it is usually best to start +from first principles: just what +.I are +you trying to do? What do you want the makefile finally to produce? +.LP +To begin with a somewhat traditional example, let's say you need to +write a makefile to create a program, +.CW expr , +that takes standard infix expressions and converts them to prefix form (for +no readily apparent reason). You've got three source files, in C, that +make up the program: +.CW main.c , +.CW parse.c , +and +.CW output.c . +Harking back to my pithy advice about dependency lines, you write the +first line of the file: +.DS +expr : main.o parse.o output.o +.DE +because you remember +.CW expr +is made from +.CW .o +files, not +.CW .c +files. Similarly for the +.CW .o +files you produce the lines: +.DS +main.o : main.c +parse.o : parse.c +output.o : output.c +main.o parse.o output.o : defs.h +.DE +.LP +Great. You've now got the dependencies specified. What you need now is +commands. These commands, remember, must produce the target on the +dependency line, usually by using the sources you've listed. +You remember about local variables? Good, so it should come +to you as no surprise when you write +.DS +expr : main.o parse.o output.o + cc -o $(.TARGET) $(.ALLSRC) +.DE +Why use the variables? If your program grows to produce postfix +expressions too (which, of course, requires a name change or two), it +is one fewer place you have to change the file. You cannot do this for +the object files, however, because they depend on their corresponding +source files +.I and +.CW defs.h , +thus if you said +.DS + cc -c $(.ALLSRC) +.DE +you'd get (for +.CW main.o ): +.DS + cc -c main.c defs.h +.DE +which is wrong. So you round out the makefile with these lines: +.DS +main.o : main.c + cc -c main.c +parse.o : parse.c + cc -c parse.c +output.o : output.c + cc -c output.c +.DE +.LP +The makefile is now complete and will, in fact, create the program you +want it to without unnecessary compilations or excessive typing on +your part. There are two things wrong with it, however (aside from it +being altogether too long, something I'll address in chapter 3): +.IP 1) +The string +.CW "main.o parse.o output.o" '' `` +is repeated twice, necessitating two changes when you add postfix +(you were planning on that, weren't you?). This is in direct violation +of de Boor's First Rule of writing makefiles: +.QP +.I +Anything that needs to be written more than once +should be placed in a variable. +.IP "\&" +I cannot emphasize this enough as being very important to the +maintenance of a makefile and its program. +.IP 2) +There is no way to alter the way compilations are performed short of +editing the makefile and making the change in all places. This is evil +and violates de Boor's Second Rule, which follows directly from the +first: +.QP +.I +Any flags or programs used inside a makefile should be placed in a variable so +they may be changed, temporarily or permanently, with the greatest ease. +.LP +The makefile should more properly read: +.DS +OBJS = main.o parse.o output.o +expr : $(OBJS) + $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC) +main.o : main.c + $(CC) $(CFLAGS) -c main.c +parse.o : parse.c + $(CC) $(CFLAGS) -c parse.c +output.o : output.c + $(CC) $(CFLAGS) -c output.c +$(OBJS) : defs.h +.DE +Alternatively, if you like the idea of dynamic sources mentioned in +section 2.3.1, +.Rm 0 2.3.1 +.Rd 4 +.Ix 0 ref "dynamic source" +.Ix 0 ref source dynamic +you could write it like this: +.DS +OBJS = main.o parse.o output.o +expr : $(OBJS) + $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC) +$(OBJS) : $(.PREFIX).c defs.h + $(CC) $(CFLAGS) -c $(.PREFIX).c +.DE +These two rules and examples lead to de Boor's First Corollary: +.QP +.I +Variables are your friends. +.LP +Once you've written the makefile comes the sometimes-difficult task of +.Ix 0 ref debugging +making sure the darn thing works. Your most helpful tool to make sure +the makefile is at least syntactically correct is the +.B \-n +.Ix 0 ref flags -n +flag, which allows you to see if PMake will choke on the makefile. The +second thing the +.B \-n +flag lets you do is see what PMake would do without it actually doing +it, thus you can make sure the right commands would be executed were +you to give PMake its head. +.LP +When you find your makefile isn't behaving as you hoped, the first +question that comes to mind (after ``What time is it, anyway?'') is +``Why not?'' In answering this, two flags will serve you well: +.CW "-d m" '' `` +.Ix 0 ref flags -d +and +.CW "-p 2" .'' `` +.Ix 0 ref flags -p +The first causes PMake to tell you as it examines each target in the +makefile and indicate why it is deciding whatever it is deciding. You +can then use the information printed for other targets to see where +you went wrong. The +.CW "-p 2" '' `` +flag makes PMake print out its internal state when it is done, +allowing you to see that you forgot to make that one chapter depend on +that file of macros you just got a new version of. The output from +.CW "-p 2" '' `` +is intended to resemble closely a real makefile, but with additional +information provided and with variables expanded in those commands +PMake actually printed or executed. +.LP +Something to be especially careful about is circular dependencies. +.Ix 0 def dependency circular +E.g. +.DS +a : b +b : c d +d : a +.DE +In this case, because of how PMake works, +.CW c +is the only thing PMake will examine, because +.CW d +and +.CW a +will effectively fall off the edge of the universe, making it +impossible to examine +.CW b +(or them, for that matter). +PMake will tell you (if run in its normal mode) all the targets +involved in any cycle it looked at (i.e. if you have two cycles in the +graph (naughty, naughty), but only try to make a target in one of +them, PMake will only tell you about that one. You'll have to try to +make the other to find the second cycle). When run as Make, it will +only print the first target in the cycle. +.xH 2 Invoking PMake +.LP +.Ix 0 ref flags +.Ix 0 ref arguments +.Ix 0 ref usage +PMake comes with a wide variety of flags to choose from. +They may appear in any order, interspersed with command-line variable +assignments and targets to create. +The flags are as follows: +.IP "\fB\-d\fP \fIwhat\fP" +.Ix 0 def flags -d +.Ix 0 ref debugging +This causes PMake to spew out debugging information that +may prove useful to you. If you can't +figure out why PMake is doing what it's doing, you might try using +this flag. The +.I what +parameter is a string of single characters that tell PMake what +aspects you are interested in. Most of what I describe will make +little sense to you, unless you've dealt with Make before. Just +remember where this table is and come back to it as you read on. +The characters and the information they produce are as follows: +.RS +.IP a +Archive searching and caching. +.IP c +Conditional evaluation. +.IP d +The searching and caching of directories. +.IP j +Various snippets of information related to the running of the multiple +shells. Not particularly interesting. +.IP m +The making of each target: what target is being examined; when it was +last modified; whether it is out-of-date; etc. +.IP p +Makefile parsing. +.IP r +Remote execution. +.IP s +The application of suffix-transformation rules. (See chapter 3) +.IP t +The maintenance of the list of targets. +.IP v +Variable assignment. +.RE +.IP "\&" +Of these all, the +.CW m +and +.CW s +letters will be most useful to you. +If the +.B \-d +is the final argument or the argument from which it would get these +key letters (see below for a note about which argument would be used) +begins with a +.B \- , +all of these debugging flags will be set, resulting in massive amounts +of output. +.IP "\fB\-f\fP \fImakefile\fP" +.Ix 0 def flags -f +Specify a makefile to read different from the standard makefiles +.CW Makefile "\&" ( +or +.CW makefile ). +.Ix 0 ref makefile default +.Ix 0 ref makefile other +If +.I makefile +is ``\-'', PMake uses the standard input. This is useful for making +quick and dirty makefiles.\|.\|. +.Ix 0 ref makefile "quick and dirty" +.IP \fB\-h\fP +.Ix 0 def flags -h +Prints out a summary of the various flags PMake accepts. It can also +be used to find out what level of concurrency was compiled into the +version of PMake you are using (look at +.B \-J +and +.B \-L ) +and various other information on how PMake was configured. +.Ix 0 ref configuration +.Ix 0 ref makefile system +.IP \fB\-i\fP +.Ix 0 def flags -i +If you give this flag, PMake will ignore non-zero status returned +by any of its shells. It's like placing a `\-' before all the commands +in the makefile. +.IP \fB\-k\fP +.Ix 0 def flags -k +This is similar to +.B \-i +in that it allows PMake to continue when it sees an error, but unlike +.B \-i , +where PMake continues blithely as if nothing went wrong, +.B \-k +causes it to recognize the error and only continue work on those +things that don't depend on the target, either directly or indirectly (through +depending on something that depends on it), whose creation returned the error. +The `k' is for ``keep going''.\|.\|. +.Ix 0 ref target +.IP \fB\-l\fP +.Ix 0 def flags -l +PMake has the ability to lock a directory against other +people executing it in the same directory (by means of a file called +``LOCK.make'' that it creates and checks for in the directory). This +is a Good Thing because two people doing the same thing in the same place +can be disastrous for the final product (too many cooks and all that). +Whether this locking is the default is up to your system +administrator. If locking is on, +.B \-l +will turn it off, and vice versa. Note that this locking will not +prevent \fIyou\fP from invoking PMake twice in the same place \*- if +you own the lock file, PMake will warn you about it but continue to execute. +.IP "\fB\-m\fP \fIdirectory\fP" +.Ix 0 def flags -m +Tells PMake another place to search for included makefiles via the <...> +style. Several +.B \-m +options can be given to form a search path. If this construct is used the +default system makefile search path is completely overridden. +To be explained in chapter 3, section 3.2. +.Rm 2 3.2 +.IP \fB\-n\fP +.Ix 0 def flags -n +This flag tells PMake not to execute the commands needed to update the +out-of-date targets in the makefile. Rather, PMake will simply print +the commands it would have executed and exit. This is particularly +useful for checking the correctness of a makefile. If PMake doesn't do +what you expect it to, it's a good chance the makefile is wrong. +.IP "\fB\-p\fP \fInumber\fP" +.Ix 0 def flags -p +.Ix 0 ref debugging +This causes PMake to print its input in a reasonable form, though +not necessarily one that would make immediate sense to anyone but me. The +.I number +is a bitwise-or of 1 and 2 where 1 means it should print the input +before doing any processing and 2 says it should print it after +everything has been re-created. Thus +.CW "\-p 3" +would print it twice\*-once before processing and once after (you +might find the difference between the two interesting). This is mostly +useful to me, but you may find it informative in some bizarre circumstances. +.IP \fB\-q\fP +.Ix 0 def flags -q +If you give PMake this flag, it will not try to re-create anything. It +will just see if anything is out-of-date and exit non-zero if so. +.IP \fB\-r\fP +.Ix 0 def flags -r +When PMake starts up, it reads a default makefile that tells it what +sort of system it's on and gives it some idea of what to do if you +don't tell it anything. I'll tell you about it in chapter 3. If you +give this flag, PMake won't read the default makefile. +.IP \fB\-s\fP +.Ix 0 def flags -s +This causes PMake to not print commands before they're executed. It +is the equivalent of putting an `@' before every command in the +makefile. +.IP \fB\-t\fP +.Ix 0 def flags -t +Rather than try to re-create a target, PMake will simply ``touch'' it +so as to make it appear up-to-date. If the target didn't exist before, +it will when PMake finishes, but if the target did exist, it will +appear to have been updated. +.IP \fB\-v\fP +.Ix 0 def flags -v +This is a mixed-compatibility flag intended to mimic the System V +version of Make. It is the same as giving +.B \-B , +and +.B \-V +as well as turning off directory locking. Targets can still be created +in parallel, however. This is the mode PMake will enter if it is +invoked either as +.CW smake '' `` +or +.CW vmake ''. `` +.IP \fB\-x\fP +.Ix 0 def flags -x +This tells PMake it's ok to export jobs to other machines, if they're +available. It is used when running in Make mode, as exporting in this +mode tends to make things run slower than if the commands were just +executed locally. +.IP \fB\-B\fP +.Ix 0 ref compatibility +.Ix 0 def flags -B +Forces PMake to be as backwards-compatible with Make as possible while +still being itself. +This includes: +.RS +.IP \(bu 2 +Executing one shell per shell command +.IP \(bu 2 +Expanding anything that looks even vaguely like a variable, with the +empty string replacing any variable PMake doesn't know. +.IP \(bu 2 +Refusing to allow you to escape a `#' with a backslash. +.IP \(bu 2 +Permitting undefined variables on dependency lines and conditionals +(see below). Normally this causes PMake to abort. +.RE +.IP \fB\-C\fP +.Ix 0 def flags -C +This nullifies any and all compatibility mode flags you may have given +or implied up to the time the +.B \-C +is encountered. It is useful mostly in a makefile that you wrote for PMake +to avoid bad things happening when someone runs PMake as +.CW make '' `` +or has things set in the environment that tell it to be compatible. +.B \-C +is +.I not +placed in the +.CW PMAKE +environment variable or the +.CW .MAKEFLAGS +or +.CW MFLAGS +global variables. +.Ix 0 ref variable environment PMAKE +.Ix 0 ref variable global .MAKEFLAGS +.Ix 0 ref variable global MFLAGS +.Ix 0 ref .MAKEFLAGS variable +.Ix 0 ref MFLAGS +.IP "\fB\-D\fP \fIvariable\fP" +.Ix 0 def flags -D +Allows you to define a variable to have +.CW 1 '' `` +as its value. The variable is a global variable, not a command-line +variable. This is useful mostly for people who are used to the C +compiler arguments and those using conditionals, which I'll get into +in section 4.3 +.Rm 1 4.3 +.IP "\fB\-I\fP \fIdirectory\fP" +.Ix 0 def flags -I +Tells PMake another place to search for included makefiles. Yet +another thing to be explained in chapter 3 (section 3.2, to be +precise). +.Rm 2 3.2 +.IP "\fB\-J\fP \fInumber\fP" +.Ix 0 def flags -J +Gives the absolute maximum number of targets to create at once on both +local and remote machines. +.IP "\fB\-L\fP \fInumber\fP" +.Ix 0 def flags -L +This specifies the maximum number of targets to create on the local +machine at once. This may be 0, though you should be wary of doing +this, as PMake may hang until a remote machine becomes available, if +one is not available when it is started. +.IP \fB\-M\fP +.Ix 0 ref compatibility +.Ix 0 def flags -M +This is the flag that provides absolute, complete, full compatibility +with Make. It still allows you to use all but a few of the features of +PMake, but it is non-parallel. This is the mode PMake enters if you +call it +.CW make .'' `` +.IP \fB\-P\fP +.Ix 0 def flags -P +.Ix 0 ref "output control" +When creating targets in parallel, several shells are executing at +once, each wanting to write its own two cent's-worth to the screen. +This output must be captured by PMake in some way in order to prevent +the screen from being filled with garbage even more indecipherable +than you usually see. PMake has two ways of doing this, one of which +provides for much cleaner output and a clear separation between the +output of different jobs, the other of which provides a more immediate +response so one can tell what is really happening. The former is done +by notifying you when the creation of a target starts, capturing the +output and transferring it to the screen all at once when the job +finishes. The latter is done by catching the output of the shell (and +its children) and buffering it until an entire line is received, then +printing that line preceded by an indication of which job produced +the output. Since I prefer this second method, it is the one used by +default. The first method will be used if you give the +.B \-P +flag to PMake. +.IP \fB\-V\fP +.Ix 0 def flags -V +As mentioned before, the +.B \-V +flag tells PMake to use Make's style of expanding variables, +substituting the empty string for any variable it doesn't know. +.IP \fB\-W\fP +.Ix 0 def flags -W +There are several times when PMake will print a message at you that is +only a warning, i.e. it can continue to work in spite of your having +done something silly (such as forgotten a leading tab for a shell +command). Sometimes you are well aware of silly things you have done +and would like PMake to stop bothering you. This flag tells it to shut +up about anything non-fatal. +.IP \fB\-X\fP +.Ix 0 def flags -X +This flag causes PMake to not attempt to export any jobs to another +machine. +.LP +Several flags may follow a single `\-'. Those flags that require +arguments take them from successive parameters. E.g. +.DS +pmake -fDnI server.mk DEBUG /chip2/X/server/include +.DE +will cause PMake to read +.CW server.mk +as the input makefile, define the variable +.CW DEBUG +as a global variable and look for included makefiles in the directory +.CW /chip2/X/server/include . +.xH 2 Summary +.LP +A makefile is made of four types of lines: +.RS +.IP \(bu 2 +Dependency lines +.IP \(bu 2 +Creation commands +.IP \(bu 2 +Variable assignments +.IP \(bu 2 +Comments, include statements and conditional directives +.RE +.LP +A dependency line is a list of one or more targets, an operator +.CW : ', (` +.CW :: ', ` +or +.CW ! '), ` +and a list of zero or more sources. Sources may contain wildcards and +certain local variables. +.LP +A creation command is a regular shell command preceded by a tab. In +addition, if the first two characters after the tab (and other +whitespace) are a combination of +.CW @ ' ` +or +.CW - ', ` +PMake will cause the command to not be printed (if the character is +.CW @ ') ` +or errors from it to be ignored (if +.CW - '). ` +A blank line, dependency line or variable assignment terminates a +creation script. There may be only one creation script for each target +with a +.CW : ' ` +or +.CW ! ' ` +operator. +.LP +Variables are places to store text. They may be unconditionally +assigned-to using the +.CW = ' ` +.Ix 0 ref = +.Ix 0 ref variable assignment +operator, appended-to using the +.CW += ' ` +.Ix 0 ref += +.Ix 0 ref variable assignment appended +operator, conditionally (if the variable is undefined) assigned-to +with the +.CW ?= ' ` +.Ix 0 ref ?= +.Ix 0 ref variable assignment conditional +operator, and assigned-to with variable expansion with the +.CW := ' ` +.Ix 0 ref := +.Ix 0 ref variable assignment expanded +operator. The output of a shell command may be assigned to a variable +using the +.CW != ' ` +.Ix 0 ref != +.Ix 0 ref variable assignment shell-output +operator. Variables may be expanded (their value inserted) by enclosing +their name in parentheses or curly braces, preceded by a dollar sign. +A dollar sign may be escaped with another dollar sign. Variables are +not expanded if PMake doesn't know about them. There are seven local +variables: +.CW .TARGET , +.CW .ALLSRC , +.CW .OODATE , +.CW .PREFIX , +.CW .IMPSRC , +.CW .ARCHIVE , +and +.CW .MEMBER . +Four of them +.CW .TARGET , ( +.CW .PREFIX , +.CW .ARCHIVE , +and +.CW .MEMBER ) +may be used to specify ``dynamic sources.'' +.Ix 0 ref "dynamic source" +.Ix 0 ref source dynamic +Variables are good. Know them. Love them. Live them. +.LP +Debugging of makefiles is best accomplished using the +.B \-n , +.B "\-d m" , +and +.B "\-p 2" +flags. +.xH 2 Exercises +.ce +\s+4\fBTBA\fP\s0 +.xH 1 Short-cuts and Other Nice Things +.LP +Based on what I've told you so far, you may have gotten the impression +that PMake is just a way of storing away commands and making sure you +don't forget to compile something. Good. That's just what it is. +However, the ways I've described have been inelegant, at best, and +painful, at worst. +This chapter contains things that make the +writing of makefiles easier and the makefiles themselves shorter and +easier to modify (and, occasionally, simpler). In this chapter, I +assume you are somewhat more +familiar with Sprite (or UNIX, if that's what you're using) than I did +in chapter 2, just so you're on your toes. +So without further ado... +.xH 2 Transformation Rules +.LP +As you know, a file's name consists of two parts: a base name, which +gives some hint as to the contents of the file, and a suffix, which +usually indicates the format of the file. +Over the years, as +.UX +has developed, +naming conventions, with regard to suffixes, have also developed that have +become almost as incontrovertible as Law. E.g. a file ending in +.CW .c +is assumed to contain C source code; one with a +.CW .o +suffix is assumed to be a compiled, relocatable object file that may +be linked into any program; a file with a +.CW .ms +suffix is usually a text file to be processed by Troff with the \-ms +macro package, and so on. +One of the best aspects of both Make and PMake comes from their +understanding of how the suffix of a file pertains to its contents and +their ability to do things with a file based solely on its suffix. This +ability comes from something known as a transformation rule. A +transformation rule specifies how to change a file with one suffix +into a file with another suffix. +.LP +A transformation rule looks much like a dependency line, except the +target is made of two known suffixes stuck together. Suffixes are made +known to PMake by placing them as sources on a dependency line whose +target is the special target +.CW .SUFFIXES . +E.g. +.DS +\&.SUFFIXES : .o .c +\&.c.o : + $(CC) $(CFLAGS) -c $(.IMPSRC) +.DE +The creation script attached to the target is used to transform a file with +the first suffix (in this case, +.CW .c ) +into a file with the second suffix (here, +.CW .o ). +In addition, the target inherits whatever attributes have been applied +to the transformation rule. +The simple rule given above says that to transform a C source file +into an object file, you compile it using +.CW cc +with the +.CW \-c +flag. +This rule is taken straight from the system makefile. Many +transformation rules (and suffixes) are defined there, and I refer you +to it for more examples (type +.CW "pmake -h" '' `` +to find out where it is). +.LP +There are several things to note about the transformation rule given +above: +.RS +.IP 1) +The +.CW .IMPSRC +variable. +.Ix 0 def variable local .IMPSRC +.Ix 0 def .IMPSRC +This variable is set to the ``implied source'' (the file from which +the target is being created; the one with the first suffix), which, in this +case, is the .c file. +.IP 2) +The +.CW CFLAGS +variable. Almost all of the transformation rules in the system +makefile are set up using variables that you can alter in your +makefile to tailor the rule to your needs. In this case, if you want +all your C files to be compiled with the +.B \-g +flag, to provide information for +.CW dbx , +you would set the +.CW CFLAGS +variable to contain +.CW -g +.CW "CFLAGS = -g" '') (`` +and PMake would take care of the rest. +.RE +.LP +To give you a quick example, the makefile in 2.3.4 +.Rm 3 2.3.4 +could be changed to this: +.DS +OBJS = a.o b.o c.o +program : $(OBJS) + $(CC) -o $(.TARGET) $(.ALLSRC) +$(OBJS) : defs.h +.DE +The transformation rule I gave above takes the place of the 6 lines\** +.FS +This is also somewhat cleaner, I think, than the dynamic source +solution presented in 2.6 +.FE +.Rm 4 2.6 +.DS +a.o : a.c + cc -c a.c +b.o : b.c + cc -c b.c +c.o : c.c + cc -c c.c +.DE +.LP +Now you may be wondering about the dependency between the +.CW .o +and +.CW .c +files \*- it's not mentioned anywhere in the new makefile. This is +because it isn't needed: one of the effects of applying a +transformation rule is the target comes to depend on the implied +source. That's why it's called the implied +.I source . +.LP +For a more detailed example. Say you have a makefile like this: +.DS +a.out : a.o b.o + $(CC) $(.ALLSRC) +.DE +and a directory set up like this: +.DS +total 4 +-rw-rw-r-- 1 deboor 34 Sep 7 00:43 Makefile +-rw-rw-r-- 1 deboor 119 Oct 3 19:39 a.c +-rw-rw-r-- 1 deboor 201 Sep 7 00:43 a.o +-rw-rw-r-- 1 deboor 69 Sep 7 00:43 b.c +.DE +While just typing +.CW pmake '' `` +will do the right thing, it's much more informative to type +.CW "pmake -d s" ''. `` +This will show you what PMake is up to as it processes the files. In +this case, PMake prints the following: +.DS +Suff_FindDeps (a.out) + using existing source a.o + applying .o -> .out to "a.o" +Suff_FindDeps (a.o) + trying a.c...got it + applying .c -> .o to "a.c" +Suff_FindDeps (b.o) + trying b.c...got it + applying .c -> .o to "b.c" +Suff_FindDeps (a.c) + trying a.y...not there + trying a.l...not there + trying a.c,v...not there + trying a.y,v...not there + trying a.l,v...not there +Suff_FindDeps (b.c) + trying b.y...not there + trying b.l...not there + trying b.c,v...not there + trying b.y,v...not there + trying b.l,v...not there +--- a.o --- +cc -c a.c +--- b.o --- +cc -c b.c +--- a.out --- +cc a.o b.o +.DE +.LP +.CW Suff_FindDeps +is the name of a function in PMake that is called to check for implied +sources for a target using transformation rules. +The transformations it tries are, naturally +enough, limited to the ones that have been defined (a transformation +may be defined multiple times, by the way, but only the most recent +one will be used). You will notice, however, that there is a definite +order to the suffixes that are tried. This order is set by the +relative positions of the suffixes on the +.CW .SUFFIXES +line \*- the earlier a suffix appears, the earlier it is checked as +the source of a transformation. Once a suffix has been defined, the +only way to change its position in the pecking order is to remove all +the suffixes (by having a +.CW .SUFFIXES +dependency line with no sources) and redefine them in the order you +want. (Previously-defined transformation rules will be automatically +redefined as the suffixes they involve are re-entered.) +.LP +Another way to affect the search order is to make the dependency +explicit. In the above example, +.CW a.out +depends on +.CW a.o +and +.CW b.o . +Since a transformation exists from +.CW .o +to +.CW .out , +PMake uses that, as indicated by the +.CW "using existing source a.o" '' `` +message. +.LP +The search for a transformation starts from the suffix of the target +and continues through all the defined transformations, in the order +dictated by the suffix ranking, until an existing file with the same +base (the target name minus the suffix and any leading directories) is +found. At that point, one or more transformation rules will have been +found to change the one existing file into the target. +.LP +For example, ignoring what's in the system makefile for now, say you +have a makefile like this: +.DS +\&.SUFFIXES : .out .o .c .y .l +\&.l.c : + lex $(.IMPSRC) + mv lex.yy.c $(.TARGET) +\&.y.c : + yacc $(.IMPSRC) + mv y.tab.c $(.TARGET) +\&.c.o : + cc -c $(.IMPSRC) +\&.o.out : + cc -o $(.TARGET) $(.IMPSRC) +.DE +and the single file +.CW jive.l . +If you were to type +.CW "pmake -rd ms jive.out" ,'' `` +you would get the following output for +.CW jive.out : +.DS +Suff_FindDeps (jive.out) + trying jive.o...not there + trying jive.c...not there + trying jive.y...not there + trying jive.l...got it + applying .l -> .c to "jive.l" + applying .c -> .o to "jive.c" + applying .o -> .out to "jive.o" +.DE +and this is why: PMake starts with the target +.CW jive.out , +figures out its suffix +.CW .out ) ( +and looks for things it can transform to a +.CW .out +file. In this case, it only finds +.CW .o , +so it looks for the file +.CW jive.o . +It fails to find it, so it looks for transformations into a +.CW .o +file. Again it has only one choice: +.CW .c . +So it looks for +.CW jive.c +and, as you know, fails to find it. At this point it has two choices: +it can create the +.CW .c +file from either a +.CW .y +file or a +.CW .l +file. Since +.CW .y +came first on the +.CW .SUFFIXES +line, it checks for +.CW jive.y +first, but can't find it, so it looks for +.CW jive.l +and, lo and behold, there it is. +At this point, it has defined a transformation path as follows: +.CW .l +\(-> +.CW .c +\(-> +.CW .o +\(-> +.CW .out +and applies the transformation rules accordingly. For completeness, +and to give you a better idea of what PMake actually did with this +three-step transformation, this is what PMake printed for the rest of +the process: +.DS +Suff_FindDeps (jive.o) + using existing source jive.c + applying .c -> .o to "jive.c" +Suff_FindDeps (jive.c) + using existing source jive.l + applying .l -> .c to "jive.l" +Suff_FindDeps (jive.l) +Examining jive.l...modified 17:16:01 Oct 4, 1987...up-to-date +Examining jive.c...non-existent...out-of-date +--- jive.c --- +lex jive.l +\&.\|.\|. meaningless lex output deleted .\|.\|. +mv lex.yy.c jive.c +Examining jive.o...non-existent...out-of-date +--- jive.o --- +cc -c jive.c +Examining jive.out...non-existent...out-of-date +--- jive.out --- +cc -o jive.out jive.o +.DE +.LP +One final question remains: what does PMake do with targets that have +no known suffix? PMake simply pretends it actually has a known suffix +and searches for transformations accordingly. +The suffix it chooses is the source for the +.CW .NULL +.Ix 0 ref .NULL +target mentioned later. In the system makefile, +.CW .out +is chosen as the ``null suffix'' +.Ix 0 def suffix null +.Ix 0 def "null suffix" +because most people use PMake to create programs. You are, however, +free and welcome to change it to a suffix of your own choosing. +The null suffix is ignored, however, when PMake is in compatibility +mode (see chapter 4). +.xH 2 Including Other Makefiles +.Ix 0 def makefile inclusion +.Rd 2 +.LP +Just as for programs, it is often useful to extract certain parts of a +makefile into another file and just include it in other makefiles +somehow. Many compilers allow you say something like +.DS +#include "defs.h" +.DE +to include the contents of +.CW defs.h +in the source file. PMake allows you to do the same thing for +makefiles, with the added ability to use variables in the filenames. +An include directive in a makefile looks either like this: +.DS +#include +.DE +or this +.DS +#include "file" +.DE +The difference between the two is where PMake searches for the file: +the first way, PMake will look for +the file only in the system makefile directory (or directories) +(to find out what that directory is, give PMake the +.B \-h +flag). +.Ix 0 ref flags -h +The system makefile directory search path can be overridden via the +.B \-m +option. +.Ix 0 ref flags -m +For files in double-quotes, the search is more complex: +.RS +.IP 1) +The directory of the makefile that's including the file. +.IP 2) +The current directory (the one in which you invoked PMake). +.IP 3) +The directories given by you using +.B \-I +flags, in the order in which you gave them. +.IP 4) +Directories given by +.CW .PATH +dependency lines (see chapter 4). +.IP 5) +The system makefile directory. +.RE +.LP +in that order. +.LP +You are free to use PMake variables in the filename\*-PMake will +expand them before searching for the file. You must specify the +searching method with either angle brackets or double-quotes +.I outside +of a variable expansion. I.e. the following +.DS +SYSTEM = + +#include $(SYSTEM) +.DE +won't work. +.xH 2 Saving Commands +.LP +.Ix 0 def ... +There may come a time when you will want to save certain commands to +be executed when everything else is done. For instance: you're +making several different libraries at one time and you want to create the +members in parallel. Problem is, +.CW ranlib +is another one of those programs that can't be run more than once in +the same directory at the same time (each one creates a file called +.CW __.SYMDEF +into which it stuffs information for the linker to use. Two of them +running at once will overwrite each other's file and the result will +be garbage for both parties). You might want a way to save the ranlib +commands til the end so they can be run one after the other, thus +keeping them from trashing each other's file. PMake allows you to do +this by inserting an ellipsis (``.\|.\|.'') as a command between +commands to be run at once and those to be run later. +.LP +So for the +.CW ranlib +case above, you might do this: +.Rd 5 +.DS +lib1.a : $(LIB1OBJS) + rm -f $(.TARGET) + ar cr $(.TARGET) $(.ALLSRC) + ... + ranlib $(.TARGET) + +lib2.a : $(LIB2OBJS) + rm -f $(.TARGET) + ar cr $(.TARGET) $(.ALLSRC) + ... + ranlib $(.TARGET) +.DE +.Ix 0 ref variable local .TARGET +.Ix 0 ref variable local .ALLSRC +This would save both +.DS +ranlib $(.TARGET) +.DE +commands until the end, when they would run one after the other +(using the correct value for the +.CW .TARGET +variable, of course). +.LP +Commands saved in this manner are only executed if PMake manages to +re-create everything without an error. +.xH 2 Target Attributes +.LP +PMake allows you to give attributes to targets by means of special +sources. Like everything else PMake uses, these sources begin with a +period and are made up of all upper-case letters. There are various +reasons for using them, and I will try to give examples for most of +them. Others you'll have to find uses for yourself. Think of it as ``an +exercise for the reader.'' By placing one (or more) of these as a source on a +dependency line, you are ``marking the target(s) with that +attribute.'' That's just the way I phrase it, so you know. +.LP +Any attributes given as sources for a transformation rule are applied +to the target of the transformation rule when the rule is applied. +.Ix 0 def attributes +.Ix 0 ref source +.Ix 0 ref target +.nr pw 12 +.IP .DONTCARE \n(pw +.Ix 0 def attributes .DONTCARE +.Ix 0 def .DONTCARE +If a target is marked with this attribute and PMake can't figure out +how to create it, it will ignore this fact and assume the file isn't +really needed or actually exists and PMake just can't find it. This may prove +wrong, but the error will be noted later on, not when PMake tries to create +the target so marked. This attribute also prevents PMake from +attempting to touch the target if it is given the +.B \-t +flag. +.Ix 0 ref flags -t +.IP .EXEC \n(pw +.Ix 0 def attributes .EXEC +.Ix 0 def .EXEC +This attribute causes its shell script to be executed while having no +effect on targets that depend on it. This makes the target into a sort +of subroutine. An example. Say you have some LISP files that need to +be compiled and loaded into a LISP process. To do this, you echo LISP +commands into a file and execute a LISP with this file as its input +when everything's done. Say also that you have to load other files +from another system before you can compile your files and further, +that you don't want to go through the loading and dumping unless one +of +.I your +files has changed. Your makefile might look a little bit +like this (remember, this is an educational example, and don't worry +about the +.CW COMPILE +rule, all will soon become clear, grasshopper): +.DS +system : init a.fasl b.fasl c.fasl + for i in $(.ALLSRC); + do + echo -n '(load "' >> input + echo -n ${i} >> input + echo '")' >> input + done + echo '(dump "$(.TARGET)")' >> input + lisp < input + +a.fasl : a.l init COMPILE +b.fasl : b.l init COMPILE +c.fasl : c.l init COMPILE +COMPILE : .USE + echo '(compile "$(.ALLSRC)")' >> input +init : .EXEC + echo '(load-system)' > input +.DE +.Ix 0 ref .USE +.Ix 0 ref attributes .USE +.Ix 0 ref variable local .ALLSRC +.IP "\&" +.CW .EXEC +sources, don't appear in the local variables of targets that depend on +them (nor are they touched if PMake is given the +.B \-t +flag). +.Ix 0 ref flags -t +Note that all the rules, not just that for +.CW system , +include +.CW init +as a source. This is because none of the other targets can be made +until +.CW init +has been made, thus they depend on it. +.IP .EXPORT \n(pw +.Ix 0 def attributes .EXPORT +.Ix 0 def .EXPORT +This is used to mark those targets whose creation should be sent to +another machine if at all possible. This may be used by some +exportation schemes if the exportation is expensive. You should ask +your system administrator if it is necessary. +.IP .EXPORTSAME \n(pw +.Ix 0 def attributes .EXPORTSAME +.Ix 0 def .EXPORTSAME +Tells the export system that the job should be exported to a machine +of the same architecture as the current one. Certain operations (e.g. +running text through +.CW nroff ) +can be performed the same on any architecture (CPU and +operating system type), while others (e.g. compiling a program with +.CW cc ) +must be performed on a machine with the same architecture. Not all +export systems will support this attribute. +.IP .IGNORE \n(pw +.Ix 0 def attributes .IGNORE +.Ix 0 def .IGNORE attribute +Giving a target the +.CW .IGNORE +attribute causes PMake to ignore errors from any of the target's commands, as +if they all had `\-' before them. +.IP .INVISIBLE \n(pw +.Ix 0 def attributes .INVISIBLE +.Ix 0 def .INVISIBLE +This allows you to specify one target as a source for another without +the one affecting the other's local variables. Useful if, say, you +have a makefile that creates two programs, one of which is used to +create the other, so it must exist before the other is created. You +could say +.DS +prog1 : $(PROG1OBJS) prog2 MAKEINSTALL +prog2 : $(PROG2OBJS) .INVISIBLE MAKEINSTALL +.DE +where +.CW MAKEINSTALL +is some complex .USE rule (see below) that depends on the +.Ix 0 ref .USE +.CW .ALLSRC +variable containing the right things. Without the +.CW .INVISIBLE +attribute for +.CW prog2 , +the +.CW MAKEINSTALL +rule couldn't be applied. This is not as useful as it should be, and +the semantics may change (or the whole thing go away) in the +not-too-distant future. +.IP .JOIN \n(pw +.Ix 0 def attributes .JOIN +.Ix 0 def .JOIN +This is another way to avoid performing some operations in parallel +while permitting everything else to be done so. Specifically it +forces the target's shell script to be executed only if one or more of the +sources was out-of-date. In addition, the target's name, +in both its +.CW .TARGET +variable and all the local variables of any target that depends on it, +is replaced by the value of its +.CW .ALLSRC +variable. +As an example, suppose you have a program that has four libraries that +compile in the same directory along with, and at the same time as, the +program. You again have the problem with +.CW ranlib +that I mentioned earlier, only this time it's more severe: you +can't just put the ranlib off to the end since the program +will need those libraries before it can be re-created. You can do +something like this: +.DS +program : $(OBJS) libraries + cc -o $(.TARGET) $(.ALLSRC) + +libraries : lib1.a lib2.a lib3.a lib4.a .JOIN + ranlib $(.OODATE) +.DE +.Ix 0 ref variable local .TARGET +.Ix 0 ref variable local .ALLSRC +.Ix 0 ref variable local .OODATE +.Ix 0 ref .TARGET +.Ix 0 ref .ALLSRC +.Ix 0 ref .OODATE +In this case, PMake will re-create the +.CW $(OBJS) +as necessary, along with +.CW lib1.a , +.CW lib2.a , +.CW lib3.a +and +.CW lib4.a . +It will then execute +.CW ranlib +on any library that was changed and set +.CW program 's +.CW .ALLSRC +variable to contain what's in +.CW $(OBJS) +followed by +.CW "lib1.a lib2.a lib3.a lib4.a" .'' `` +In case you're wondering, it's called +.CW .JOIN +because it joins together different threads of the ``input graph'' at +the target marked with the attribute. +Another aspect of the .JOIN attribute is it keeps the target from +being created if the +.B \-t +flag was given. +.Ix 0 ref flags -t +.IP .MAKE \n(pw +.Ix 0 def attributes .MAKE +.Ix 0 def .MAKE +The +.CW .MAKE +attribute marks its target as being a recursive invocation of PMake. +This forces PMake to execute the script associated with the target (if +it's out-of-date) even if you gave the +.B \-n +or +.B \-t +flag. By doing this, you can start at the top of a system and type +.DS +pmake -n +.DE +and have it descend the directory tree (if your makefiles are set up +correctly), printing what it would have executed if you hadn't +included the +.B \-n +flag. +.IP .NOEXPORT \n(pw +.Ix 0 def attributes .NOEXPORT +.Ix 0 def .NOEXPORT attribute +If possible, PMake will attempt to export the creation of all targets to +another machine (this depends on how PMake was configured). Sometimes, +the creation is so simple, it is pointless to send it to another +machine. If you give the target the +.CW .NOEXPORT +attribute, it will be run locally, even if you've given PMake the +.B "\-L 0" +flag. +.IP .NOTMAIN \n(pw +.Ix 0 def attributes .NOTMAIN +.Ix 0 def .NOTMAIN +Normally, if you do not specify a target to make in any other way, +PMake will take the first target on the first dependency line of a +makefile as the target to create. That target is known as the ``Main +Target'' and is labeled as such if you print the dependencies out +using the +.B \-p +flag. +.Ix 0 ref flags -p +Giving a target this attribute tells PMake that the target is +definitely +.I not +the Main Target. +This allows you to place targets in an included makefile and +have PMake create something else by default. +.IP .PRECIOUS \n(pw +.Ix 0 def attributes .PRECIOUS +.Ix 0 def .PRECIOUS attribute +When PMake is interrupted (you type control-C at the keyboard), it +will attempt to clean up after itself by removing any half-made +targets. If a target has the +.CW .PRECIOUS +attribute, however, PMake will leave it alone. An additional side +effect of the `::' operator is to mark the targets as +.CW .PRECIOUS . +.Ix 0 ref operator double-colon +.Ix 0 ref :: +.IP .SILENT \n(pw +.Ix 0 def attributes .SILENT +.Ix 0 def .SILENT attribute +Marking a target with this attribute keeps its commands from being +printed when they're executed, just as if they had an `@' in front of them. +.IP .USE \n(pw +.Ix 0 def attributes .USE +.Ix 0 def .USE +By giving a target this attribute, you turn it into PMake's equivalent +of a macro. When the target is used as a source for another target, +the other target acquires the commands, sources and attributes (except +.CW .USE ) +of the source. +If the target already has commands, the +.CW .USE +target's commands are added to the end. If more than one .USE-marked +source is given to a target, the rules are applied sequentially. +.IP "\&" \n(pw +The typical .USE rule (as I call them) will use the sources of the +target to which it is applied (as stored in the +.CW .ALLSRC +variable for the target) as its ``arguments,'' if you will. +For example, you probably noticed that the commands for creating +.CW lib1.a +and +.CW lib2.a +in the example in section 3.3 +.Rm 5 3.3 +were exactly the same. You can use the +.CW .USE +attribute to eliminate the repetition, like so: +.DS +lib1.a : $(LIB1OBJS) MAKELIB +lib2.a : $(LIB2OBJS) MAKELIB + +MAKELIB : .USE + rm -f $(.TARGET) + ar cr $(.TARGET) $(.ALLSRC) + ... + ranlib $(.TARGET) +.DE +.Ix 0 ref variable local .TARGET +.Ix 0 ref variable local .ALLSRC +.IP "\&" \n(pw +Several system makefiles (not to be confused with The System Makefile) +make use of these .USE rules to make your +life easier (they're in the default, system makefile directory...take a look). +Note that the .USE rule source itself +.CW MAKELIB ) ( +does not appear in any of the targets's local variables. +There is no limit to the number of times I could use the +.CW MAKELIB +rule. If there were more libraries, I could continue with +.CW "lib3.a : $(LIB3OBJS) MAKELIB" '' `` +and so on and so forth. +.xH 2 Special Targets +.LP +As there were in Make, so there are certain targets that have special +meaning to PMake. When you use one on a dependency line, it is the +only target that may appear on the left-hand-side of the operator. +.Ix 0 ref target +.Ix 0 ref operator +As for the attributes and variables, all the special targets +begin with a period and consist of upper-case letters only. +I won't describe them all in detail because some of them are rather +complex and I'll describe them in more detail than you'll want in +chapter 4. +The targets are as follows: +.nr pw 10 +.IP .BEGIN \n(pw +.Ix 0 def .BEGIN +Any commands attached to this target are executed before anything else +is done. You can use it for any initialization that needs doing. +.IP .DEFAULT \n(pw +.Ix 0 def .DEFAULT +This is sort of a .USE rule for any target (that was used only as a +source) that PMake can't figure out any other way to create. It's only +``sort of'' a .USE rule because only the shell script attached to the +.CW .DEFAULT +target is used. The +.CW .IMPSRC +variable of a target that inherits +.CW .DEFAULT 's +commands is set to the target's own name. +.Ix 0 ref .IMPSRC +.Ix 0 ref variable local .IMPSRC +.IP .END \n(pw +.Ix 0 def .END +This serves a function similar to +.CW .BEGIN , +in that commands attached to it are executed once everything has been +re-created (so long as no errors occurred). It also serves the extra +function of being a place on which PMake can hang commands you put off +to the end. Thus the script for this target will be executed before +any of the commands you save with the ``.\|.\|.''. +.Ix 0 ref ... +.IP .EXPORT \n(pw +The sources for this target are passed to the exportation system compiled +into PMake. Some systems will use these sources to configure +themselves. You should ask your system administrator about this. +.IP .IGNORE \n(pw +.Ix 0 def .IGNORE target +.Ix 0 ref .IGNORE attribute +.Ix 0 ref attributes .IGNORE +This target marks each of its sources with the +.CW .IGNORE +attribute. If you don't give it any sources, then it is like +giving the +.B \-i +flag when you invoke PMake \*- errors are ignored for all commands. +.Ix 0 ref flags -i +.IP .INCLUDES \n(pw +.Ix 0 def .INCLUDES target +.Ix 0 def variable global .INCLUDES +.Ix 0 def .INCLUDES variable +The sources for this target are taken to be suffixes that indicate a +file that can be included in a program source file. +The suffix must have already been declared with +.CW .SUFFIXES +(see below). +Any suffix so marked will have the directories on its search path +(see +.CW .PATH , +below) placed in the +.CW .INCLUDES +variable, each preceded by a +.B \-I +flag. This variable can then be used as an argument for the compiler +in the normal fashion. The +.CW .h +suffix is already marked in this way in the system makefile. +.Ix 0 ref makefile system +E.g. if you have +.DS +\&.SUFFIXES : .bitmap +\&.PATH.bitmap : /usr/local/X/lib/bitmaps +\&.INCLUDES : .bitmap +.DE +PMake will place +.CW "-I/usr/local/X/lib/bitmaps" '' `` +in the +.CW .INCLUDES +variable and you can then say +.DS +cc $(.INCLUDES) -c xprogram.c +.DE +(Note: the +.CW .INCLUDES +variable is not actually filled in until the entire makefile has been read.) +.IP .INTERRUPT \n(pw +.Ix 0 def .INTERRUPT +When PMake is interrupted, +it will execute the commands in the script for this target, if it +exists. +.IP .LIBS \n(pw +.Ix 0 def .LIBS target +.Ix 0 def .LIBS variable +.Ix 0 def variable global .LIBS +This does for libraries what +.CW .INCLUDES +does for include files, except the flag used is +.B \-L , +as required by those linkers that allow you to tell them where to find +libraries. The variable used is +.CW .LIBS . +Be forewarned that PMake may not have been compiled to do this if the +linker on your system doesn't accept the +.B \-L +flag, though the +.CW .LIBS +variable will always be defined once the makefile has been read. +.IP .MAIN \n(pw +.Ix 0 def .MAIN +If you didn't give a target (or targets) to create when you invoked +PMake, it will take the sources of this target as the targets to +create. +.IP .MAKEFLAGS \n(pw +.Ix 0 def .MAKEFLAGS target +This target provides a way for you to always specify flags for PMake +when the makefile is used. The flags are just as they would be typed +to the shell (except you can't use shell variables unless they're in +the environment), +though the +.B \-f +and +.B \-r +flags have no effect. +.IP .NULL \n(pw +.Ix 0 def .NULL +.Ix 0 ref suffix null +.Ix 0 ref "null suffix" +This allows you to specify what suffix PMake should pretend a file has +if, in fact, it has no known suffix. Only one suffix may be so +designated. The last source on the dependency line is the suffix that +is used (you should, however, only give one suffix.\|.\|.). +.IP .PATH \n(pw +.Ix 0 def .PATH +If you give sources for this target, PMake will take them as +directories in which to search for files it cannot find in the current +directory. If you give no sources, it will clear out any directories +added to the search path before. Since the effects of this all get +very complex, I'll leave it til chapter four to give you a complete +explanation. +.IP .PATH\fIsuffix\fP \n(pw +.Ix 0 ref .PATH +This does a similar thing to +.CW .PATH , +but it does it only for files with the given suffix. The suffix must +have been defined already. Look at +.B "Search Paths" +(section 4.1) +.Rm 6 4.1 +for more information. +.IP .PRECIOUS \n(pw +.Ix 0 def .PRECIOUS target +.Ix 0 ref .PRECIOUS attribute +.Ix 0 ref attributes .PRECIOUS +Similar to +.CW .IGNORE , +this gives the +.CW .PRECIOUS +attribute to each source on the dependency line, unless there are no +sources, in which case the +.CW .PRECIOUS +attribute is given to every target in the file. +.IP .RECURSIVE \n(pw +.Ix 0 def .RECURSIVE +.Ix 0 ref attributes .MAKE +.Ix 0 ref .MAKE +This target applies the +.CW .MAKE +attribute to all its sources. It does nothing if you don't give it any sources. +.IP .SHELL \n(pw +.Ix 0 def .SHELL +PMake is not constrained to only using the Bourne shell to execute +the commands you put in the makefile. You can tell it some other shell +to use with this target. Check out +.B "A Shell is a Shell is a Shell" +(section 4.4) +.Rm 7 4.4 +for more information. +.IP .SILENT \n(pw +.Ix 0 def .SILENT target +.Ix 0 ref .SILENT attribute +.Ix 0 ref attributes .SILENT +When you use +.CW .SILENT +as a target, it applies the +.CW .SILENT +attribute to each of its sources. If there are no sources on the +dependency line, then it is as if you gave PMake the +.B \-s +flag and no commands will be echoed. +.IP .SUFFIXES \n(pw +.Ix 0 def .SUFFIXES +This is used to give new file suffixes for PMake to handle. Each +source is a suffix PMake should recognize. If you give a +.CW .SUFFIXES +dependency line with no sources, PMake will forget about all the +suffixes it knew (this also nukes the null suffix). +For those targets that need to have suffixes defined, this is how you do it. +.LP +In addition to these targets, a line of the form +.DS +\fIattribute\fP : \fIsources\fP +.DE +applies the +.I attribute +to all the targets listed as +.I sources . +.xH 2 Modifying Variable Expansion +.LP +.Ix 0 def variable expansion modified +.Ix 0 ref variable expansion +.Ix 0 def variable modifiers +Variables need not always be expanded verbatim. PMake defines several +modifiers that may be applied to a variable's value before it is +expanded. You apply a modifier by placing it after the variable name +with a colon between the two, like so: +.DS +${\fIVARIABLE\fP:\fImodifier\fP} +.DE +Each modifier is a single character followed by something specific to +the modifier itself. +You may apply as many modifiers as you want \*- each one is applied to +the result of the previous and is separated from the previous by +another colon. +.LP +There are seven ways to modify a variable's expansion, most of which +come from the C shell variable modification characters: +.RS +.IP "M\fIpattern\fP" +.Ix 0 def :M +.Ix 0 def modifier match +This is used to select only those words (a word is a series of +characters that are neither spaces nor tabs) that match the given +.I pattern . +The pattern is a wildcard pattern like that used by the shell, where +.CW * +means 0 or more characters of any sort; +.CW ? +is any single character; +.CW [abcd] +matches any single character that is either `a', `b', `c' or `d' +(there may be any number of characters between the brackets); +.CW [0-9] +matches any single character that is between `0' and `9' (i.e. any +digit. This form may be freely mixed with the other bracket form), and +`\\' is used to escape any of the characters `*', `?', `[' or `:', +leaving them as regular characters to match themselves in a word. +For example, the system makefile +.CW +uses +.CW "$(CFLAGS:M-[ID]*)" '' `` +to extract all the +.CW \-I +and +.CW \-D +flags that would be passed to the C compiler. This allows it to +properly locate include files and generate the correct dependencies. +.IP "N\fIpattern\fP" +.Ix 0 def :N +.Ix 0 def modifier nomatch +This is identical to +.CW :M +except it substitutes all words that don't match the given pattern. +.IP "S/\fIsearch-string\fP/\fIreplacement-string\fP/[g]" +.Ix 0 def :S +.Ix 0 def modifier substitute +Causes the first occurrence of +.I search-string +in the variable to be replaced by +.I replacement-string , +unless the +.CW g +flag is given at the end, in which case all occurrences of the string +are replaced. The substitution is performed on each word in the +variable in turn. If +.I search-string +begins with a +.CW ^ , +the string must match starting at the beginning of the word. If +.I search-string +ends with a +.CW $ , +the string must match to the end of the word (these two may be +combined to force an exact match). If a backslash precedes these two +characters, however, they lose their special meaning. Variable +expansion also occurs in the normal fashion inside both the +.I search-string +and the +.I replacement-string , +.B except +that a backslash is used to prevent the expansion of a +.CW $ , +not another dollar sign, as is usual. +Note that +.I search-string +is just a string, not a pattern, so none of the usual +regular-expression/wildcard characters have any special meaning save +.CW ^ +and +.CW $ . +In the replacement string, +the +.CW & +character is replaced by the +.I search-string +unless it is preceded by a backslash. +You are allowed to use any character except +colon or exclamation point to separate the two strings. This so-called +delimiter character may be placed in either string by preceding it +with a backslash. +.IP T +.Ix 0 def :T +.Ix 0 def modifier tail +Replaces each word in the variable expansion by its last +component (its ``tail''). For example, given +.DS +OBJS = ../lib/a.o b /usr/lib/libm.a +TAILS = $(OBJS:T) +.DE +the variable +.CW TAILS +would expand to +.CW "a.o b libm.a" .'' `` +.IP H +.Ix 0 def :H +.Ix 0 def modifier head +This is similar to +.CW :T , +except that every word is replaced by everything but the tail (the +``head''). Using the same definition of +.CW OBJS , +the string +.CW "$(OBJS:H)" '' `` +would expand to +.CW "../lib /usr/lib" .'' `` +Note that the final slash on the heads is removed and +anything without a head is replaced by the empty string. +.IP E +.Ix 0 def :E +.Ix 0 def modifier extension +.Ix 0 def modifier suffix +.Ix 0 ref suffix "variable modifier" +.CW :E +replaces each word by its suffix (``extension''). So +.CW "$(OBJS:E)" '' `` +would give you +.CW ".o .a" .'' `` +.IP R +.Ix 0 def :R +.Ix 0 def modifier root +.Ix 0 def modifier base +This replaces each word by everything but the suffix (the ``root'' of +the word). +.CW "$(OBJS:R)" '' `` +expands to `` +.CW "../lib/a b /usr/lib/libm" .'' +.RE +.LP +In addition, the System V style of substitution is also supported. +This looks like: +.DS +$(\fIVARIABLE\fP:\fIsearch-string\fP=\fIreplacement\fP) +.DE +It must be the last modifier in the chain. The search is anchored at +the end of each word, so only suffixes or whole words may be replaced. +.xH 2 More on Debugging +.xH 2 More Exercises +.IP (3.1) +You've got a set programs, each of which is created from its own +assembly-language source file (suffix +.CW .asm ). +Each program can be assembled into two versions, one with error-checking +code assembled in and one without. You could assemble them into files +with different suffixes +.CW .eobj \& ( +and +.CW .obj , +for instance), but your linker only understands files that end in +.CW .obj . +To top it all off, the final executables +.I must +have the suffix +.CW .exe . +How can you still use transformation rules to make your life easier +(Hint: assume the error-checking versions have +.CW ec +tacked onto their prefix)? +.IP (3.2) +Assume, for a moment or two, you want to perform a sort of +``indirection'' by placing the name of a variable into another one, +then you want to get the value of the first by expanding the second +somehow. Unfortunately, PMake doesn't allow constructs like +.DS I +$($(FOO)) +.DE +What do you do? Hint: no further variable expansion is performed after +modifiers are applied, thus if you cause a $ to occur in the +expansion, that's what will be in the result. +.xH 1 PMake for Gods +.LP +This chapter is devoted to those facilities in PMake that allow you to +do a great deal in a makefile with very little work, as well as do +some things you couldn't do in Make without a great deal of work (and +perhaps the use of other programs). The problem with these features, +is they must be handled with care, or you will end up with a mess. +.LP +Once more, I assume a greater familiarity with +.UX +or Sprite than I did in the previous two chapters. +.xH 2 Search Paths +.Rd 6 +.LP +PMake supports the dispersal of files into multiple directories by +allowing you to specify places to look for sources with +.CW .PATH +targets in the makefile. The directories you give as sources for these +targets make up a ``search path.'' Only those files used exclusively +as sources are actually sought on a search path, the assumption being +that anything listed as a target in the makefile can be created by the +makefile and thus should be in the current directory. +.LP +There are two types of search paths +in PMake: one is used for all types of files (including included +makefiles) and is specified with a plain +.CW .PATH +target (e.g. +.CW ".PATH : RCS" ''), `` +while the other is specific to a certain type of file, as indicated by +the file's suffix. A specific search path is indicated by immediately following +the +.CW .PATH +with the suffix of the file. For instance +.DS +\&.PATH.h : /sprite/lib/include /sprite/att/lib/include +.DE +would tell PMake to look in the directories +.CW /sprite/lib/include +and +.CW /sprite/att/lib/include +for any files whose suffix is +.CW .h . +.LP +The current directory is always consulted first to see if a file +exists. Only if it cannot be found there are the directories in the +specific search path, followed by those in the general search path, +consulted. +.LP +A search path is also used when expanding wildcard characters. If the +pattern has a recognizable suffix on it, the path for that suffix will +be used for the expansion. Otherwise the default search path is employed. +.LP +When a file is found in some directory other than the current one, all +local variables that would have contained the target's name +.CW .ALLSRC , ( +and +.CW .IMPSRC ) +will instead contain the path to the file, as found by PMake. +Thus if you have a file +.CW ../lib/mumble.c +and a makefile +.DS +\&.PATH.c : ../lib +mumble : mumble.c + $(CC) -o $(.TARGET) $(.ALLSRC) +.DE +the command executed to create +.CW mumble +would be +.CW "cc -o mumble ../lib/mumble.c" .'' `` +(As an aside, the command in this case isn't strictly necessary, since +it will be found using transformation rules if it isn't given. This is because +.CW .out +is the null suffix by default and a transformation exists from +.CW .c +to +.CW .out . +Just thought I'd throw that in.) +.LP +If a file exists in two directories on the same search path, the file +in the first directory on the path will be the one PMake uses. So if +you have a large system spread over many directories, it would behoove +you to follow a naming convention that avoids such conflicts. +.LP +Something you should know about the way search paths are implemented +is that each directory is read, and its contents cached, exactly once +\&\*- when it is first encountered \*- so any changes to the +directories while PMake is running will not be noted when searching +for implicit sources, nor will they be found when PMake attempts to +discover when the file was last modified, unless the file was created in the +current directory. While people have suggested that PMake should read +the directories each time, my experience suggests that the caching seldom +causes problems. In addition, not caching the directories slows things +down enormously because of PMake's attempts to apply transformation +rules through non-existent files \*- the number of extra file-system +searches is truly staggering, especially if many files without +suffixes are used and the null suffix isn't changed from +.CW .out . +.xH 2 Archives and Libraries +.LP +.UX +and Sprite allow you to merge files into an archive using the +.CW ar +command. Further, if the files are relocatable object files, you can +run +.CW ranlib +on the archive and get yourself a library that you can link into any +program you want. The main problem with archives is they double the +space you need to store the archived files, since there's one copy in +the archive and one copy out by itself. The problem with libraries is +you usually think of them as +.CW -lm +rather than +.CW /usr/lib/libm.a +and the linker thinks they're out-of-date if you so much as look at +them. +.LP +PMake solves the problem with archives by allowing you to tell it to +examine the files in the archives (so you can remove the individual +files without having to regenerate them later). To handle the problem +with libraries, PMake adds an additional way of deciding if a library +is out-of-date: +.IP \(bu 2 +If the table of contents is older than the library, or is missing, the +library is out-of-date. +.LP +A library is any target that looks like +.CW \-l name'' `` +or that ends in a suffix that was marked as a library using the +.CW .LIBS +target. +.CW .a +is so marked in the system makefile. +.LP +Members of an archive are specified as +``\fIarchive\fP(\fImember\fP[ \fImember\fP...])''. +Thus +.CW libdix.a(window.o) '' ``' +specifies the file +.CW window.o +in the archive +.CW libdix.a . +You may also use wildcards to specify the members of the archive. Just +remember that most the wildcard characters will only find +.I existing +files. +.LP +A file that is a member of an archive is treated specially. If the +file doesn't exist, but it is in the archive, the modification time +recorded in the archive is used for the file when determining if the +file is out-of-date. When figuring out how to make an archived member target +(not the file itself, but the file in the archive \*- the +\fIarchive\fP(\fImember\fP) target), special care is +taken with the transformation rules, as follows: +.IP \(bu 2 +\&\fIarchive\fP(\fImember\fP) is made to depend on \fImember\fP. +.IP \(bu 2 +The transformation from the \fImember\fP's suffix to the +\fIarchive\fP's suffix is applied to the \fIarchive\fP(\fImember\fP) target. +.IP \(bu 2 +The \fIarchive\fP(\fImember\fP)'s +.CW .TARGET +variable is set to the name of the \fImember\fP if \fImember\fP is +actually a target, or the path to the member file if \fImember\fP is +only a source. +.IP \(bu 2 +The +.CW .ARCHIVE +variable for the \fIarchive\fP(\fImember\fP) target is set to the name +of the \fIarchive\fP. +.Ix 0 def variable local .ARCHIVE +.Ix 0 def .ARCHIVE +.IP \(bu 2 +The +.CW .MEMBER +variable is set to the actual string inside the parentheses. In most +cases, this will be the same as the +.CW .TARGET +variable. +.Ix 0 def variable local .MEMBER +.Ix 0 def .MEMBER +.IP \(bu 2 +The \fIarchive\fP(\fImember\fP)'s place in the local variables of the +targets that depend on it is taken by the value of its +.CW .TARGET +variable. +.LP +Thus, a program library could be created with the following makefile: +.DS +\&.o.a : + ... + rm -f $(.TARGET:T) +OBJS = obj1.o obj2.o obj3.o +libprog.a : libprog.a($(OBJS)) + ar cru $(.TARGET) $(.OODATE) + ranlib $(.TARGET) +.DE +This will cause the three object files to be compiled (if the +corresponding source files were modified after the object file or, if +that doesn't exist, the archived object file), the out-of-date ones +archived in +.CW libprog.a , +a table of contents placed in the archive and the newly-archived +object files to be removed. +.LP +All this is used in the +.CW makelib.mk +system makefile to create a single library with ease. This makefile +looks like this: +.DS +.SM +# +# Rules for making libraries. The object files that make up the library +# are removed once they are archived. +# +# To make several libraries in parallel, you should define the variable +# "many_libraries". This will serialize the invocations of ranlib. +# +# To use, do something like this: +# +# OBJECTS = +# +# fish.a: fish.a($(OBJECTS)) MAKELIB +# +# + +#ifndef _MAKELIB_MK +_MAKELIB_MK = + +#include + +\&.po.a .o.a : + ... + rm -f $(.MEMBER) + +ARFLAGS ?= crl + +# +# Re-archive the out-of-date members and recreate the library's table of +# contents using ranlib. If many_libraries is defined, put the ranlib +# off til the end so many libraries can be made at once. +# +MAKELIB : .USE .PRECIOUS + ar $(ARFLAGS) $(.TARGET) $(.OODATE) +#ifndef no_ranlib +# ifdef many_libraries + ... +# endif /* many_libraries */ + ranlib $(.TARGET) +#endif /* no_ranlib */ + +#endif /* _MAKELIB_MK */ +.DE +.xH 2 On the Condition... +.Rd 1 +.LP +Like the C compiler before it, PMake allows you to configure the makefile, +based on the current environment, using conditional statements. A +conditional looks like this: +.DS +#if \fIboolean expression\fP +\fIlines\fP +#elif \fIanother boolean expression\fP +\fImore lines\fP +#else +\fIstill more lines\fP +#endif +.DE +They may be nested to a maximum depth of 30 and may occur anywhere +(except in a comment, of course). The +.CW # '' `` +must the very first character on the line. +.LP +Each +.I "boolean expression" +is made up of terms that look like function calls, the standard C +boolean operators +.CW && , +.CW || , +and +.CW ! , +and the standard relational operators +.CW == , +.CW != , +.CW > , +.CW >= , +.CW < , +and +.CW <= , +with +.CW == +and +.CW != +being overloaded to allow string comparisons as well. +.CW && +represents logical AND; +.CW || +is logical OR and +.CW ! +is logical NOT. The arithmetic and string operators take precedence +over all three of these operators, while NOT takes precedence over +AND, which takes precedence over OR. This precedence may be +overridden with parentheses, and an expression may be parenthesized to +your heart's content. Each term looks like a call on one of four +functions: +.nr pw 9 +.Ix 0 def make +.Ix 0 def conditional make +.Ix 0 def if make +.IP make \n(pw +The syntax is +.CW make( \fItarget\fP\c +.CW ) +where +.I target +is a target in the makefile. This is true if the given target was +specified on the command line, or as the source for a +.CW .MAIN +target (note that the sources for +.CW .MAIN +are only used if no targets were given on the command line). +.IP defined \n(pw +.Ix 0 def defined +.Ix 0 def conditional defined +.Ix 0 def if defined +The syntax is +.CW defined( \fIvariable\fP\c +.CW ) +and is true if +.I variable +is defined. Certain variables are defined in the system makefile that +identify the system on which PMake is being run. +.IP exists \n(pw +.Ix 0 def exists +.Ix 0 def conditional exists +.Ix 0 def if exists +The syntax is +.CW exists( \fIfile\fP\c +.CW ) +and is true if the file can be found on the global search path +(i.e. that defined by +.CW .PATH +targets, not by +.CW .PATH \fIsuffix\fP +targets). +.IP empty \n(pw +.Ix 0 def empty +.Ix 0 def conditional empty +.Ix 0 def if empty +This syntax is much like the others, except the string inside the +parentheses is of the same form as you would put between parentheses +when expanding a variable, complete with modifiers and everything. The +function returns true if the resulting string is empty (NOTE: an undefined +variable in this context will cause at the very least a warning +message about a malformed conditional, and at the worst will cause the +process to stop once it has read the makefile. If you want to check +for a variable being defined or empty, use the expression +.CW !defined( \fIvar\fP\c `` +.CW ") || empty(" \fIvar\fP\c +.CW ) '' +as the definition of +.CW || +will prevent the +.CW empty() +from being evaluated and causing an error, if the variable is +undefined). This can be used to see if a variable contains a given +word, for example: +.DS +#if !empty(\fIvar\fP:M\fIword\fP) +.DE +.LP +The arithmetic and string operators may only be used to test the value +of a variable. The lefthand side must contain the variable expansion, +while the righthand side contains either a string, enclosed in +double-quotes, or a number. The standard C numeric conventions (except +for specifying an octal number) apply to both sides. E.g. +.DS +#if $(OS) == 4.3 + +#if $(MACHINE) == "sun3" + +#if $(LOAD_ADDR) < 0xc000 +.DE +are all valid conditionals. In addition, the numeric value of a +variable can be tested as a boolean as follows: +.DS +#if $(LOAD) +.DE +would see if +.CW LOAD +contains a non-zero value and +.DS +#if !$(LOAD) +.DE +would test if +.CW LOAD +contains a zero value. +.LP +In addition to the bare +.CW #if ,'' `` +there are other forms that apply one of the first two functions to each +term. They are as follows: +.DS + ifdef \fRdefined\fP + ifndef \fR!defined\fP + ifmake \fRmake\fP + ifnmake \fR!make\fP +.DE +There are also the ``else if'' forms: +.CW elif , +.CW elifdef , +.CW elifndef , +.CW elifmake , +and +.CW elifnmake . +.LP +For instance, if you wish to create two versions of a program, one of which +is optimized (the production version) and the other of which is for debugging +(has symbols for dbx), you have two choices: you can create two +makefiles, one of which uses the +.CW \-g +flag for the compilation, while the other uses the +.CW \-O +flag, or you can use another target (call it +.CW debug ) +to create the debug version. The construct below will take care of +this for you. I have also made it so defining the variable +.CW DEBUG +(say with +.CW "pmake -D DEBUG" ) +will also cause the debug version to be made. +.DS +#if defined(DEBUG) || make(debug) +CFLAGS += -g +#else +CFLAGS += -O +#endif +.DE +There are, of course, problems with this approach. The most glaring +annoyance is that if you want to go from making a debug version to +making a production version, you have to remove all the object files, +or you will get some optimized and some debug versions in the same +program. Another annoyance is you have to be careful not to make two +targets that ``conflict'' because of some conditionals in the +makefile. For instance +.DS +#if make(print) +FORMATTER = ditroff -Plaser_printer +#endif +#if make(draft) +FORMATTER = nroff -Pdot_matrix_printer +#endif +.DE +would wreak havoc if you tried +.CW "pmake draft print" '' `` +since you would use the same formatter for each target. As I said, +this all gets somewhat complicated. +.xH 2 A Shell is a Shell is a Shell +.Rd 7 +.LP +In normal operation, the Bourne Shell (better known as +.CW sh '') `` +is used to execute the commands to re-create targets. PMake also allows you +to specify a different shell for it to use when executing these +commands. There are several things PMake must know about the shell you +wish to use. These things are specified as the sources for the +.CW .SHELL +.Ix 0 ref .SHELL +.Ix 0 ref target .SHELL +target by keyword, as follows: +.IP "\fBpath=\fP\fIpath\fP" +PMake needs to know where the shell actually resides, so it can +execute it. If you specify this and nothing else, PMake will use the +last component of the path and look in its table of the shells it +knows and use the specification it finds, if any. Use this if you just +want to use a different version of the Bourne or C Shell (yes, PMake knows +how to use the C Shell too). +.IP "\fBname=\fP\fIname\fP" +This is the name by which the shell is to be known. It is a single +word and, if no other keywords are specified (other than +.B path ), +it is the name by which PMake attempts to find a specification for +it (as mentioned above). You can use this if you would just rather use +the C Shell than the Bourne Shell +.CW ".SHELL: name=csh" '' (`` +will do it). +.IP "\fBquiet=\fP\fIecho-off command\fP" +As mentioned before, PMake actually controls whether commands are +printed by introducing commands into the shell's input stream. This +keyword, and the next two, control what those commands are. The +.B quiet +keyword is the command used to turn echoing off. Once it is turned +off, echoing is expected to remain off until the echo-on command is given. +.IP "\fBecho=\fP\fIecho-on command\fP" +The command PMake should give to turn echoing back on again. +.IP "\fBfilter=\fP\fIprinted echo-off command\fP" +Many shells will echo the echo-off command when it is given. This +keyword tells PMake in what format the shell actually prints the +echo-off command. Wherever PMake sees this string in the shell's +output, it will delete it and any following whitespace, up to and +including the next newline. See the example at the end of this section +for more details. +.IP "\fBechoFlag=\fP\fIflag to turn echoing on\fP" +Unless a target has been marked +.CW .SILENT , +PMake wants to start the shell running with echoing on. To do this, it +passes this flag to the shell as one of its arguments. If either this +or the next flag begins with a `\-', the flags will be passed to the +shell as separate arguments. Otherwise, the two will be concatenated +(if they are used at the same time, of course). +.IP "\fBerrFlag=\fP\fIflag to turn error checking on\fP" +Likewise, unless a target is marked +.CW .IGNORE , +PMake wishes error-checking to be on from the very start. To this end, +it will pass this flag to the shell as an argument. The same rules for +an initial `\-' apply as for the +.B echoFlag . +.IP "\fBcheck=\fP\fIcommand to turn error checking on\fP" +Just as for echo-control, error-control is achieved by inserting +commands into the shell's input stream. This is the command to make +the shell check for errors. It also serves another purpose if the +shell doesn't have error-control as commands, but I'll get into that +in a minute. Again, once error checking has been turned on, it is +expected to remain on until it is turned off again. +.IP "\fBignore=\fP\fIcommand to turn error checking off\fP" +This is the command PMake uses to turn error checking off. It has +another use if the shell doesn't do error-control, but I'll tell you +about that.\|.\|.\|now. +.IP "\fBhasErrCtl=\fP\fIyes or no\fP" +This takes a value that is either +.B yes +or +.B no . +Now you might think that the existence of the +.B check +and +.B ignore +keywords would be enough to tell PMake if the shell can do +error-control, but you'd be wrong. If +.B hasErrCtl +is +.B yes , +PMake uses the check and ignore commands in a straight-forward manner. +If this is +.B no , +however, their use is rather different. In this case, the check +command is used as a template, in which the string +.B %s +is replaced by the command that's about to be executed, to produce a +command for the shell that will echo the command to be executed. The +ignore command is also used as a template, again with +.B %s +replaced by the command to be executed, to produce a command that will +execute the command to be executed and ignore any error it returns. +When these strings are used as templates, you must provide newline(s) +.CW \en '') (`` +in the appropriate place(s). +.LP +The strings that follow these keywords may be enclosed in single or +double quotes (the quotes will be stripped off) and may contain the +usual C backslash-characters (\en is newline, \er is return, \eb is +backspace, \e' escapes a single-quote inside single-quotes, \e" +escapes a double-quote inside double-quotes). Now for an example. +.LP +This is actually the contents of the +.CW +system makefile, and causes PMake to use the Bourne Shell in such a +way that each command is printed as it is executed. That is, if more +than one command is given on a line, each will be printed separately. +Similarly, each time the body of a loop is executed, the commands +within that loop will be printed, etc. The specification runs like +this: +.DS +# +# This is a shell specification to have the Bourne shell echo +# the commands just before executing them, rather than when it reads +# them. Useful if you want to see how variables are being expanded, etc. +# +\&.SHELL : path=/bin/sh \e + quiet="set -" \e + echo="set -x" \e + filter="+ set - " \e + echoFlag=x \e + errFlag=e \e + hasErrCtl=yes \e + check="set -e" \e + ignore="set +e" +.DE +.LP +It tells PMake the following: +.Bp +The shell is located in the file +.CW /bin/sh . +It need not tell PMake that the name of the shell is +.CW sh +as PMake can figure that out for itself (it's the last component of +the path). +.Bp +The command to stop echoing is +.CW "set -" . +.Bp +The command to start echoing is +.CW "set -x" . +.Bp +When the echo off command is executed, the shell will print +.CW "+ set - " +(The `+' comes from using the +.CW \-x +flag (rather than the +.CW \-v +flag PMake usually uses)). PMake will remove all occurrences of this +string from the output, so you don't notice extra commands you didn't +put there. +.Bp +The flag the Bourne Shell will take to start echoing in this way is +the +.CW \-x +flag. The Bourne Shell will only take its flag arguments concatenated +as its first argument, so neither this nor the +.B errFlag +specification begins with a \-. +.Bp +The flag to use to turn error-checking on from the start is +.CW \-e . +.Bp +The shell can turn error-checking on and off, and the commands to do +so are +.CW "set +e" +and +.CW "set -e" , +respectively. +.LP +I should note that this specification is for Bourne Shells that are +not part of Berkeley +.UX , +as shells from Berkeley don't do error control. You can get a similar +effect, however, by changing the last three lines to be: +.DS + hasErrCtl=no \e + check="echo \e"+ %s\e"\en" \e + ignore="sh -c '%s || exit 0\en" +.DE +.LP +This will cause PMake to execute the two commands +.DS +echo "+ \fIcmd\fP" +sh -c '\fIcmd\fP || true' +.DE +for each command for which errors are to be ignored. (In case you are +wondering, the thing for +.CW ignore +tells the shell to execute another shell without error checking on and +always exit 0, since the +.B || +causes the +.CW "exit 0" +to be executed only if the first command exited non-zero, and if the +first command exited zero, the shell will also exit zero, since that's +the last command it executed). +.xH 2 Compatibility +.Ix 0 ref compatibility +.LP +There are three (well, 3 \(12) levels of backwards-compatibility built +into PMake. Most makefiles will need none at all. Some may need a +little bit of work to operate correctly when run in parallel. Each +level encompasses the previous levels (e.g. +.B \-B +(one shell per command) implies +.B \-V ) +The three levels are described in the following three sections. +.xH 3 DEFCON 3 \*- Variable Expansion +.Ix 0 ref compatibility +.LP +As noted before, PMake will not expand a variable unless it knows of a +value for it. This can cause problems for makefiles that expect to +leave variables undefined except in special circumstances (e.g. if +more flags need to be passed to the C compiler or the output from a +text processor should be sent to a different printer). If the +variables are enclosed in curly braces +.CW ${PRINTER} ''), (`` +the shell will let them pass. If they are enclosed in parentheses, +however, the shell will declare a syntax error and the make will come +to a grinding halt. +.LP +You have two choices: change the makefile to define the variables +(their values can be overridden on the command line, since that's +where they would have been set if you used Make, anyway) or always give the +.B \-V +flag (this can be done with the +.CW .MAKEFLAGS +target, if you want). +.xH 3 DEFCON 2 \*- The Number of the Beast +.Ix 0 ref compatibility +.LP +Then there are the makefiles that expect certain commands, such as +changing to a different directory, to not affect other commands in a +target's creation script. You can solve this is either by going +back to executing one shell per command (which is what the +.B \-B +flag forces PMake to do), which slows the process down a good bit and +requires you to use semicolons and escaped newlines for shell constructs, or +by changing the makefile to execute the offending command(s) in a subshell +(by placing the line inside parentheses), like so: +.DS +install :: .MAKE + (cd src; $(.PMAKE) install) + (cd lib; $(.PMAKE) install) + (cd man; $(.PMAKE) install) +.DE +.Ix 0 ref operator double-colon +.Ix 0 ref variable global .PMAKE +.Ix 0 ref .PMAKE +.Ix 0 ref .MAKE +.Ix 0 ref attribute .MAKE +This will always execute the three makes (even if the +.B \-n +flag was given) because of the combination of the ``::'' operator and +the +.CW .MAKE +attribute. Each command will change to the proper directory to perform +the install, leaving the main shell in the directory in which it started. +.xH 3 "DEFCON 1 \*- Imitation is the Not the Highest Form of Flattery" +.Ix 0 ref compatibility +.LP +The final category of makefile is the one where every command requires +input, the dependencies are incompletely specified, or you simply +cannot create more than one target at a time, as mentioned earlier. In +addition, you may not have the time or desire to upgrade the makefile +to run smoothly with PMake. If you are the conservative sort, this is +the compatibility mode for you. It is entered either by giving PMake +the +.B \-M +flag (for Make), or by executing PMake as +.CW make .'' `` +In either case, PMake performs things exactly like Make (while still +supporting most of the nice new features PMake provides). This +includes: +.IP \(bu 2 +No parallel execution. +.IP \(bu 2 +Targets are made in the exact order specified by the makefile. The +sources for each target are made in strict left-to-right order, etc. +.IP \(bu 2 +A single Bourne shell is used to execute each command, thus the +shell's +.CW $$ +variable is useless, changing directories doesn't work across command +lines, etc. +.IP \(bu 2 +If no special characters exist in a command line, PMake will break the +command into words itself and execute the command directly, without +executing a shell first. The characters that cause PMake to execute a +shell are: +.CW # , +.CW = , +.CW | , +.CW ^ , +.CW ( , +.CW ) , +.CW { , +.CW } , +.CW ; , +.CW & , +.CW < , +.CW > , +.CW * , +.CW ? , +.CW [ , +.CW ] , +.CW : , +.CW $ , +.CW ` , +and +.CW \e . +You should notice that these are all the characters that are given +special meaning by the shell (except +.CW ' +and +.CW " , +which PMake deals with all by its lonesome). +.IP \(bu 2 +The use of the null suffix is turned off. +.Ix 0 ref "null suffix" +.Ix 0 ref suffix null +.xH 2 The Way Things Work +.LP +When PMake reads the makefile, it parses sources and targets into +nodes in a graph. The graph is directed only in the sense that PMake +knows which way is up. Each node contains not only links to all its +parents and children (the nodes that depend on it and those on which +it depends, respectively), but also a count of the number of its +children that have already been processed. +.LP +The most important thing to know about how PMake uses this graph is +that the traversal is breadth-first and occurs in two passes. +.LP +After PMake has parsed the makefile, it begins with the nodes the user +has told it to make (either on the command line, or via a +.CW .MAIN +target, or by the target being the first in the file not labeled with +the +.CW .NOTMAIN +attribute) placed in a queue. It continues to take the node off the +front of the queue, mark it as something that needs to be made, pass +the node to +.CW Suff_FindDeps +(mentioned earlier) to find any implicit sources for the node, and +place all the node's children that have yet to be marked at the end of +the queue. If any of the children is a +.CW .USE +rule, its attributes are applied to the parent, then its commands are +appended to the parent's list of commands and its children are linked +to its parent. The parent's unmade children counter is then decremented +(since the +.CW .USE +node has been processed). You will note that this allows a +.CW .USE +node to have children that are +.CW .USE +nodes and the rules will be applied in sequence. +If the node has no children, it is placed at the end of +another queue to be examined in the second pass. This process +continues until the first queue is empty. +.LP +At this point, all the leaves of the graph are in the examination +queue. PMake removes the node at the head of the queue and sees if it +is out-of-date. If it is, it is passed to a function that will execute +the commands for the node asynchronously. When the commands have +completed, all the node's parents have their unmade children counter +decremented and, if the counter is then 0, they are placed on the +examination queue. Likewise, if the node is up-to-date. Only those +parents that were marked on the downward pass are processed in this +way. Thus PMake traverses the graph back up to the nodes the user +instructed it to create. When the examination queue is empty and no +shells are running to create a target, PMake is finished. +.LP +Once all targets have been processed, PMake executes the commands +attached to the +.CW .END +target, either explicitly or through the use of an ellipsis in a shell +script. If there were no errors during the entire process but there +are still some targets unmade (PMake keeps a running count of how many +targets are left to be made), there is a cycle in the graph. PMake does +a depth-first traversal of the graph to find all the targets that +weren't made and prints them out one by one. +.xH 1 Answers to Exercises +.IP (3.1) +This is something of a trick question, for which I apologize. The +trick comes from the UNIX definition of a suffix, which PMake doesn't +necessarily share. You will have noticed that all the suffixes used in +this tutorial (and in UNIX in general) begin with a period +.CW .ms , ( +.CW .c , +etc.). Now, PMake's idea of a suffix is more like English's: it's the +characters at the end of a word. With this in mind, one possible +.Ix 0 def suffix +solution to this problem goes as follows: +.DS I +\&.SUFFIXES : ec.exe .exe ec.obj .obj .asm +ec.objec.exe .obj.exe : + link -o $(.TARGET) $(.IMPSRC) +\&.asmec.obj : + asm -o $(.TARGET) -DDO_ERROR_CHECKING $(.IMPSRC) +\&.asm.obj : + asm -o $(.TARGET) $(.IMPSRC) +.DE +.IP (3.2) +The trick to this one lies in the ``:='' variable-assignment operator +and the ``:S'' variable-expansion modifier. +.Ix 0 ref variable assignment expanded +.Ix 0 ref variable expansion modified +.Ix 0 ref modifier substitute +.Ix 0 ref :S +.Ix 0 ref := +Basically what you want is to take the pointer variable, so to speak, +and transform it into an invocation of the variable at which it +points. You might try something like +.DS I +$(PTR:S/^/\e$(/:S/$/)) +.DE +which places +.CW $( '' `` +at the front of the variable name and +.CW ) '' `` +at the end, thus transforming +.CW VAR ,'' `` +for example, into +.CW $(VAR) ,'' `` +which is just what we want. Unfortunately (as you know if you've tried +it), since, as it says in the hint, PMake does no further substitution +on the result of a modified expansion, that's \fIall\fP you get. The +solution is to make use of ``:='' to place that string into yet +another variable, then invoke the other variable directly: +.DS I +*PTR := $(PTR:S/^/\e$(/:S/$/)/) +.DE +You can then use +.CW $(*PTR) '' `` +to your heart's content. +.de Gp +.XP +\&\fB\\$1:\fP +.. +.xH 1 Glossary of Jargon +.Gp "attribute" +A property given to a target that causes PMake to treat it differently. +.Gp "command script" +The lines immediately following a dependency line that specify +commands to execute to create each of the targets on the dependency +line. Each line in the command script must begin with a tab. +.Gp "command-line variable" +A variable defined in an argument when PMake is first executed. +Overrides all assignments to the same variable name in the makefile. +.Gp "conditional" +A construct much like that used in C that allows a makefile to be +configured on the fly based on the local environment, or on what is being +made by that invocation of PMake. +.Gp "creation script" +Commands used to create a target. See ``command script.'' +.Gp "dependency" +The relationship between a source and a target. This comes in three +flavors, as indicated by the operator between the target and the +source. `:' gives a straight time-wise dependency (if the target is +older than the source, the target is out-of-date), while `!' provides +simply an ordering and always considers the target out-of-date. `::' +is much like `:', save it creates multiple instances of a target each +of which depends on its own list of sources. +.Gp "dynamic source" +This refers to a source that has a local variable invocation in it. It +allows a single dependency line to specify a different source for each +target on the line. +.Gp "global variable" +Any variable defined in a makefile. Takes precedence over variables +defined in the environment, but not over command-line or local variables. +.Gp "input graph" +What PMake constructs from a makefile. Consists of nodes made of the +targets in the makefile, and the links between them (the +dependencies). The links are directed (from source to target) and +there may not be any cycles (loops) in the graph. +.Gp "local variable" +A variable defined by PMake visible only in a target's shell script. +There are seven local variables, not all of which are defined for +every target: +.CW .TARGET , +.CW .ALLSRC , +.CW .OODATE , +.CW .PREFIX , +.CW .IMPSRC , +.CW .ARCHIVE , +and +.CW .MEMBER . +.CW .TARGET , +.CW .PREFIX , +.CW .ARCHIVE , +and +.CW .MEMBER +may be used on dependency lines to create ``dynamic sources.'' +.Gp "makefile" +A file that describes how a system is built. If you don't know what it +is after reading this tutorial.\|.\|.\|. +.Gp "modifier" +A letter, following a colon, used to alter how a variable is expanded. +It has no effect on the variable itself. +.Gp "operator" +What separates a source from a target (on a dependency line) and specifies +the relationship between the two. There are three: +.CW : ', ` +.CW :: ', ` +and +.CW ! '. ` +.Gp "search path" +A list of directories in which a file should be sought. PMake's view +of the contents of directories in a search path does not change once +the makefile has been read. A file is sought on a search path only if +it is exclusively a source. +.Gp "shell" +A program to which commands are passed in order to create targets. +.Gp "source" +Anything to the right of an operator on a dependency line. Targets on +the dependency line are usually created from the sources. +.Gp "special target" +A target that causes PMake to do special things when it's encountered. +.Gp "suffix" +The tail end of a file name. Usually begins with a period, +.CW .c +or +.CW .ms , +e.g. +.Gp "target" +A word to the left of the operator on a dependency line. More +generally, any file that PMake might create. A file may be (and often +is) both a target and a source (what it is depends on how PMake is +looking at it at the time \*- sort of like the wave/particle duality +of light, you know). +.Gp "transformation rule" +A special construct in a makefile that specifies how to create a file +of one type from a file of another, as indicated by their suffixes. +.Gp "variable expansion" +The process of substituting the value of a variable for a reference to +it. Expansion may be altered by means of modifiers. +.Gp "variable" +A place in which to store text that may be retrieved later. Also used +to define the local environment. Conditionals exist that test whether +a variable is defined or not. +.bp +.\" Output table of contents last, with an entry for the index, making +.\" sure to save and restore the last real page number for the index... +.nr @n \n(PN+1 +.\" We are not generating an index +.\" .XS \n(@n +.\" Index +.\" .XE +.nr %% \n% +.PX +.nr % \n(%% Index: vendor/NetBSD/bmake/20201101/PSD.doc/Makefile =================================================================== --- vendor/NetBSD/bmake/20201101/PSD.doc/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20201101/PSD.doc/Makefile (revision 367461) @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.4 2014/07/05 19:22:43 dholland Exp $ +# @(#)Makefile 8.1 (Berkeley) 8/14/93 + +SECTION=reference/ref1 +ARTICLE=make +SRCS= tutorial.ms +MACROS= -ms +EXTRAHTMLFILES=make1.png make2.png + +.include Property changes on: vendor/NetBSD/bmake/20201101/PSD.doc/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/README =================================================================== --- vendor/NetBSD/bmake/20201101/README (nonexistent) +++ vendor/NetBSD/bmake/20201101/README (revision 367461) @@ -0,0 +1,52 @@ + bmake + ***** + +This directory contains a port of the BSD make tool (from NetBSD). +Since 1993 I have run it on AIX, BSDi, Darwin, FreeBSD, HP-UX, IRIX, +Linux, Minix, OSF, Solaris, SunOS and even UTS. +Others have run it on many more systems. + +Currently each release is tested on NetBSD, FreeBSD, Solaris and Linux. + +Since 2003 bmake switched to a date based version (first was 20030714) +which generally represents the date it was last merged with NetBSD's +make. Since then, NetBSD's make is imported within a week of any +interesting changes, so that bmake tracks it very closely. + +Building +======== + +The preferred way to bootstrap bmake is:: + + ./bmake/boot-strap + +there are a number of args - most of which get passed to configure, +eg. +:: + + ./bmake/boot-strap --prefix=/opt + +see the boot-strap script for details. + +For folk that hate to read anything, since 20121212 you can also use +the GNU standard process of:: + + ./configure; make; make install + +To make much use of bmake you will need the bsd.*.mk macros or my +portable *.mk macros which are included with bmake since 20121212 +and separately available from +http://www.crufty.net/ftp/pub/sjg/mk.tar.gz +which will be links to the latest versions. + +Porting +======= + +If you encounter a system that bmake does not build or work on *out of +the box*, I welcome patches. +If you can provide access to a suitable machine - even better. + +More info can be found at http://www.crufty.net/help/sjg/bmake.htm + +--sjg + Index: vendor/NetBSD/bmake/20201101/getopt.c =================================================================== --- vendor/NetBSD/bmake/20201101/getopt.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/getopt.c (revision 367461) @@ -0,0 +1,188 @@ +/* $NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT) +#include + +#include +#include +#include + + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt = BADCH, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(int nargc, char * const nargv[], const char *ostr) +{ + extern char *__progname; + static const char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + +#ifndef BSD4_4 + if (!__progname) { + if (__progname = strrchr(nargv[0], '/')) + ++__progname; + else + __progname = nargv[0]; + } +#endif + + if (optreset || *place == 0) { /* update scanning pointer */ + optreset = 0; + place = nargv[optind]; + if (optind >= nargc || *place++ != '-') { + /* Argument is absent or is not an option */ + place = EMSG; + return (-1); + } + optopt = *place++; + if (optopt == '-' && *place == 0) { + /* "--" => end of options */ + ++optind; + place = EMSG; + return (-1); + } + if (optopt == 0) { + /* Solitary '-', treat as a '-' option + if the program (eg su) is looking for it. */ + place = EMSG; + if (strchr(ostr, '-') == NULL) + return -1; + optopt = '-'; + } + } else + optopt = *place++; + + /* See if option letter is one the caller wanted... */ + if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { + if (*place == 0) + ++optind; + if (opterr && *ostr != ':') + (void)fprintf(stderr, + "%s: unknown option -- %c\n", __progname, optopt); + return (BADCH); + } + + /* Does this option need an argument? */ + if (oli[1] != ':') { + /* don't need argument */ + optarg = NULL; + if (*place == 0) + ++optind; + } else { + /* Option-argument is either the rest of this argument or the + entire next argument. */ + if (*place) + optarg = __UNCONST(place); + else if (oli[2] == ':') + /* + * GNU Extension, for optional arguments if the rest of + * the argument is empty, we return NULL + */ + optarg = NULL; + else if (nargc > ++optind) + optarg = nargv[optind]; + else { + /* option-argument absent */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + __progname, optopt); + return (BADCH); + } + place = EMSG; + ++optind; + } + return (optopt); /* return option letter */ +} +#endif +#ifdef MAIN +#ifndef BSD4_4 +char *__progname; +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c; + char *opts = argv[1]; + + --argc; + ++argv; + + while ((c = getopt(argc, argv, opts)) != EOF) { + switch (c) { + case '-': + if (optarg) + printf("--%s ", optarg); + break; + case '?': + exit(1); + break; + default: + if (optarg) + printf("-%c %s ", c, optarg); + else + printf("-%c ", c); + break; + } + } + + if (optind < argc) { + printf("-- "); + for (; optind < argc; ++optind) { + printf("%s ", argv[optind]); + } + } + printf("\n"); + exit(0); +} +#endif Property changes on: vendor/NetBSD/bmake/20201101/getopt.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/makefile.in =================================================================== --- vendor/NetBSD/bmake/20201101/makefile.in (nonexistent) +++ vendor/NetBSD/bmake/20201101/makefile.in (revision 367461) @@ -0,0 +1,14 @@ +# $Id: makefile.in,v 1.1 2012/12/28 21:28:19 sjg Exp $ + +# a simple makefile for those who don't like anything beyond: +# ./configure; make; make install + +prefix= @prefix@ +srcdir= @srcdir@ + +all: build + +build clean install test: + ${srcdir}/boot-strap --prefix=${prefix} -o . op=$@ + + Property changes on: vendor/NetBSD/bmake/20201101/makefile.in ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/realpath.c =================================================================== --- vendor/NetBSD/bmake/20201101/realpath.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/realpath.c (revision 367461) @@ -0,0 +1,215 @@ +/* $Id: realpath.c,v 1.3 2013/01/25 17:06:09 sjg Exp $ */ +/* from: $NetBSD: getcwd.c,v 1.53 2012/06/21 23:29:23 enami Exp $ */ + +/* + * Copyright (c) 1989, 1991, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ +#ifdef HAVE_CONFIG_H +# include +#endif +#ifndef HAVE_REALPATH + +#include +#include +#include + +#include +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifndef __restrict +# define __restrict /* restrict */ +#endif + +/* + * char *realpath(const char *path, char *resolved); + * + * Find the real name of path, by removing all ".", ".." and symlink + * components. Returns (resolved) on success, or (NULL) on failure, + * in which case the path which caused trouble is left in (resolved). + */ +char * +realpath(const char * __restrict path, char * __restrict resolved) +{ + struct stat sb; + int idx = 0, nlnk = 0; + const char *q; + char *p, wbuf[2][MAXPATHLEN], *fres; + size_t len; + ssize_t n; + + /* POSIX sez we must test for this */ + if (path == NULL) { + errno = EINVAL; + return NULL; + } + + if (resolved == NULL) { + fres = resolved = malloc(MAXPATHLEN); + if (resolved == NULL) + return NULL; + } else + fres = NULL; + + + /* + * Build real path one by one with paying an attention to ., + * .. and symbolic link. + */ + + /* + * `p' is where we'll put a new component with prepending + * a delimiter. + */ + p = resolved; + + if (*path == '\0') { + *p = '\0'; + errno = ENOENT; + goto out; + } + + /* If relative path, start from current working directory. */ + if (*path != '/') { + /* check for resolved pointer to appease coverity */ + if (resolved && getcwd(resolved, MAXPATHLEN) == NULL) { + p[0] = '.'; + p[1] = '\0'; + goto out; + } + len = strlen(resolved); + if (len > 1) + p += len; + } + +loop: + /* Skip any slash. */ + while (*path == '/') + path++; + + if (*path == '\0') { + if (p == resolved) + *p++ = '/'; + *p = '\0'; + return resolved; + } + + /* Find the end of this component. */ + q = path; + do + q++; + while (*q != '/' && *q != '\0'); + + /* Test . or .. */ + if (path[0] == '.') { + if (q - path == 1) { + path = q; + goto loop; + } + if (path[1] == '.' && q - path == 2) { + /* Trim the last component. */ + if (p != resolved) + while (*--p != '/') + continue; + path = q; + goto loop; + } + } + + /* Append this component. */ + if (p - resolved + 1 + q - path + 1 > MAXPATHLEN) { + errno = ENAMETOOLONG; + if (p == resolved) + *p++ = '/'; + *p = '\0'; + goto out; + } + p[0] = '/'; + memcpy(&p[1], path, + /* LINTED We know q > path. */ + q - path); + p[1 + q - path] = '\0'; + + /* + * If this component is a symlink, toss it and prepend link + * target to unresolved path. + */ + if (lstat(resolved, &sb) == -1) + goto out; + + if (S_ISLNK(sb.st_mode)) { + if (nlnk++ >= MAXSYMLINKS) { + errno = ELOOP; + goto out; + } + n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1); + if (n < 0) + goto out; + if (n == 0) { + errno = ENOENT; + goto out; + } + + /* Append unresolved path to link target and switch to it. */ + if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) { + errno = ENAMETOOLONG; + goto out; + } + memcpy(&wbuf[idx][n], q, len + 1); + path = wbuf[idx]; + idx ^= 1; + + /* If absolute symlink, start from root. */ + if (*path == '/') + p = resolved; + goto loop; + } + if (*q == '/' && !S_ISDIR(sb.st_mode)) { + errno = ENOTDIR; + goto out; + } + + /* Advance both resolved and unresolved path. */ + p += 1 + q - path; + path = q; + goto loop; +out: + free(fres); + return NULL; +} +#endif Property changes on: vendor/NetBSD/bmake/20201101/realpath.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/find_lib.sh =================================================================== --- vendor/NetBSD/bmake/20201101/find_lib.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/find_lib.sh (revision 367461) @@ -0,0 +1,13 @@ +: +re=$1; shift + +for lib in $* +do + found=`nm $lib | egrep "$re"` + case "$found" in + "") ;; + *) echo "$lib: $found";; + esac +done + + Property changes on: vendor/NetBSD/bmake/20201101/find_lib.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/install-sh =================================================================== --- vendor/NetBSD/bmake/20201101/install-sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/install-sh (revision 367461) @@ -0,0 +1,201 @@ +: +# NAME: +# install.sh - portable version of install(1) +# +# SYNOPSIS: +# install [-CNcs] [-f flags] [-i errs] [-o owner] [-g group] [-m mode] file1 file2 ... +# install -d [-i errs] [-o owner] [-g group] [-m mode] directory ... +# +# DESCRIPTION: +# Compatible with BSD install(1). Except that '-c' is always +# true and we always move an already installed target aside as +# this is important on many systems. Recent BSD install(1) +# versions have a '-b' option for this. +# +# +# OPTIONS: +# -b move previous target file aside (always true). +# +# -B "suffix" +# use "suffix" instead of .old for saving existing target. +# +# -c copy rather than move the file into place (always true). +# +# -C compare. Only install if target is missing or +# different. +# +# -N newer. Only install if target is missing or older. +# +# -s strip target +# +# -o "owner" +# make target owned by "owner" +# +# -g "group" +# make target group owned by "group" +# +# -m "mode" +# set permissions to "mode" +# +# -f "flags" +# Pass "flags" onto chflags(1) +# +# -i "errs" +# Ignore errors from steps indicated by "errs" (``s,o,g,m''). +# +# BUGS: +# The '-i' option is to save your sanity when 'bsd.prog.mk' +# insists on haveing a '-o' "owner" option which is doomed to +# fail on many systems. We ignore '-b', '-B' and '-c' options. +# +# AUTHOR: +# Simon J. Gerraty +# + +# RCSid: +# $Id: install-sh,v 1.18 2001/03/16 17:33:02 sjg Exp $ +# +# @(#) Copyright (c) 1993 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@quick.com.au +# + +set -- `getopt B:bpxCNcsdo:g:m:i:f: $*` + +Mydir=`dirname $0` +[ -s $Mydir/.installrc ] && . $Mydir/.installrc + +owner=: +group=: +mode=: +strip=: +mkdirs= +compare=: +newer=: +chflags=: +LS1= +CP_P= + +while [ $# -gt 1 ] +do + case $1 in + --) shift; break;; + -p) CP_P=-p;; + -x) set -x;; + -B) OLD_EXT=$2; shift;; + -C) compare=Different;; + -N) newer=Newer; + # check if /bin/ls supports -1 + /bin/ls -1 $0 >/dev/null 2>&1 && LS1=1 + ;; + -o) owner="${CHOWN:-chown} $2 "; shift;; + -g) group="${CHGRP:-chgrp} $2 "; shift;; + -m) mode="${CHMOD:-chmod} $2 "; shift;; + -s) strip=${STRIP:-strip};; + -d) mkdirs="mkdir -p";; + -i) ignore_err="$ignore_err$2"; shift;; + -f) chflags="${CHFLAGS:-chflags} $2 "; shift;; + esac + shift +done + +Newer() { + n=`/bin/ls -t$LS1 $* 2>/dev/null | head -1` + [ $1 = $n ] +} + +Different() { + cmp -s $* + [ $? != 0 ] +} + +Err() { + case "$ignore_err" in + *$1*) ;; + *) exit 1;; + esac +} + +Setem() { + # the order is important + if [ ! -d $1 ]; then + $strip $1 || Err s + fi + $group $1 || Err g + $owner $1 || Err o + $mode $1 || Err m + $chflags $1 || Err f + return 0 +} + +# a bug in HP-UX's /bin/sh, means we need to re-set $* +# after any calls to add_path() +args="$*" + +# all this just for chown! +add_path () { [ -d $1 ] && eval ${2:-PATH}="\$${2:-PATH}:$1"; } +add_path /etc +add_path /usr/etc +add_path /sbin +add_path /usr/sbin + +# restore saved $* +set -- $args + +# make directories if needed +# and ensure mode etc are as desired +if [ "$mkdirs" ]; then + for d in $* + do + [ ! -d $d ] && $mkdirs $d + Setem $d + done + exit 0 # that's all we do +fi + +# install files +if [ $# -gt 2 ]; then + dest_dir=yes +elif [ $# -eq 1 ]; then + echo "what should I do with $*?" >&2 + exit 1 +fi + +# get list of files +while [ $# -gt 1 ] +do + files="$files $1" + shift +done +# last one is dest +dest=$1 +shift + + +if [ "$dest_dir" = yes -a ! -d $dest ]; then + echo "no directory $dest" >&2 + exit 1 +fi + +for f in $files +do + b=`basename $f` + if [ -d $dest ]; then + t=$dest/$b + else + t=$dest + fi + $newer $f $t || continue + $compare $f $t || continue + [ -f $t ] && { mv -f $t $t.old || exit 1; } + { cp $CP_P $f $t && Setem $t; } || exit 1 +done +exit 0 Property changes on: vendor/NetBSD/bmake/20201101/install-sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/mkdeps.sh =================================================================== --- vendor/NetBSD/bmake/20201101/mkdeps.sh (nonexistent) +++ vendor/NetBSD/bmake/20201101/mkdeps.sh (revision 367461) @@ -0,0 +1,314 @@ +: +# NAME: +# mkdeps - generate dependencies +# +# SYNOPSIS: +# mkdeps [options] file ... +# +# DESCRIPTION: +# This script updates "makefile" with dependencies for +# "file"(s). It borrows ideas from various makedepend scripts +# and should be compatible with most. +# +# By default we use grep to extract include file names from +# source files. We source an "rc" file '$Mydir/.${Myname}rc' which +# can contain variable assignments such as: +#.nf +# +# cpp_c=/usr/lib/cpp +# cpp_cc=g++ -E +# ... +# +#.fi +# If the variable 'cpp_$suffix' is set, we use it as our cpp in +# place of grep. The program referenced by these variables are +# expected to produce output like: +#.nf +# +# # 10 \"/usr/include/stdio.h\" 1 +# +#.fi +# This allows us to skip most of our processing. For lex,yacc +# and other source files, grep is probably just as quick and +# certainly more portable. +# +# If the "rc" file does not exist, we create it and attempt to +# find cpp or an equivalent cc invocation to assign to 'cpp_c'. +# +# AUTHOR: +# Simon J. Gerraty +# + +# RCSid: +# $Id: mkdeps.sh,v 1.23 2002/11/29 06:58:59 sjg Exp $ +# +# @(#) Copyright (c) 1993 Simon J. Gerraty +# +# This file is provided in the hope that it will +# be of use. There is absolutely NO WARRANTY. +# Permission to copy, redistribute or otherwise +# use this file is hereby granted provided that +# the above copyright notice and this notice are +# left intact. +# +# Please send copies of changes and bug-fixes to: +# sjg@zen.void.oz.au +# + +Myname=`basename $0 .sh` +Mydir=`dirname $0` + +case `echo -n .` in +-n*) N=; C="\c";; +*) N=-n; C=;; +esac + +cc_include=-I/usr/include + +TF=/tmp/dep.$$ +EF=/tmp/deperr.$$ +> $EF + +case "$*" in +*-n*) # don't use rc file + rc=/dev/null + norc=yes;; +*) + rc=$Mydir/.${Myname}rc + ;; +esac + +update= +Include=include + +if [ x"$norc" = x -a -f $rc ]; then + . $rc +else + # if /usr/lib/cpp or equivalent is available it is better than + # grepping .c files. + # See what (if anything) works on this system... + echo : > $rc + echo "# pre-processor for .c files" >> $rc + # try a couple of sane places first + for d in /usr/libexec /usr/lib /usr/bin /lib /usr/ccs/bin + do + cpp_c=$d/cpp + [ -x $cpp_c ] && break + done + + if [ -x $cpp_c ]; then + echo cpp_c=$cpp_c >> $rc + else + cpp_c= + # rats see if cc can be used + echo "#include " > /tmp/f$$.c + echo "main() { return 0; }" >> /tmp/f$$.c + # try some sensible args to cc + for arg in -E -P -M + do + ok=`${REALCC:-${CC:-cc}} $arg /tmp/f$$.c 2>/dev/null | grep '^#.*stdio.h' | tail -1` + case "$ok" in + "") ;; + *) + cpp_c="${REALCC:-${CC:-cc}} $arg" + echo cpp_c="'$cpp_c'" >> $rc + break;; + esac + done + rm -f /tmp/f$$.c + fi +fi + +clean_up() { + trap "" 2 3 + trap 0 + if [ -s $EF ]; then + egrep -vi "included from|warning" $EF > ${EF}2 + if [ -s ${EF}2 ]; then + cat $EF >&2 + rm -f .depend + ests=1 + fi + fi + rm -f $TF $EF* + exit ${ests:-0} +} + +# this lot does not work on HPsUX - complain to Hp. +trap clean_up 0 +trap exit 2 3 + +get_incs() { + case "$cpp" in + grep) + # set IGNORE="<" to skip system includes + egrep '^#[ ]*include' $* | egrep -v "$IGNORE" | \ + sed -e 's/^.*include[^"<]*["<]//' -e 's/[">].*//g';; + *) + # $cpp (eg. /usr/lib/cpp or cc -E) should produce output like: + # 1 "/usr/include/stdio.h" 2 + # set IGNORE=/usr/include to skip system includes + $cpp $cpp_opts $cc_include $* 2>> $EF | egrep '^#.*\.h"' | sed 's,^#.*"\(.*\)".*,\1,' | + egrep -v "$IGNORE" | sort -u;; + esac +} + +gen_deps() { + llen=$1 + shift + + for ifile in $* + do + case "$cpp" in + grep) + # this lot is not needed if not using grep. + for dir in $srcdir $dirlist /usr/include + do + [ -f "$dir/$ifile" ] && break + done + + if [ ! -f "$dir/$ifile" ]; then + # produce a useful error message (useful to emacs or error) + iline=`grep -n ".*include.*[\"<]$ifile[\">]" $file | cut -d: -f1` + echo "\"$file\", line $iline: cannot find include file \"$ifile\"" >> $EF + # no point adding to dependency list as the resulting makefile + # would not work anyway... + continue + fi + ifile=$dir/$ifile + + # check whether we have done it yet + case `grep "$ifile" $TF` in + "") echo "$ifile" >> $TF;; + *) continue;; # no repeats... + esac + ;; + esac + + len=`expr "$ifile " : '.*'` + if [ "`expr $llen + $len`" -gt ${width:-76} ]; then + echo "\\" >> .depend + echo $N " $C" >> .depend + llen=8 + fi + echo $N "$ifile $C" >> .depend + llen=`expr $llen + $len` + + case "$cpp" in + grep) + # this lot is not needed unless using grep. + ilist=`get_incs $ifile` # recurse needed? + [ "$ilist" ] && llen=`gen_deps $llen $ilist` + ;; + esac + done + echo $llen +} + +for f in makefile Makefile +do + test -s $f && { MAKEFILE=$f; break; } +done + +MAKEFILE=${MAKEFILE:-makefile} +IGNORE=${IGNORE:-"^-"} # won't happen +obj=o +cpp_opts= # incase cpp != grep +vpath= +append= +progDep= + +set -- `getopt "AanNV:s:w:o:I:D:b:f:i:p" "$@"` +for key in "$@" +do + case $key in + --) shift; break;; + -A) Include=;; # cat .depend >> $MAKEFILE + -a) append=yes; shift;; + -n) shift;; # ignore rc + -N) update=no; shift;; # don't update $MAKEFILE + -I) cpp_opts="$cpp_opts$1$2 "; dirlist="$dirlist $2"; shift 2;; + -o) obj=$2; shift 2;; + -s) shift 2;; # can't handle it anyway... + -w) width=$2; shift 2;; + -f) MAKEFILE=$2; shift 2;; + -b) BASEDIR=$2; shift 2;; + -i) IGNORE="$2"; shift 2;; # ignore headers matching this... + -D) cpp_opts="$cpp_opts$1$2 "; shift 2;; + -V) VPATH="$2"; shift 2;; # where to look for files + -p) progDep=yes; shift;; + esac +done + +[ "$VPATH" ] && vpath=`IFS=:; set -- $VPATH; echo $*` + +[ "$append" ] || > .depend + +for file in $* +do + cpp= + suffix=`expr $file : '.*\.\([^.]*\)'` + + eval cpp=\"\${cpp_${suffix}:-grep}\" + + if [ ! -f $file -a "$vpath" ]; then + for d in . $vpath + do + [ -f $d/$file ] && { file=$d/$file; break; } + done + fi + srcdir=`dirname $file` + base=`basename $file .$suffix` + + ilist=`get_incs $file` + + if [ "$ilist" ]; then + > $TF + if [ "$progDep" ]; then + echo "$base: $file \\" >> .depend + else + echo "$base.$obj: $file \\" >> .depend + fi + echo $N " $C" >> .depend + llen=8 + llen=`gen_deps $llen $ilist` + echo >> .depend + echo >> .depend + elif [ "$progDep" ]; then + echo "$base: $file" >> .depend + echo >> .depend + fi +done + +if [ -s .depend ]; then + # ./foo.h looks ugly + mv .depend $TF + { test "$BASEDIR" && sed -e "s;$BASEDIR;\$(BASEDIR);g" $TF || cat $TF; } | + sed 's;\([^.]\)\./;\1;g' > .depend + + # + # Save the manually updated section of the makefile + # + if [ x$update != xno ]; then + trap "" 2 # don't die if we got this far + + # if make doesn't support include, then append our deps... + depended=`grep 'include.*\.depend' $MAKEFILE` + test "$depended" && clean_up + + sed '/^# DO NOT DELETE.*depend.*$/,$d' < $MAKEFILE > $TF + mv $TF $MAKEFILE + cat <> $MAKEFILE +# DO NOT DELETE THIS LINE -- make depend depends on it +# Do not edit anything below, it was added automagically by $Myname. + +! + + case "$Include" in + "") cat .depend >> $MAKEFILE;; + .include) echo '.include ".depend"' >> $MAKEFILE;; + include) echo include .depend >> $MAKEFILE;; + esac + fi +fi +clean_up Property changes on: vendor/NetBSD/bmake/20201101/mkdeps.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/pathnames.h =================================================================== --- vendor/NetBSD/bmake/20201101/pathnames.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/pathnames.h (revision 367461) @@ -0,0 +1,62 @@ +/* $NetBSD: pathnames.h,v 1.17 2009/04/11 09:41:18 apb Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)pathnames.h 5.2 (Berkeley) 6/1/90 + * $Id: pathnames.h,v 1.13 2009/08/26 23:43:42 sjg Exp $ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#ifndef MAKE_NATIVE +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif +#endif +#ifdef HAVE_PATHS_H +#include +#endif +#define _PATH_OBJDIR "obj" +#define _PATH_OBJDIRPREFIX "/usr/obj" +#ifndef _PATH_DEFSHELLDIR +#define _PATH_DEFSHELLDIR "/bin" +#endif +#define _PATH_DEFSYSMK "sys.mk" +#define _path_defsyspath "/usr/share/mk:/usr/local/share/mk:/opt/share/mk" +#ifndef _PATH_DEFSYSPATH +# ifdef _PATH_PREFIX_SYSPATH +# define _PATH_DEFSYSPATH _PATH_PREFIX_SYSPATH ":" _path_defsyspath +# else +# define _PATH_DEFSYSPATH _path_defsyspath +# endif +#endif +#ifndef _PATH_TMP +#define _PATH_TMP "/tmp/" /* with trailing slash */ +#endif Property changes on: vendor/NetBSD/bmake/20201101/pathnames.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/ranlib.h =================================================================== --- vendor/NetBSD/bmake/20201101/ranlib.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/ranlib.h (revision 367461) @@ -0,0 +1,32 @@ +/* @(#)ranlib.h 1.6 88/08/19 SMI; from UCB 4.1 83/05/03 */ +/* $Id: ranlib.h,v 1.5 2005/11/01 02:35:15 sjg Exp $ */ + +/* + * Structure of the __.SYMDEF table of contents for an archive. + * __.SYMDEF begins with a word giving the number of ranlib structures + * which immediately follow, and then continues with a string + * table consisting of a word giving the number of bytes of strings + * which follow and then the strings themselves. + * The ran_strx fields index the string table whose first byte is numbered 0. + */ + +#if !defined(IRIX) && !defined(__digital__) && !defined(__osf__) +#ifndef _ranlib_h +#define _ranlib_h + +#if 0 +#define RANLIBMAG "!\n__.SYMDEF" /* archive file name */ +#endif +#define RANLIBMAG "__.SYMDEF" /* archive file name */ +#define RANLIBSKEW 3 /* creation time offset */ + +struct ranlib { + union { + off_t ran_strx; /* string table index of */ + char *ran_name; /* symbol defined by */ + } ran_un; + off_t ran_off; /* library member at this offset */ +}; + +#endif /*!_ranlib_h*/ +#endif Property changes on: vendor/NetBSD/bmake/20201101/ranlib.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/setenv.c =================================================================== --- vendor/NetBSD/bmake/20201101/setenv.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/setenv.c (revision 367461) @@ -0,0 +1,154 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifndef HAVE_SETENV + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/ +static char *rcsid = "$Id: setenv.c,v 1.5 1996/09/04 22:10:42 sjg Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +/* + * __findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + * This routine *should* be a static; don't use it. + */ +static char * +__findenv(name, offset) + register char *name; + int *offset; +{ + extern char **environ; + register int len; + register char **P, *C; + + for (C = name, len = 0; *C && *C != '='; ++C, ++len); + for (P = environ; *P; ++P) + if (!strncmp(*P, name, len)) + if (*(C = *P + len) == '=') { + *offset = P - environ; + return(++C); + } + return(NULL); +} + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +setenv(name, value, rewrite) + register const char *name; + register const char *value; + int rewrite; +{ + extern char **environ; + static int alloced; /* if allocated space before */ + register char *C; + int l_value, offset; + char *__findenv(); + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((C = __findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return (0); + if (strlen(C) >= l_value) { /* old larger; copy over */ + while (*C++ = *value++); + return (0); + } + } else { /* create new slot */ + register int cnt; + register char **P; + + for (P = environ, cnt = 0; *P; ++P, ++cnt); + if (alloced) { /* just increase size */ + environ = (char **)realloc((char *)environ, + (size_t)(sizeof(char *) * (cnt + 2))); + if (!environ) + return (-1); + } + else { /* get new space */ + alloced = 1; /* copy old entries into it */ + P = (char **)malloc((size_t)(sizeof(char *) * + (cnt + 2))); + if (!P) + return (-1); + bcopy(environ, P, cnt * sizeof(char *)); + environ = P; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((size_t)((int)(C - name) + l_value + 2)))) + return (-1); + for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) + ; + for (*C++ = '='; *C++ = *value++; ) + ; + return (0); +} + +/* + * unsetenv(name) -- + * Delete environmental variable "name". + */ +void +unsetenv(name) + const char *name; +{ + extern char **environ; + register char **P; + int offset; + char *__findenv(); + + while (__findenv(name, &offset)) /* if set multiple times */ + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; +} +#endif Property changes on: vendor/NetBSD/bmake/20201101/setenv.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/sigcompat.c =================================================================== --- vendor/NetBSD/bmake/20201101/sigcompat.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/sigcompat.c (revision 367461) @@ -0,0 +1,325 @@ +/* + * NAME: + * sigcompat - BSD compat signals via POSIX + * + * SYNOPSIS: + * void (*signal(int "sig", void (*"handler")(int)))(int); + * int sigsetmask(int "mask"); + * int sigblock(int "mask"); + * int sigpause(int "mask"); + * int sigvec(int "signo", struct sigvec *"sv", struct sigvec *"osv"); + * + * DESCRIPTION: + * These implement the old BSD routines via the POSIX equivalents. + * This module can be used to provide the missing routines, or if + * 'FORCE_POSIX_SIGNALS' is defined, force use of these. + * + * Note that signal() is identical to my Signal() routine except + * for checking for recursion. Within libsig, signal() just + * calls Signal(). + * + * BUGS: + * This package assumes POSIX signal handling is available and + * NOT implemeneted using these routines. To be safe, we check + * for recursion and abort(3) if detected. + * + * Sadly, on some systems, sigset_t is an array, and we cannot + * test for this via #if sizeof(sigset_t) ..., so unless + * 'SIGSET_T_INT' is defined, we have to assume the worst and use + * memcpy(3) to handle args and return values. + * + * HISTORY: + * These routines originate from BSD, and are derrived from the + * NetBSD 1.1 implementation. They have been seriously hacked to + * make them portable to other systems. + * + * AUTHOR: + * Simon J. Gerraty + */ +/* + * @(#)Copyright (c) 1994, Simon J. Gerraty. + * + * This is free software. It comes with NO WARRANTY. + * Permission to use, modify and distribute this source code + * is granted subject to the following conditions. + * 1/ that the above copyright notice and this notice + * are preserved in all copies and that due credit be given + * to the author. + * 2/ that any changes to this code are clearly commented + * as such so that the author does not get blamed for bugs + * other than his own. + * + * Please send copies of changes and bug-fixes to: + * sjg@crufty.net + */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#if defined(sun) && !(defined(__svr4__) || defined(__SVR4)) +# define NO_SIGCOMPAT +#endif +#if defined(__MINT__) +# define NO_SIGCOMPAT +#endif + +#if !defined(NO_SIGCOMPAT) && (defined(HAVE_SIGACTION) || defined(SA_NOCLDSTOP)) + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)sigcompat.c 5.3 (Berkeley) 2/24/91";*/ +static char *rcsid = "$Id: sigcompat.c,v 1.23 2011/02/14 00:07:11 sjg Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#undef signal +#include +#include +#include +#include +#include "assert.h" + +#ifndef ASSERT +# define ASSERT assert +#endif + +#ifdef NDEBUG +# define _DBUG(x) +#else +# define _DBUG(x) x +#endif + +#ifndef SA_RESTART +# define SA_RESTART 2 +#endif +#ifndef SV_INTERRUPT +# define SV_INTERRUPT SA_RESTART +#endif + +#ifndef MASK_T +# if defined(__hpux__) || defined(__hpux) +# define MASK_T long +# else +# define MASK_T int +# endif +#endif +/* I just hate HPsUX */ +#if (defined(__HPUX_VERSION) && __HPUX_VERSION > 9) || defined(__hpux) +# define PAUSE_MASK_T int +#else +# define PAUSE_MASK_T MASK_T +#endif + +#ifndef SIG_HDLR +# define SIG_HDLR void +#endif + +#ifdef FORCE_POSIX_SIGNALS +#if !(defined(libsig) || defined(libsjg)) +/* + * This little block is almost identical to Signal(), + * and make this module standalone. + * We don't use it in libsig by default, as some apps might use both + * and expect _SignalFlags to be used by both. + */ + +#ifndef SIGNAL_FLAGS +# define SIGNAL_FLAGS 0 /* no auto-restart */ +#endif +int _signalFlags = SIGNAL_FLAGS; + +SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) +{ + _DBUG(static int depth_signal = 0); + struct sigaction act, oact; + int n; + + _DBUG(++depth_signal); + ASSERT(depth_signal < 2); + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = _signalFlags; + n = sigaction(sig, &act, &oact); + _DBUG(--depth_signal); + if (n < 0) + return (SIG_ERR); + return (oact.sa_handler); +} +#else +SIG_HDLR(*signal(int sig, SIG_HDLR(*handler)(int)))(int) +{ + extern SIG_HDLR(*Signal(int, void (*)(int)))(int); + _DBUG(static int depth_signal = 0); + SIG_HDLR(*old) __P((int)); + + _DBUG(++depth_signal); + ASSERT(depth_signal < 2); + old = Signal(sig, handler); + _DBUG(--depth_signal); + return old; +} +#endif +#endif + +/* + * on some systems, sigset_t is an array... + * it would be nicer if we could do + * #if sizeof(sigset_t) > sizeof(MASK_T) + */ +#ifdef SIGSET_T_INT +# define ss2m(ss) (MASK_T) *(ss) +# define m2ss(ss, m) *ss = (sigset_t) *(m) +#else +static MASK_T +ss2m(sigset_t *ss) +{ + MASK_T ma[(sizeof(sigset_t) / sizeof(MASK_T)) + 1]; + + memcpy((char *) ma, (char *) ss, sizeof(sigset_t)); + return ma[0]; +} + +static void +m2ss(sigset_t *ss, MASK_T *m) +{ + if (sizeof(sigset_t) > sizeof(MASK_T)) + memset((char *) ss, 0, sizeof(sigset_t)); + + memcpy((char *) ss, (char *) m, sizeof(MASK_T)); +} +#endif + +#if !defined(HAVE_SIGSETMASK) || defined(FORCE_POSIX_SIGNALS) +MASK_T +sigsetmask(MASK_T mask) +{ + _DBUG(static int depth_sigsetmask = 0); + sigset_t m, omask; + int n; + + _DBUG(++depth_sigsetmask); + ASSERT(depth_sigsetmask < 2); + m2ss(&m, &mask); + n = sigprocmask(SIG_SETMASK, (sigset_t *) & m, (sigset_t *) & omask); + _DBUG(--depth_sigsetmask); + if (n) + return (n); + + return ss2m(&omask); +} + + +MASK_T +sigblock(MASK_T mask) +{ + _DBUG(static int depth_sigblock = 0); + sigset_t m, omask; + int n; + + _DBUG(++depth_sigblock); + ASSERT(depth_sigblock < 2); + if (mask) + m2ss(&m, &mask); + n = sigprocmask(SIG_BLOCK, (sigset_t *) ((mask) ? &m : 0), (sigset_t *) & omask); + _DBUG(--depth_sigblock); + if (n) + return (n); + return ss2m(&omask); +} + +#undef sigpause /* Linux at least */ + +PAUSE_MASK_T +sigpause(PAUSE_MASK_T mask) +{ + _DBUG(static int depth_sigpause = 0); + sigset_t m; + PAUSE_MASK_T n; + + _DBUG(++depth_sigpause); + ASSERT(depth_sigpause < 2); + m2ss(&m, &mask); + n = sigsuspend(&m); + _DBUG(--depth_sigpause); + return n; +} +#endif + +#if defined(HAVE_SIGVEC) && defined(FORCE_POSIX_SIGNALS) +int +sigvec(int signo, struct sigvec *sv, struct sigvec *osv) +{ + _DBUG(static int depth_sigvec = 0); + int ret; + struct sigvec nsv; + + _DBUG(++depth_sigvec); + ASSERT(depth_sigvec < 2); + if (sv) { + nsv = *sv; + nsv.sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ + } + ret = sigaction(signo, sv ? (struct sigaction *) & nsv : NULL, + (struct sigaction *) osv); + _DBUG(--depth_sigvec); + if (ret == 0 && osv) + osv->sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */ + return (ret); +} +#endif + +#ifdef MAIN +# ifndef sigmask +# define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1))) +# endif + +int +main(int argc, char *argv[]) +{ + MASK_T old = 0; + + printf("expect: old=0,old=2\n"); + fflush(stdout); + signal(SIGQUIT, SIG_IGN); + old = sigblock(sigmask(SIGINT)); + printf("old=%d,", old); + old = sigsetmask(sigmask(SIGALRM)); + printf("old=%d\n", old); +} +#endif +#endif Property changes on: vendor/NetBSD/bmake/20201101/sigcompat.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/strlcpy.c =================================================================== --- vendor/NetBSD/bmake/20201101/strlcpy.c (nonexistent) +++ vendor/NetBSD/bmake/20201101/strlcpy.c (revision 367461) @@ -0,0 +1,63 @@ +/* $NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ + +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif +#ifndef HAVE_STRLCPY + +#include + +#include +#include + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + if (!dst || !src) + return 0; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} +#endif Property changes on: vendor/NetBSD/bmake/20201101/strlcpy.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20201101/wait.h =================================================================== --- vendor/NetBSD/bmake/20201101/wait.h (nonexistent) +++ vendor/NetBSD/bmake/20201101/wait.h (revision 367461) @@ -0,0 +1,81 @@ +/* NAME: + * wait.h - compensate for what vendors leave out + * + * AUTHOR: + * Simon J. Gerraty + */ +/* + * RCSid: + * $Id: wait.h,v 1.6 2002/11/26 07:53:06 sjg Exp $ + * + * @(#)Copyright (c) 1994, Simon J. Gerraty. + * + * This is free software. It comes with NO WARRANTY. + * Permission to use, modify and distribute this source code + * is granted subject to the following conditions. + * 1/ that the above copyright notice and this notice + * are preserved in all copies and that due credit be given + * to the author. + * 2/ that any changes to this code are clearly commented + * as such so that the author does not get blamed for bugs + * other than his own. + * + * Please send copies of changes and bug-fixes to: + * sjg@crufty.net + */ + +#include + +#ifdef sun386 +# define UNION_WAIT +# define WEXITSTATUS(x) ((&x)->w_retcode) +# define WTERMSIG(x) ((&x)->w_termsig) +# define WSTOPSIG(x) ((&x)->w_stopsig) +# define HAVE_WAIT4 +#endif + +#ifndef WAIT_T +# ifdef UNION_WAIT +# define WAIT_T union wait +# define WAIT_STATUS(x) (x).w_status +# else +# define WAIT_T int +# define WAIT_STATUS(x) x +# endif +#endif + +#ifndef WEXITSTATUS +# define WEXITSTATUS(_X) (((int)(_X)>>8)&0377) +#endif +#ifndef WSTOPPED +# define WSTOPPED 0177 +#endif +#ifndef WSTOPSIG +# define WSTOPSIG(x) WSTOPPED +#endif + +#ifdef UNION_WAIT +#ifndef WSET_STOPCODE +#define WSET_STOPCODE(x, sig) ((&x)->w_stopsig = (sig)) +#endif +#ifndef WSET_EXITCODE +#define WSET_EXITCODE(x, ret, sig) ((&x)->w_termsig = (sig), (&x)->w_retcode = (ret)) +#endif +#else +#ifndef WSET_STOPCODE +#define WSET_STOPCODE(x, sig) ((x) = ((sig) << 8) | 0177) +#endif +#ifndef WSET_EXITCODE +#define WSET_EXITCODE(x, ret, sig) ((x) = (ret << 8) | (sig)) +#endif +#endif + +#ifndef HAVE_WAITPID +# ifdef HAVE_WAIT4 +# define waitpid(pid, statusp, flags) wait4(pid, statusp, flags, (char *)0) +# else +# ifdef HAVE_WAIT3 +# define waitpid(pid, statusp, flags) wait3(statusp, flags, (char *)0) +# endif +# endif +#endif Property changes on: vendor/NetBSD/bmake/20201101/wait.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property