Index: vendor/NetBSD/bmake/20200902/ChangeLog =================================================================== --- vendor/NetBSD/bmake/20200902/ChangeLog (nonexistent) +++ vendor/NetBSD/bmake/20200902/ChangeLog (revision 365363) @@ -0,0 +1,2735 @@ +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/20200902/FILES =================================================================== --- vendor/NetBSD/bmake/20200902/FILES (nonexistent) +++ vendor/NetBSD/bmake/20200902/FILES (revision 365363) @@ -0,0 +1,644 @@ +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 +strlist.c +strlist.h +suff.c +targ.c +trace.c +trace.h +unit-tests/Makefile +unit-tests/Makefile.config.in +unit-tests/archive.exp +unit-tests/archive.mk +unit-tests/archive-suffix.exp +unit-tests/archive-suffix.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-func.exp +unit-tests/cond-func.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-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/cond1.exp +unit-tests/cond1.mk +unit-tests/cond2.exp +unit-tests/cond2.mk +unit-tests/counter.exp +unit-tests/counter.mk +unit-tests/dep-colon.exp +unit-tests/dep-colon.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-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-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.exp +unit-tests/depsrc-usebefore.mk +unit-tests/depsrc-usebefore-double-colon.exp +unit-tests/depsrc-usebefore-double-colon.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.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.exp +unit-tests/dir.mk +unit-tests/dir-expand-path.exp +unit-tests/dir-expand-path.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-literal.exp +unit-tests/directive-export-literal.mk +unit-tests/directive-export.exp +unit-tests/directive-export.mk +unit-tests/directive-for.exp +unit-tests/directive-for.mk +unit-tests/directive-for-generating-endif.exp +unit-tests/directive-for-generating-endif.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-info.exp +unit-tests/directive-info.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/hash.exp +unit-tests/hash.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/lint.exp +unit-tests/lint.mk +unit-tests/make-exported.exp +unit-tests/make-exported.mk +unit-tests/misc.exp +unit-tests/misc.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.exp +unit-tests/opt-debug.mk +unit-tests/opt-debug-g1.exp +unit-tests/opt-debug-g1.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/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/suffixes.exp +unit-tests/suffixes.mk +unit-tests/sunshcmd.exp +unit-tests/sunshcmd.mk +unit-tests/sysv.exp +unit-tests/sysv.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.exp +unit-tests/var-op.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-includes.exp +unit-tests/varname-dot-includes.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-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.exp +unit-tests/varname-make_print_var_on_error.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/varquote.exp +unit-tests/varquote.mk +unit-tests/varshell.exp +unit-tests/varshell.mk +util.c +var.c +wait.h Index: vendor/NetBSD/bmake/20200902/LICENSE =================================================================== --- vendor/NetBSD/bmake/20200902/LICENSE (nonexistent) +++ vendor/NetBSD/bmake/20200902/LICENSE (revision 365363) @@ -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/20200902/Makefile =================================================================== --- vendor/NetBSD/bmake/20200902/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20200902/Makefile (revision 365363) @@ -0,0 +1,215 @@ +# $Id: Makefile,v 1.112 2020/08/28 16:26:17 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 \ + strlist.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/20200902/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/20200902/VERSION =================================================================== --- vendor/NetBSD/bmake/20200902/VERSION (nonexistent) +++ vendor/NetBSD/bmake/20200902/VERSION (revision 365363) @@ -0,0 +1,2 @@ +# keep this compatible with sh and make +_MAKE_VERSION=20200902 Index: vendor/NetBSD/bmake/20200902/arch.c =================================================================== --- vendor/NetBSD/bmake/20200902/arch.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/arch.c (revision 365363) @@ -0,0 +1,1275 @@ +/* $NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94"; +#else +__RCSID("$NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 Cleanup 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 +#include +#include +#ifdef HAVE_UTIME_H +#include +#endif + +#include "make.h" +#include "hash.h" +#include "dir.h" + +#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 + +static Lst archives; /* Lst of archives we've already examined */ + +typedef struct Arch { + char *name; /* Name of archive */ + Hash_Table 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 struct ar_hdr *ArchStatMember(const char *, const char *, Boolean); +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 + +#define AR_MAX_NAME_LEN (sizeof(arh.AR_NAME)-1) + +#ifdef CLEANUP +static void +ArchFree(void *ap) +{ + Arch *a = (Arch *)ap; + Hash_Search search; + Hash_Entry *entry; + + /* Free memory from hash entries */ + for (entry = Hash_EnumFirst(&a->members, &search); + entry != NULL; + entry = Hash_EnumNext(&search)) + free(Hash_GetValue(entry)); + + free(a->name); + free(a->fnametab); + Hash_DeleteTable(&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, Lst 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'; cp++) { + if (*cp == '$') { + /* + * Variable spec, so call the Var module to parse the puppy + * so we can safely advance beyond it... + */ + int length; + void *result_freeIt; + const char *result; + Boolean isError; + + result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, + &length, &result_freeIt); + isError = result == var_Error; + free(result_freeIt); + if (isError) + return FALSE; + + subLibName = TRUE; + cp += length - 1; + } + } + + *cp++ = '\0'; + if (subLibName) { + libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES); + } + + + 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 */ + + while (*cp != '\0' && *cp != ')' && isspace ((unsigned char)*cp)) { + cp++; + } + memName = cp; + while (*cp != '\0' && *cp != ')' && !isspace ((unsigned char)*cp)) { + if (*cp == '$') { + /* + * Variable spec, so call the Var module to parse the puppy + * so we can safely advance beyond it... + */ + int length; + void *freeIt; + const char *result; + Boolean isError; + + result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES, + &length, &freeIt); + isError = result == var_Error; + free(freeIt); + + if (isError) + return FALSE; + + doSubst = TRUE; + cp += length; + } 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; + + memName = Var_Subst(memName, ctxt, VARE_UNDEFERR | VARE_WANTRES); + + /* + * 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_FindNode(buf, TARG_CREATE); + + if (gn == NULL) { + free(buf); + return FALSE; + } else { + gn->type |= OP_ARCHV; + Lst_Append(nodeLst, gn); + } + } else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) { + /* + * Error in nested call -- free buffer and return FALSE + * ourselves. + */ + free(buf); + return FALSE; + } + /* + * Free buffer and continue with our work. + */ + free(buf); + } else if (Dir_HasWildcards(memName)) { + Lst members = Lst_Init(); + Buffer nameBuf; + + Buf_Init(&nameBuf, 0); + Dir_Expand(memName, dirSearchPath, members); + while (!Lst_IsEmpty(members)) { + char *member = Lst_Dequeue(members); + + Buf_Empty(&nameBuf); + Buf_AddStr(&nameBuf, libName); + Buf_AddStr(&nameBuf, "("); + Buf_AddStr(&nameBuf, member); + Buf_AddStr(&nameBuf, ")"); + free(member); + + gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); + if (gn == NULL) { + Buf_Destroy(&nameBuf, TRUE); + return FALSE; + } else { + /* + * 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); + } + } + Lst_Free(members); + Buf_Destroy(&nameBuf, TRUE); + } else { + Buffer nameBuf; + + Buf_Init(&nameBuf, 0); + Buf_AddStr(&nameBuf, libName); + Buf_AddStr(&nameBuf, "("); + Buf_AddStr(&nameBuf, memName); + Buf_AddStr(&nameBuf, ")"); + + gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE); + Buf_Destroy(&nameBuf, TRUE); + if (gn == NULL) { + return FALSE; + } else { + /* + * 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); + } + + /* + * We promised the pointer would be set up at the next non-space, so + * we must advance cp there before setting *linePtr... (note that on + * entrance to the loop, cp is guaranteed to point at a ')') + */ + do { + cp++; + } while (*cp != '\0' && isspace ((unsigned char)*cp)); + + *linePtr = cp; + return TRUE; +} + +/* See if the given archive is the one we are looking for. + * Called via Lst_Find. */ +static Boolean +ArchFindArchive(const void *ar, const void *desiredName) +{ + return strcmp(((const Arch *)ar)->name, desiredName) == 0; +} + +/*- + *----------------------------------------------------------------------- + * ArchStatMember -- + * 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. If it is a path, only the last + * component is used. + * hash TRUE if archive should be hashed if not already so. + * + * Results: + * A pointer to the current struct ar_hdr structure for the member. Note + * That no position is returned, so this is not useful for touching + * archive members. This is mostly because we have no assurances that + * The archive will remain constant after we read all the headers, so + * there's not much point in remembering the position... + *----------------------------------------------------------------------- + */ +static struct ar_hdr * +ArchStatMember(const char *archive, const char *member, Boolean hash) +{ + FILE * arch; /* Stream to archive */ + size_t size; /* Size of archive member */ + char magic[SARMAG]; + LstNode ln; /* Lst member containing archive descriptor */ + Arch *ar; /* Archive descriptor */ + Hash_Entry *he; /* Entry containing member's description */ + 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 final path components, not the entire thing, so we need + * to point 'member' to the final component, if there is one, to make + * the comparisons easier... + */ + const char *base = strrchr(member, '/'); + if (base != NULL) { + member = base + 1; + } + + ln = Lst_Find(archives, ArchFindArchive, archive); + if (ln != NULL) { + ar = LstNode_Datum(ln); + + he = Hash_FindEntry(&ar->members, member); + + if (he != NULL) { + return (struct ar_hdr *)Hash_GetValue(he); + } else { + /* 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); + } + if ((he = Hash_FindEntry(&ar->members, copy)) != NULL) + return (struct ar_hdr *)Hash_GetValue(he); + return NULL; + } + } + + 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; + } else { + 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; + Hash_InitTable(&ar->members, -1); + 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 && + isdigit((unsigned char)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)) { + fprintf(debug_file, "ArchStat: Extended format entry for %s\n", memName); + } + } +#endif + + he = Hash_CreateEntry(&ar->members, memName, NULL); + Hash_SetValue(he, bmake_malloc(sizeof(struct ar_hdr))); + memcpy(Hash_GetValue(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. + */ + he = Hash_FindEntry(&ar->members, member); + + if (he != NULL) { + return (struct ar_hdr *)Hash_GetValue(he); + } else { + return NULL; + } + +badarch: + fclose(arch); + Hash_DeleteTable(&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) { + if (DEBUG(ARCH)) { + fprintf(debug_file, "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) { + if (DEBUG(ARCH)) { + fprintf(debug_file, "Reading an SVR4 name table failed\n"); + } + return -1; + } + eptr = ar->fnametab + size; + for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++) + switch (*ptr) { + case '/': + entry++; + *ptr = '\0'; + break; + + case '\n': + break; + + default: + break; + } + if (DEBUG(ARCH)) { + fprintf(debug_file, "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]) { + if (DEBUG(ARCH)) { + fprintf(debug_file, "Could not parse SVR4 name %s\n", name); + } + return 2; + } + if (entry >= ar->fnamesize) { + if (DEBUG(ARCH)) { + fprintf(debug_file, "SVR4 entry offset %s is greater than %lu\n", + name, (unsigned long)ar->fnamesize); + } + return 2; + } + + if (DEBUG(ARCH)) { + fprintf(debug_file, "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 * base; + + 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 final path components, not the entire thing, so we need + * to point 'member' to the final component, if there is one, to make + * the comparisons easier... + */ + base = strrchr(member, '/'); + if (base != NULL) { + member = base + 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; + } else 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; + } else { + /* + * 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; + } + } else +#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 && + isdigit((unsigned char)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)) { + fprintf(debug_file, "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; + } + goto skip; + } else +#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 */ + char *p1, *p2; + + arch = ArchFindMember(Var_Value(ARCHIVE, gn, &p1), + Var_Value(MEMBER, gn, &p2), + &arh, "r+"); + + bmake_free(p1); + bmake_free(p2); + + 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 */ + char *p1, *p2; + + arhPtr = ArchStatMember(Var_Value(ARCHIVE, gn, &p1), + Var_Value(MEMBER, gn, &p2), + TRUE); + + bmake_free(p1); + bmake_free(p2); + + 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) +{ + LstNode ln; + GNode *pgn; + + Lst_Open(gn->parents); + while ((ln = Lst_Next(gn->parents)) != NULL) { + pgn = LstNode_Datum(ln); + + 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; + } + } + + Lst_Close(gn->parents); + + 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 + * path Search path + */ +void +Arch_FindLib(GNode *gn, Lst path) +{ + char *libName; /* file name for archive */ + size_t sz = strlen(gn->name) + 6 - 2; + + libName = bmake_malloc(sz); + snprintf(libName, sz, "lib%s.a", &gn->name[2]); + + 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 /* LIBRARIES */ +} + +/* 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->cmgn->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 (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) { + oodate = FALSE; + } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) || + (gn->mtime > now) || + (gn->cmgn != NULL && gn->mtime < gn->cmgn->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)) { + fprintf(debug_file, "%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC)); + } + oodate = (gn->cmgn == NULL || gn->cmgn->mtime > modTimeTOC); + } else { + /* + * A library w/o a table of contents is out-of-date + */ + if (DEBUG(ARCH) || DEBUG(MAKE)) { + fprintf(debug_file, "No t.o.c...."); + } + oodate = TRUE; + } +#else + oodate = FALSE; +#endif + } + return oodate; +} + +/* Initialize things for this module. */ +void +Arch_Init(void) +{ + archives = Lst_Init(); +} + +/* Clean up things for this 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/20200902/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/20200902/bmake.1 =================================================================== --- vendor/NetBSD/bmake/20200902/bmake.1 (nonexistent) +++ vendor/NetBSD/bmake/20200902/bmake.1 (revision 365363) @@ -0,0 +1,2455 @@ +.\" $NetBSD: make.1,v 1.289 2020/08/28 17:15:04 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 August 28, 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 integral +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 an integral 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/20200902/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/20200902/bmake.cat1 =================================================================== --- vendor/NetBSD/bmake/20200902/bmake.cat1 (nonexistent) +++ vendor/NetBSD/bmake/20200902/bmake.cat1 (revision 365363) @@ -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 + integral 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 an integral 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 August 28, 2020 FreeBSD 11.3 Index: vendor/NetBSD/bmake/20200902/bsd.after-import.mk =================================================================== --- vendor/NetBSD/bmake/20200902/bsd.after-import.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/bsd.after-import.mk (revision 365363) @@ -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/20200902/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/20200902/buf.c =================================================================== --- vendor/NetBSD/bmake/20200902/buf.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/buf.c (revision 365363) @@ -0,0 +1,223 @@ +/* $NetBSD: buf.c,v 1.37 2020/08/23 08:21:50 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: buf.c,v 1.37 2020/08/23 08:21:50 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: buf.c,v 1.37 2020/08/23 08:21:50 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/* Functions for automatically-expanded null-terminated buffers. */ + +#include +#include "make.h" + +/* Extend the buffer for adding a single byte. */ +void +Buf_Expand_1(Buffer *bp) +{ + bp->size += MAX(bp->size, 16); + bp->buffer = bmake_realloc(bp->buffer, bp->size); +} + +/* Add the given bytes to the buffer. */ +void +Buf_AddBytes(Buffer *bp, const char *bytesPtr, size_t numBytes) +{ + size_t count = bp->count; + char *ptr; + + if (__predict_false(count + numBytes >= bp->size)) { + bp->size += MAX(bp->size, numBytes + 16); + bp->buffer = bmake_realloc(bp->buffer, bp->size); + } + + ptr = bp->buffer + count; + bp->count = count + numBytes; + memcpy(ptr, bytesPtr, numBytes); + ptr[numBytes] = '\0'; +} + +/* Add the bytes between start and end to the buffer. */ +void +Buf_AddBytesBetween(Buffer *bp, const char *start, const char *end) +{ + Buf_AddBytes(bp, start, (size_t)(end - start)); +} + +/* Add the given string to the buffer. */ +void +Buf_AddStr(Buffer *bp, const char *str) +{ + Buf_AddBytes(bp, str, strlen(str)); +} + +/* Add the given number to the buffer. */ +void +Buf_AddInt(Buffer *bp, 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, + buf_size = max_sign_chars + max_decimal_digits + 1 + }; + char buf[buf_size]; + + size_t len = (size_t)snprintf(buf, sizeof buf, "%d", n); + Buf_AddBytes(bp, buf, 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 pointer to the data and optionally the length of the + * data in the buffer. */ +char * +Buf_GetAll(Buffer *bp, size_t *numBytesPtr) +{ + if (numBytesPtr != NULL) + *numBytesPtr = bp->count; + return bp->buffer; +} + +/* Mark the buffer as empty, so it can be filled with data again. */ +void +Buf_Empty(Buffer *bp) +{ + bp->count = 0; + bp->buffer[0] = '\0'; +} + +/* Initialize a buffer. + * If the given initial size is 0, a reasonable default is used. */ +void +Buf_Init(Buffer *bp, size_t size) +{ + if (size <= 0) { + size = 256; + } + bp->size = size; + bp->count = 0; + bp->buffer = bmake_malloc(size); + bp->buffer[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->buffer; + if (freeData) { + free(data); + data = NULL; + } + + buf->size = 0; + buf->count = 0; + buf->buffer = 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->size - buf->count >= BUF_COMPACT_LIMIT) { + /* We trust realloc to be smart */ + char *data = bmake_realloc(buf->buffer, buf->count + 1); + data[buf->count] = '\0'; + Buf_Destroy(buf, FALSE); + return data; + } +#endif + return Buf_Destroy(buf, FALSE); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/buf.h =================================================================== --- vendor/NetBSD/bmake/20200902/buf.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/buf.h (revision 365363) @@ -0,0 +1,125 @@ +/* $NetBSD: buf.h,v 1.28 2020/09/01 17:38:26 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 size; /* Allocated size of the buffer, including the null */ + size_t count; /* Number of bytes in buffer, excluding the null */ + char *buffer; /* 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 void MAKE_ATTR_UNUSED +Buf_AddByte(Buffer *bp, char byte) +{ + size_t count = ++bp->count; + char *ptr; + if (__predict_false(count >= bp->size)) + Buf_Expand_1(bp); + ptr = bp->buffer + count; + ptr[-1] = byte; + ptr[0] = 0; +} + +static inline size_t MAKE_ATTR_UNUSED +Buf_Size(const Buffer *bp) +{ + return bp->count; +} + +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/20200902/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/20200902/compat.c =================================================================== --- vendor/NetBSD/bmake/20200902/compat.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/compat.c (revision 365363) @@ -0,0 +1,751 @@ +/* $NetBSD: compat.c,v 1.139 2020/08/30 20:08:47 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: compat.c,v 1.139 2020/08/30 20:08:47 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: compat.c,v 1.139 2020/08/30 20:08:47 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 +#include + +#include "make.h" +#include "hash.h" +#include "dir.h" +#include "job.h" +#include "metachar.h" +#include "pathnames.h" + + +static GNode *curTarg = NULL; +static GNode *ENDNode; +static void CompatInterrupt(int); +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)) { + char *p1; + const char *file = Var_Value(TARGET, gn, &p1); + + if (!noExecute && eunlink(file) != -1) { + Error("*** %s removed", file); + } + + bmake_free(p1); + } +} + +/* 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", TARG_NOCREATE); + 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); + } +} + +/*- + *----------------------------------------------------------------------- + * CompatRunCommand -- + * 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. + * + * Side Effects: + * The node's 'made' field may be set to ERROR. + * + *----------------------------------------------------------------------- + */ +int +CompatRunCommand(void *cmdp, void *gnp) +{ + char *cmdStart; /* Start of expanded command */ + char *cp, *bp; + Boolean silent, /* Don't print command */ + 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 */ + LstNode 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 */ + char * volatile cmd = (char *)cmdp; + GNode *gn = (GNode *)gnp; + + silent = (gn->type & OP_SILENT) != 0; + errCheck = !(gn->type & OP_IGNORE); + doIt = FALSE; + + cmdNode = Lst_FindDatum(gn->commands, cmd); + cmdStart = Var_Subst(cmd, gn, VARE_WANTRES); + + /* + * brk_string will return an argv with a NULL in av[0], thus causing + * execvp to choke and die horribly. Besides, how can we execute a null + * command? In any case, we warn the user that the command expanded to + * nothing (is this the right thing to do?). + */ + + if (*cmdStart == '\0') { + free(cmdStart); + return 0; + } + cmd = cmdStart; + LstNode_Set(cmdNode, cmdStart); + + if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { + assert(ENDNode != NULL); + 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 (isspace((unsigned char)*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, FALSE); +#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 || NoExecute(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 && NoExecute(gn)) { + return 0; + } + if (DEBUG(JOB)) + fprintf(debug_file, "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)); + execError("exec", av[0]); + _exit(1); + } + + 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 (1) { + + while ((retstat = wait(&reason)) != cpid) { + if (retstat > 0) + JobReapChild(retstat, reason, FALSE); /* not ours? */ + if (retstat == -1 && errno != EINTR) { + break; + } + } + + if (retstat > -1) { + 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)) { + fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ", + gn->name); + for (cp = cmd; *cp; ) { + if (isspace((unsigned char)*cp)) { + fprintf(debug_file, " "); + while (isspace((unsigned char)*cp)) + cp++; + } else { + fprintf(debug_file, "%c", *cp); + cp++; + } + } + fprintf(debug_file, "\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 (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; + } + } + break; + } else { + Fatal("error in wait: %d: %s", retstat, strerror(errno)); + /*NOTREACHED*/ + } + } + free(cmdStart); + compatChild = 0; + if (compatSigno) { + bmake_signal(compatSigno, SIG_DFL); + kill(myPid, compatSigno); + } + + return status; +} + +/*- + *----------------------------------------------------------------------- + * Compat_Make -- + * Make a target. + * + * Input: + * gnp The node to make + * pgnp Parent to abort if necessary + * + * Results: + * 0 + * + * Side Effects: + * If an error is detected and not being ignored, the process exits. + * + *----------------------------------------------------------------------- + */ +int +Compat_Make(void *gnp, void *pgnp) +{ + GNode *gn = (GNode *)gnp; + GNode *pgn = (GNode *)pgnp; + + if (!shellName) /* we came here from jobs */ + Shell_Init(); + if (gn->made == UNMADE && (gn == pgn || (pgn->type & OP_MADE) == 0)) { + /* + * 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) == 0) + Suff_FindDeps(gn); + Lst_ForEach(gn->children, Compat_Make, gn); + if ((gn->flags & REMAKE) == 0) { + gn->made = ABORTED; + pgn->flags &= ~(unsigned)REMAKE; + goto cohorts; + } + + if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) { + char *p1; + Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); + bmake_free(p1); + } + + /* + * All the children were made ok. Now cmgn->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. + */ + if (DEBUG(MAKE)) { + fprintf(debug_file, "Examining %s...", gn->name); + } + if (! Make_OODate(gn)) { + gn->made = UPTODATE; + if (DEBUG(MAKE)) { + fprintf(debug_file, "up-to-date.\n"); + } + goto cohorts; + } else if (DEBUG(MAKE)) { + fprintf(debug_file, "out-of-date.\n"); + } + + /* + * If the user is just seeing if something is out-of-date, exit now + * to tell him/her "yes". + */ + if (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 (!touchFlag || (gn->type & OP_MAKE)) { + curTarg = gn; +#ifdef USE_META + if (useMeta && !NoExecute(gn)) { + meta_job_start(NULL, gn); + } +#endif + Lst_ForEach(gn->commands, CompatRunCommand, gn); + curTarg = NULL; + } else { + Job_Touch(gn, (gn->type & OP_SILENT) != 0); + } + } else { + gn->made = ERROR; + } +#ifdef USE_META + if (useMeta && !NoExecute(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 (keepgoing) { + pgn->flags &= ~(unsigned)REMAKE; + } else { + PrintOnError(gn, "\nStop."); + exit(1); + } + } else if (gn->made == ERROR) { + /* + * Already had an error when making this beastie. Tell the parent + * to abort. + */ + pgn->flags &= ~(unsigned)REMAKE; + } else { + if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) { + char *p1; + const char *target = Var_Value(TARGET, gn, &p1); + Var_Set(IMPSRC, target != NULL ? target : "", pgn); + bmake_free(p1); + } + 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: + Lst_ForEach(gn->cohorts, Compat_Make, pgnp); + return 0; +} + +/* Initialize this module and start making. + * + * Input: + * targs The target nodes to re-create + */ +void +Compat_Run(Lst 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); + } + + ENDNode = Targ_FindNode(".END", TARG_CREATE); + ENDNode->type = OP_SPECIAL; + /* + * If the user has defined a .BEGIN target, execute the commands attached + * to it. + */ + if (!queryFlag) { + gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); + 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 += 1; + } + } + + /* + * If the user has defined a .END target, run its commands. + */ + if (errors == 0) { + Compat_Make(ENDNode, ENDNode); + if (gn->made == ERROR) { + PrintOnError(gn, "\nStop."); + exit(1); + } + } +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/cond.c =================================================================== --- vendor/NetBSD/bmake/20200902/cond.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/cond.c (revision 365363) @@ -0,0 +1,1282 @@ +/* $NetBSD: cond.c,v 1.106 2020/08/29 13:38:48 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: cond.c,v 1.106 2020/08/29 13:38:48 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cond.c 8.2 (Berkeley) 1/2/94"; +#else +__RCSID("$NetBSD: cond.c,v 1.106 2020/08/29 13:38:48 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * cond.c -- + * Functions to handle conditionals in a makefile. + * + * Interface: + * Cond_Eval Evaluate the conditional in the passed line. + * + */ + +#include + +#include "make.h" +#include "dir.h" + +/* + * 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. + * + * Tokens are scanned from the 'condExpr' string. The scanner (CondToken) + * will return TOK_AND for '&' and '&&', TOK_OR for '|' and '||', + * TOK_NOT for '!', TOK_LPAREN for '(', TOK_RPAREN for ')' and will evaluate + * the other terminal symbols, using either the default function or the + * function given in the terminal, and return the result as 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 (CondE, CondF and CondT) return TOK_ERROR on + * error. + */ +typedef enum { + TOK_FALSE = 0, TOK_TRUE = 1, TOK_AND, TOK_OR, TOK_NOT, + TOK_LPAREN, TOK_RPAREN, TOK_EOF, TOK_NONE, TOK_ERROR +} Token; + +static Token CondE(Boolean); +static CondEvalResult do_Cond_EvalExpression(Boolean *); + +static const struct If *if_info; /* Info for current statement */ +static const char *condExpr; /* The expression to parse */ +static Token condPushBack = TOK_NONE; /* Single push-back token used in + * parsing */ + +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. + * TRUE when Cond_EvalExpression is called from Cond_Eval (.if etc) + * FALSE when Cond_EvalExpression is called from var.c:ApplyModifiers + * since lhs is already expanded and we cannot tell if + * it was a variable reference or not. + */ +static Boolean lhsStrict; + +static int +istoken(const char *str, const char *tok, size_t len) +{ + return strncmp(str, tok, len) == 0 && !isalpha((unsigned char)str[len]); +} + +/* Push back the most recent token read. We only need one level of + * this, so the thing is just stored in 'condPushback'. */ +static void +CondPushBack(Token t) +{ + condPushBack = t; +} + +/*- + * Parse the argument of a built-in function. + * + * Results: + * The length of the argument. + * *argPtr receives the argument as string. + * *linePtr is updated to point behind the ')' of the function call. + */ +static int +CondGetArg(Boolean doEval, const char **linePtr, char **argPtr, + const char *func) +{ + const char *cp; + Buffer buf; + int paren_depth; + char ch; + size_t argLen; + + cp = *linePtr; + if (func != NULL) + /* Skip opening '(' - verified by caller */ + cp++; + + if (*cp == '\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... + */ + *argPtr = NULL; + return 0; + } + + while (*cp == ' ' || *cp == '\t') { + cp++; + } + + /* + * Create a buffer for the argument and start it out at 16 characters + * long. Why 16? Why not? + */ + Buf_Init(&buf, 16); + + paren_depth = 0; + for (;;) { + ch = *cp; + if (ch == 0 || ch == ' ' || ch == '\t') + break; + if ((ch == '&' || ch == '|') && paren_depth == 0) + break; + if (*cp == '$') { + /* + * 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 do it too. Nor do we return an error, + * though perhaps we should... + */ + int len; + void *freeIt; + VarEvalFlags eflags = VARE_UNDEFERR | (doEval ? VARE_WANTRES : 0); + const char *cp2 = Var_Parse(cp, VAR_CMD, eflags, &len, &freeIt); + Buf_AddStr(&buf, cp2); + free(freeIt); + cp += len; + continue; + } + if (ch == '(') + paren_depth++; + else if (ch == ')' && --paren_depth < 0) + break; + Buf_AddByte(&buf, *cp); + cp++; + } + + *argPtr = Buf_GetAll(&buf, &argLen); + Buf_Destroy(&buf, FALSE); + + while (*cp == ' ' || *cp == '\t') { + cp++; + } + + if (func != NULL && *cp++ != ')') { + Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()", + func); + return 0; + } + + *linePtr = cp; + return argLen; +} + +/* Test whether the given variable is defined. */ +static Boolean +CondDoDefined(int argLen MAKE_ATTR_UNUSED, const char *arg) +{ + char *freeIt; + Boolean result = Var_Value(arg, VAR_CMD, &freeIt) != NULL; + bmake_free(freeIt); + return result; +} + +/* Wrapper around Str_Match, to be used by Lst_Find. */ +static Boolean +CondFindStrMatch(const void *string, const void *pattern) +{ + return Str_Match(string, pattern); +} + +/* See if the given target is being made. */ +static Boolean +CondDoMake(int argLen MAKE_ATTR_UNUSED, const char *arg) +{ + return Lst_Find(create, CondFindStrMatch, arg) != NULL; +} + +/* See if the given file exists. */ +static Boolean +CondDoExists(int argLen MAKE_ATTR_UNUSED, const char *arg) +{ + Boolean result; + char *path; + + path = Dir_FindFile(arg, dirSearchPath); + if (DEBUG(COND)) { + fprintf(debug_file, "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 +CondDoTarget(int argLen MAKE_ATTR_UNUSED, const char *arg) +{ + GNode *gn; + + gn = Targ_FindNode(arg, TARG_NOCREATE); + return gn != NULL && !OP_NOP(gn->type); +} + +/* See if the given node exists and is an actual target with commands + * associated with it. */ +static Boolean +CondDoCommands(int argLen MAKE_ATTR_UNUSED, const char *arg) +{ + GNode *gn; + + gn = Targ_FindNode(arg, TARG_NOCREATE); + return gn != NULL && !OP_NOP(gn->type) && !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 +CondCvtArg(const char *str, double *value) +{ + char *eptr, ech; + unsigned long l_val; + double d_val; + + errno = 0; + if (!*str) { + *value = (double)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; +} + +/*- + * Get a string from a variable reference or an optionally quoted + * string. This is called for the lhs and rhs of string compares. + * + * Results: + * Returns the string, absent any quotes, or NULL on error. + * Sets quoted if the string was quoted. + * Sets freeIt if needed. + * + * Side Effects: + * Moves condExpr past the end of this token. + */ +/* coverity:[+alloc : arg-*2] */ +static const char * +CondGetString(Boolean doEval, Boolean *quoted, void **freeIt, Boolean strictLHS) +{ + Buffer buf; + const char *cp; + const char *str; + int len; + Boolean qt; + const char *start; + VarEvalFlags eflags; + + Buf_Init(&buf, 0); + str = NULL; + *freeIt = NULL; + *quoted = qt = *condExpr == '"' ? 1 : 0; + if (qt) + condExpr++; + for (start = condExpr; *condExpr && str == NULL; condExpr++) { + switch (*condExpr) { + case '\\': + if (condExpr[1] != '\0') { + condExpr++; + Buf_AddByte(&buf, *condExpr); + } + break; + case '"': + if (qt) { + condExpr++; /* we don't want the quotes */ + goto got_str; + } else + Buf_AddByte(&buf, *condExpr); /* likely? */ + break; + case ')': + case '!': + case '=': + case '>': + case '<': + case ' ': + case '\t': + if (!qt) + goto got_str; + else + Buf_AddByte(&buf, *condExpr); + break; + case '$': + /* if we are in quotes, then an undefined variable is ok */ + eflags = ((!qt && doEval) ? VARE_UNDEFERR : 0) | + (doEval ? VARE_WANTRES : 0); + str = Var_Parse(condExpr, VAR_CMD, eflags, &len, freeIt); + if (str == var_Error) { + 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; + } + condExpr += len; + /* + * If the '$' was first char (no quotes), and we are + * followed by space, the operator or end of expression, + * we are done. + */ + if ((condExpr == start + len) && + (*condExpr == '\0' || + isspace((unsigned char)*condExpr) || + strchr("!=><)", *condExpr))) { + goto cleanup; + } + /* + * Nope, we better copy str to buf + */ + for (cp = str; *cp; cp++) { + Buf_AddByte(&buf, *cp); + } + if (*freeIt) { + free(*freeIt); + *freeIt = NULL; + } + str = NULL; /* not finished yet */ + condExpr--; /* don't skip over next char */ + break; + default: + if (strictLHS && !qt && *start != '$' && + !isdigit((unsigned char)*start)) { + /* lhs must be quoted, a variable reference or number */ + if (*freeIt) { + free(*freeIt); + *freeIt = NULL; + } + str = NULL; + goto cleanup; + } + Buf_AddByte(&buf, *condExpr); + break; + } + } +got_str: + *freeIt = Buf_GetAll(&buf, NULL); + str = *freeIt; +cleanup: + Buf_Destroy(&buf, FALSE); + return str; +} + +/* The different forms of #if's. */ +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)(int, const char *); /* Default function to apply */ +} ifs[] = { + { "def", 3, FALSE, CondDoDefined }, + { "ndef", 4, TRUE, CondDoDefined }, + { "make", 4, FALSE, CondDoMake }, + { "nmake", 5, TRUE, CondDoMake }, + { "", 0, FALSE, CondDoDefined }, + { NULL, 0, FALSE, NULL } +}; + +/*- + * Return the next token from the input. + * + * Side Effects: + * condPushback will be set back to TOK_NONE if it is used. + */ +static Token +compare_expression(Boolean doEval) +{ + Token t; + const char *lhs; + const char *rhs; + const char *op; + void *lhsFree; + void *rhsFree; + Boolean lhsQuoted; + Boolean rhsQuoted; + double left, right; + + t = TOK_ERROR; + rhs = NULL; + lhsFree = rhsFree = NULL; + lhsQuoted = rhsQuoted = FALSE; + + /* + * Parse the variable spec and skip over it, saving its + * value in lhs. + */ + lhs = CondGetString(doEval, &lhsQuoted, &lhsFree, lhsStrict); + if (!lhs) + goto done; + + /* + * Skip whitespace to get to the operator + */ + while (isspace((unsigned char)*condExpr)) + condExpr++; + + /* + * Make sure the operator is a valid one. If it isn't a + * known relational operator, pretend we got a + * != 0 comparison. + */ + op = condExpr; + switch (*condExpr) { + case '!': + case '=': + case '<': + case '>': + if (condExpr[1] == '=') { + condExpr += 2; + } else { + condExpr += 1; + } + break; + default: + if (!doEval) { + t = TOK_FALSE; + goto done; + } + /* For .ifxxx "..." check for non-empty string. */ + if (lhsQuoted) { + t = lhs[0] != 0; + goto done; + } + /* For .ifxxx compare against zero */ + if (CondCvtArg(lhs, &left)) { + t = left != 0.0; + goto done; + } + /* For .if ${...} check for non-empty string (defProc is ifdef). */ + if (if_info->form[0] == 0) { + t = lhs[0] != 0; + goto done; + } + /* Otherwise action default test ... */ + t = if_info->defProc(strlen(lhs), lhs) != if_info->doNot; + goto done; + } + + while (isspace((unsigned char)*condExpr)) + condExpr++; + + if (*condExpr == '\0') { + Parse_Error(PARSE_WARNING, + "Missing right-hand-side of operator"); + goto done; + } + + rhs = CondGetString(doEval, &rhsQuoted, &rhsFree, FALSE); + if (!rhs) + goto done; + + if (!doEval) { + t = TOK_FALSE; + goto done; + } + + if (rhsQuoted || lhsQuoted) { + do_string_compare: + if (((*op != '!') && (*op != '=')) || (op[1] != '=')) { + Parse_Error(PARSE_WARNING, + "String comparison operator should be either == or !="); + goto done; + } + + if (DEBUG(COND)) { + fprintf(debug_file, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", + lhs, rhs, op); + } + /* + * Null-terminate rhs and perform the comparison. + * t is set to the result. + */ + if (*op == '=') { + t = strcmp(lhs, rhs) == 0; + } else { + t = strcmp(lhs, rhs) != 0; + } + } else { + /* + * rhs is either a float or an integer. Convert both the + * lhs and the rhs to a double and compare the two. + */ + + if (!CondCvtArg(lhs, &left) || !CondCvtArg(rhs, &right)) + goto do_string_compare; + + if (DEBUG(COND)) { + fprintf(debug_file, "left = %f, right = %f, op = %.2s\n", left, + right, op); + } + switch (op[0]) { + case '!': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, + "Unknown operator"); + goto done; + } + t = (left != right); + break; + case '=': + if (op[1] != '=') { + Parse_Error(PARSE_WARNING, + "Unknown operator"); + goto done; + } + t = (left == right); + break; + case '<': + if (op[1] == '=') { + t = (left <= right); + } else { + t = (left < right); + } + break; + case '>': + if (op[1] == '=') { + t = (left >= right); + } else { + t = (left > right); + } + break; + } + } + +done: + free(lhsFree); + free(rhsFree); + return t; +} + +static int +get_mpt_arg(Boolean doEval, const char **linePtr, char **argPtr, + const char *func MAKE_ATTR_UNUSED) +{ + /* + * Use Var_Parse to parse the spec in parens and return + * TOK_TRUE if the resulting string is empty. + */ + int length; + void *val_freeIt; + const char *val; + const char *cp = *linePtr; + + /* We do all the work here and return the result as the length */ + *argPtr = NULL; + + val = Var_Parse(cp - 1, VAR_CMD, doEval ? VARE_WANTRES : 0, &length, + &val_freeIt); + /* + * Advance *linePtr to beyond the closing ). Note that + * we subtract one because 'length' is calculated from 'cp - 1'. + */ + *linePtr = cp - 1 + length; + + if (val == var_Error) { + free(val_freeIt); + return -1; + } + + /* A variable is empty when it just contains spaces... 4/15/92, christos */ + while (isspace((unsigned char)val[0])) + val++; + + /* + * For consistency with the other functions we can't generate the + * true/false here. + */ + length = *val ? 2 : 1; + free(val_freeIt); + return length; +} + +static Boolean +CondDoEmpty(int arglen, const char *arg MAKE_ATTR_UNUSED) +{ + return arglen == 1; +} + +static Token +compare_function(Boolean doEval) +{ + static const struct fn_def { + const char *fn_name; + size_t fn_name_len; + int (*fn_getarg)(Boolean, const char **, char **, const char *); + Boolean (*fn_proc)(int, const char *); + } fn_defs[] = { + { "defined", 7, CondGetArg, CondDoDefined }, + { "make", 4, CondGetArg, CondDoMake }, + { "exists", 6, CondGetArg, CondDoExists }, + { "empty", 5, get_mpt_arg, CondDoEmpty }, + { "target", 6, CondGetArg, CondDoTarget }, + { "commands", 8, CondGetArg, CondDoCommands }, + { NULL, 0, NULL, NULL }, + }; + const struct fn_def *fn_def; + Token t; + char *arg = NULL; + int arglen; + const char *cp = condExpr; + const char *cp1; + + for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) { + if (!istoken(cp, fn_def->fn_name, fn_def->fn_name_len)) + continue; + cp += fn_def->fn_name_len; + /* There can only be whitespace before the '(' */ + while (isspace((unsigned char)*cp)) + cp++; + if (*cp != '(') + break; + + arglen = fn_def->fn_getarg(doEval, &cp, &arg, fn_def->fn_name); + if (arglen <= 0) { + condExpr = cp; + return arglen < 0 ? TOK_ERROR : TOK_FALSE; + } + /* Evaluate the argument using the required function. */ + t = !doEval || fn_def->fn_proc(arglen, arg); + free(arg); + condExpr = cp; + return t; + } + + /* Push anything numeric through the compare expression */ + cp = condExpr; + if (isdigit((unsigned char)cp[0]) || strchr("+-", cp[0])) + return compare_expression(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 = CondGetArg(doEval, &cp, &arg, NULL); + for (cp1 = cp; isspace((unsigned char)*cp1); cp1++) + continue; + if (*cp1 == '=' || *cp1 == '!') + return compare_expression(doEval); + condExpr = 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 || if_info->defProc(arglen, arg) != if_info->doNot; + free(arg); + return t; +} + +static Token +CondToken(Boolean doEval) +{ + Token t; + + t = condPushBack; + if (t != TOK_NONE) { + condPushBack = TOK_NONE; + return t; + } + + while (*condExpr == ' ' || *condExpr == '\t') { + condExpr++; + } + + switch (*condExpr) { + + case '(': + condExpr++; + return TOK_LPAREN; + + case ')': + condExpr++; + return TOK_RPAREN; + + case '|': + if (condExpr[1] == '|') { + condExpr++; + } + condExpr++; + return TOK_OR; + + case '&': + if (condExpr[1] == '&') { + condExpr++; + } + condExpr++; + return TOK_AND; + + case '!': + condExpr++; + return TOK_NOT; + + case '#': + case '\n': + case '\0': + return TOK_EOF; + + case '"': + case '$': + return compare_expression(doEval); + + default: + return compare_function(doEval); + } +} + +/*- + *----------------------------------------------------------------------- + * CondT -- + * Parse a single term in the expression. This consists of a terminal + * symbol or TOK_NOT and a terminal symbol (not including the binary + * operators): + * T -> defined(variable) | make(target) | exists(file) | symbol + * T -> ! T | ( E ) + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR. + * + * Side Effects: + * Tokens are consumed. + * + *----------------------------------------------------------------------- + */ +static Token +CondT(Boolean doEval) +{ + Token t; + + t = CondToken(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 = CondE(doEval); + if (t != TOK_ERROR) { + if (CondToken(doEval) != TOK_RPAREN) { + t = TOK_ERROR; + } + } + } else if (t == TOK_NOT) { + t = CondT(doEval); + if (t == TOK_TRUE) { + t = TOK_FALSE; + } else if (t == TOK_FALSE) { + t = TOK_TRUE; + } + } + return t; +} + +/*- + *----------------------------------------------------------------------- + * CondF -- + * Parse a conjunctive factor (nice name, wot?) + * F -> T && F | T + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR + * + * Side Effects: + * Tokens are consumed. + * + *----------------------------------------------------------------------- + */ +static Token +CondF(Boolean doEval) +{ + Token l, o; + + l = CondT(doEval); + if (l != TOK_ERROR) { + o = CondToken(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 an TOK_ERROR or no. + */ + if (l == TOK_TRUE) { + l = CondF(doEval); + } else { + (void)CondF(FALSE); + } + } else { + /* + * F -> T + */ + CondPushBack(o); + } + } + return l; +} + +/*- + *----------------------------------------------------------------------- + * CondE -- + * Main expression production. + * E -> F || E | F + * + * Results: + * TOK_TRUE, TOK_FALSE or TOK_ERROR. + * + * Side Effects: + * Tokens are, of course, consumed. + * + *----------------------------------------------------------------------- + */ +static Token +CondE(Boolean doEval) +{ + Token l, o; + + l = CondF(doEval); + if (l != TOK_ERROR) { + o = CondToken(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 = CondE(doEval); + } else { + (void)CondE(FALSE); + } + } else { + /* + * E -> F + */ + CondPushBack(o); + } + } + return l; +} + +static CondEvalResult +do_Cond_EvalExpression(Boolean *value) +{ + + switch (CondE(TRUE)) { + case TOK_TRUE: + if (CondToken(TRUE) == TOK_EOF) { + *value = TRUE; + return COND_PARSE; + } + break; + case TOK_FALSE: + if (CondToken(TRUE) == TOK_EOF) { + *value = FALSE; + return COND_PARSE; + } + break; + default: + case TOK_ERROR: + break; + } + + return COND_INVALID; +} + +/*- + *----------------------------------------------------------------------- + * Cond_EvalExpression -- + * Evaluate an expression in the passed line. The expression + * consists of &&, ||, !, make(target), defined(variable) + * 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 + * + * Side Effects: + * Any effects from evaluating the variables. + *----------------------------------------------------------------------- + */ +CondEvalResult +Cond_EvalExpression(const struct If *info, char *line, Boolean *value, + int eprint, Boolean strictLHS) +{ + static const struct If *dflt_info; + const struct If *sv_if_info = if_info; + const char *sv_condExpr = condExpr; + Token sv_condPushBack = condPushBack; + int rval; + + lhsStrict = strictLHS; + + while (*line == ' ' || *line == '\t') + line++; + + 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); + + if_info = info; + condExpr = line; + condPushBack = TOK_NONE; + + rval = do_Cond_EvalExpression(value); + + if (rval == COND_INVALID && eprint) + Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line); + + if_info = sv_if_info; + condExpr = sv_condExpr; + condPushBack = sv_condPushBack; + + return rval; +} + + +/*- + *----------------------------------------------------------------------- + * Cond_Eval -- + * Evaluate the conditional in the passed line. The line + * looks like this: + * . + * where is any of if, ifmake, ifnmake, ifdef, + * ifndef, elif, elifmake, elifnmake, elifdef, elifndef + * and consists of &&, ||, !, make(target), defined(variable) + * and parenthetical groupings thereof. + * + * Input: + * line Line to parse + * + * Results: + * COND_PARSE if should parse lines after the conditional + * COND_SKIP if should skip lines after the conditional + * COND_INVALID if not a valid conditional. + * + * 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'. + *----------------------------------------------------------------------- + */ +CondEvalResult +Cond_Eval(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; + int level; /* Level at which to report errors. */ + enum if_states state; + + level = PARSE_FATAL; + 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 (!istoken(line + 1, "ndif", 4)) + return COND_INVALID; + /* End of conditional section */ + if (cond_depth == cond_min_depth) { + Parse_Error(level, "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 (istoken(line, "se", 2)) { + /* It is else... */ + if (cond_depth == cond_min_depth) { + Parse_Error(level, "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 (istoken(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(level, "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 expresssion */ + if (Cond_EvalExpression(ifp, line, &value, 1, 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) +{ + int open_conds = cond_depth - cond_min_depth; + + if (open_conds != 0 || saved_depth > cond_depth) { + Parse_Error(PARSE_FATAL, "%d 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) +{ + int depth = cond_min_depth; + + cond_min_depth = cond_depth; + return depth; +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/dir.c =================================================================== --- vendor/NetBSD/bmake/20200902/dir.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/dir.c (revision 365363) @@ -0,0 +1,1770 @@ +/* $NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; +#else +__RCSID("$NetBSD: dir.c,v 1.135 2020/09/02 04:32:13 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * dir.c -- + * Directory searching using wildcards and/or normal names... + * Used both for source wildcarding in the Makefile and for finding + * implicit sources. + * + * The interface for this module is: + * Dir_Init Initialize the module. + * + * Dir_InitCur Set the cur Path. + * + * Dir_InitDot Set the dot Path. + * + * Dir_End Cleanup the module. + * + * Dir_SetPATH Set ${.PATH} to reflect state of dirSearchPath. + * + * Dir_HasWildcards Returns TRUE if the name given it needs to + * be wildcard-expanded. + * + * Dir_Expand Given a pattern and a path, return a Lst of names + * which match the pattern on the search path. + * + * Dir_FindFile Searches for a file on a given search path. + * If it exists, the entire path is returned. + * Otherwise NULL is returned. + * + * Dir_FindHereOrAbove Search for a path in the current directory and + * then all the directories above it in turn until + * the path is found or we reach the root ("/"). + * + * Dir_MTime Return the modification time of a node. The file + * is searched for along the default search path. + * The path and mtime fields of the node are filled + * in. + * + * Dir_AddDir Add a directory to a search path. + * + * Dir_MakeFlags Given a search path and a command flag, create + * a string with each of the directories in the path + * preceded by the command flag and all of them + * separated by a space. + * + * Dir_Destroy Destroy an element of a search path. Frees up all + * things that can be freed for the element as long + * as the element is no longer referenced by any other + * search path. + * Dir_ClearPath Resets a search path to the empty list. + * + * For debugging: + * Dir_PrintDirectories Print stats about the directory cache. + */ + +#include +#include + +#include +#include +#include + +#include "make.h" +#include "dir.h" +#include "job.h" + + +#define DIR_DEBUG0(fmt) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt) + +#define DIR_DEBUG1(fmt, arg1) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt, arg1) + +#define DIR_DEBUG2(fmt, arg1, arg2) \ + if (!DEBUG(DIR)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2) + + +/* + * A search path consists of a Lst of Path structures. A Path structure + * has in it the name of the directory and a hash table 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. + * + * A list of all previously-read directories is kept in the + * openDirectories Lst. This list 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 hashing 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 Path structure and + * verify the directory hasn't changed since the contents were + * hashed. 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 + * rehashing could seriously degrade performance. It might be + * good in such cases to keep track of the number of rehashes + * 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. + */ + +Lst dirSearchPath; /* main search path */ + +static Lst openDirectories; /* the list of all open directories */ + +/* + * Variables for gathering statistics on the efficiency of the hashing + * 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 Path *dot; /* contents of current directory */ +static Path *cur; /* contents of current directory, if not dot */ +static Path *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 Hash_Table mtimes; + +static Hash_Table lmtimes; /* same as mtimes but for lstat */ + +static void DirExpandCurly(const char *, const char *, Lst, Lst); +static void DirExpandInt(const char *, Lst, Lst); +static int DirPrintWord(void *, void *); +static int DirPrintDir(void *, void *); +static char *DirLookup(Path *, const char *, const char *, Boolean); +static char *DirLookupSubdir(Path *, const char *); +static char *DirFindDot(Boolean, const char *, const char *); +static char *DirLookupAbs(Path *, const char *, const char *); + + +/* + * 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 { + 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(Hash_Table *htp, const char *pathname, struct make_stat *mst, + CachedStatsFlags flags) +{ + Hash_Entry *entry; + struct stat sys_st; + struct cache_st *cst; + int rc; + + if (!pathname || !pathname[0]) + return -1; + + entry = Hash_FindEntry(htp, pathname); + + if (entry && !(flags & CST_UPDATE)) { + cst = Hash_GetValue(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 = Hash_CreateEntry(htp, pathname, NULL); + if (Hash_GetValue(entry) == NULL) { + Hash_SetValue(entry, bmake_malloc(sizeof(*cst))); + memset(Hash_GetValue(entry), 0, sizeof(*cst)); + } + cst = Hash_GetValue(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 things for this module. */ +void +Dir_Init(void) +{ + dirSearchPath = Lst_Init(); + openDirectories = Lst_Init(); + Hash_InitTable(&mtimes, 0); + Hash_InitTable(&lmtimes, 0); +} + +void +Dir_InitDir(const char *cdname) +{ + Dir_InitCur(cdname); + + dotLast = bmake_malloc(sizeof(Path)); + dotLast->refCount = 1; + dotLast->hits = 0; + dotLast->name = bmake_strdup(".DOTLAST"); + Hash_InitTable(&dotLast->files, -1); +} + +/* + * Called by Dir_InitDir and whenever .CURDIR is assigned to. + */ +void +Dir_InitCur(const char *cdname) +{ + Path *p; + + if (cdname != NULL) { + /* + * Our build directory is not the same as our source directory. + * Keep this one around too. + */ + if ((p = Dir_AddDir(NULL, cdname))) { + p->refCount += 1; + if (cur && cur != p) { + /* + * We've been here before, cleanup. + */ + cur->refCount -= 1; + Dir_Destroy(cur); + } + cur = p; + } + } +} + +/* (Re)initialize "dot" (current/object directory) path hash. + * Some directories may be opened. */ +void +Dir_InitDot(void) +{ + if (dot != NULL) { + LstNode ln; + + /* Remove old entry from openDirectories, but do not destroy. */ + ln = Lst_FindDatum(openDirectories, dot); + Lst_Remove(openDirectories, ln); + } + + 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 += 1; + Dir_SetPATH(); /* initialize */ +} + +/* Clean up things for this module. */ +void +Dir_End(void) +{ +#ifdef CLEANUP + if (cur) { + cur->refCount -= 1; + Dir_Destroy(cur); + } + dot->refCount -= 1; + dotLast->refCount -= 1; + Dir_Destroy(dotLast); + Dir_Destroy(dot); + Dir_ClearPath(dirSearchPath); + Lst_Free(dirSearchPath); + Dir_ClearPath(openDirectories); + Lst_Free(openDirectories); + Hash_DeleteTable(&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) +{ + LstNode ln; /* a list element */ + Path *p; + Boolean hasLastDot = FALSE; /* true if we should search dot last */ + + Var_Delete(".PATH", VAR_GLOBAL); + + Lst_Open(dirSearchPath); + if ((ln = Lst_First(dirSearchPath)) != NULL) { + p = LstNode_Datum(ln); + if (p == 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); + } + + while ((ln = Lst_Next(dirSearchPath)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if (p == dot && hasLastDot) + continue; + Var_Append(".PATH", p->name, VAR_GLOBAL); + } + + if (hasLastDot) { + if (dot) + Var_Append(".PATH", dot->name, VAR_GLOBAL); + if (cur) + Var_Append(".PATH", cur->name, VAR_GLOBAL); + } + Lst_Close(dirSearchPath); +} + +/* See if the Path structure describes the same directory as the + * given one by comparing their names. Called from Dir_AddDir via + * Lst_Find when searching the list of open directories. */ +static Boolean +DirFindName(const void *p, const void *desiredName) +{ + return strcmp(((const Path *)p)->name, desiredName) == 0; +} + +/* See if the given name has any wildcard characters in it. Be careful not to + * expand unmatching brackets or braces. + * + * 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! + * + * Input: + * name name to check + * + * Results: + * returns TRUE if the word should be expanded, FALSE otherwise + */ +Boolean +Dir_HasWildcards(const char *name) +{ + const char *cp; + Boolean wild = FALSE; + int braces = 0, brackets = 0; + + for (cp = name; *cp; cp++) { + switch (*cp) { + 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; +} + +/*- + *----------------------------------------------------------------------- + * DirMatchFiles -- + * Given a pattern and a Path structure, see if any files + * match the pattern and add their names to the 'expansions' list if + * any do. This is incomplete -- it doesn't take care of patterns like + * src / *src / *.c properly (just *.c on any of the directories), but it + * will do for now. + * + * Input: + * pattern Pattern to look for + * p Directory to search + * expansion Place to store the results + * + * Side Effects: + * File names are added to the expansions lst. The directory will be + * fully hashed when this is done. + *----------------------------------------------------------------------- + */ +static void +DirMatchFiles(const char *pattern, Path *p, Lst expansions) +{ + Hash_Search search; /* Index into the directory's table */ + Hash_Entry *entry; /* Current entry in the table */ + Boolean isDot; /* TRUE if the directory being searched is . */ + + isDot = (*p->name == '.' && p->name[1] == '\0'); + + for (entry = Hash_EnumFirst(&p->files, &search); + entry != NULL; + entry = Hash_EnumNext(&search)) + { + /* + * See if the file matches the given pattern. Note we follow the UNIX + * convention that dot files will only be found if the pattern + * begins with a dot (note also that as a side effect of the hashing + * scheme, .* won't match . or .. since they aren't hashed). + */ + if (Str_Match(entry->name, pattern) && + ((entry->name[0] != '.') || + (pattern[0] == '.'))) + { + Lst_Append(expansions, + (isDot ? bmake_strdup(entry->name) : + str_concat3(p->name, "/", entry->name))); + } + } +} + +/* 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; +} + +/*- + *----------------------------------------------------------------------- + * DirExpandCurly -- + * Expand curly braces like the C shell. Does this recursively. + * Note the special case: if after the piece of the curly brace is + * done there are no wildcard characters in the result, the result is + * placed on the list WITHOUT CHECKING FOR ITS EXISTENCE. + * + * Input: + * word Entire word to expand + * brace First curly brace in it + * path Search path to use + * expansions Place to store the expansions + * + * Results: + * None. + * + * Side Effects: + * The given list is filled with the expansions... + * + *----------------------------------------------------------------------- + */ +static void +DirExpandCurly(const char *word, const char *brace, Lst path, Lst 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 */ + } +} + + +/*- + *----------------------------------------------------------------------- + * DirExpandInt -- + * Internal expand routine. Passes through the directories in the + * path one by one, calling DirMatchFiles for each. NOTE: This still + * doesn't handle patterns in directories... + * + * Input: + * word Word to expand + * path Path on which to look + * expansions Place to store the result + * + * Results: + * None. + * + * Side Effects: + * Things are added to the expansions list. + * + *----------------------------------------------------------------------- + */ +static void +DirExpandInt(const char *word, Lst path, Lst expansions) +{ + LstNode ln; /* Current node */ + + Lst_Open(path); + while ((ln = Lst_Next(path)) != NULL) { + Path *p = LstNode_Datum(ln); + DirMatchFiles(word, p, expansions); + } + Lst_Close(path); +} + +/* Print a word in the list of expansions. + * Callback for Dir_Expand when DEBUG(DIR), via Lst_ForEach. */ +static int +DirPrintWord(void *word, void *dummy MAKE_ATTR_UNUSED) +{ + fprintf(debug_file, "%s ", (char *)word); + + return 0; +} + +/*- + *----------------------------------------------------------------------- + * Dir_Expand -- + * 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 list of directories in which to find the + * resulting files + * expansions the list on which to place the results + * + * Results: + * A list of words consisting of the files which exist along the search + * path matching the given pattern. + * + * Side Effects: + * Directories may be opened. Who knows? + * Undefined behavior if the word is really in read-only memory. + *----------------------------------------------------------------------- + */ +void +Dir_Expand(const char *word, Lst path, Lst 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 == '*' || *cp == '{') { + break; + } + } + if (*cp == '{') { + /* + * This one will be fun. + */ + DirExpandCurly(word, cp, path, expansions); + return; + } else if (*cp != '\0') { + /* + * Back up to the start of the component + */ + while (cp > word && *cp != '/') { + cp--; + } + if (cp != word) { + char sc; + char *dirpath; + /* + * If the glob isn't in the first component, try and find + * all the components up to the one with a wildcard. + */ + sc = cp[1]; + ((char *)UNCONST(cp))[1] = '\0'; + dirpath = Dir_FindFile(word, path); + ((char *)UNCONST(cp))[1] = sc; + /* + * 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_Init(); + (void)Dir_AddDir(path, dirpath); + DirExpandInt(cp + 1, path, expansions); + Lst_Free(path); + } + } else { + /* + * Start the search from the local directory + */ + DirExpandInt(word, path, expansions); + } + } else { + /* + * Return the file -- this should never happen. + */ + DirExpandInt(word, path, expansions); + } + } else { + /* + * First the files in dot + */ + DirMatchFiles(word, dot, expansions); + + /* + * Then the files in every other directory on the path. + */ + DirExpandInt(word, path, expansions); + } + } + if (DEBUG(DIR)) { + Lst_ForEach(expansions, DirPrintWord, NULL); + fprintf(debug_file, "\n"); + } +} + +/*- + *----------------------------------------------------------------------- + * DirLookup -- + * Find if the file with the given name exists in the given path. + * + * Results: + * The path to the file or NULL. This path is guaranteed to be in a + * different part of memory than name and so may be safely free'd. + * + * Side Effects: + * None. + *----------------------------------------------------------------------- + */ +static char * +DirLookup(Path *p, const char *name MAKE_ATTR_UNUSED, const char *cp, + Boolean hasSlash MAKE_ATTR_UNUSED) +{ + char *file; /* the current filename to check */ + + DIR_DEBUG1(" %s ...\n", p->name); + + if (Hash_FindEntry(&p->files, cp) == NULL) + return NULL; + + file = str_concat3(p->name, "/", cp); + DIR_DEBUG1(" returning %s\n", file); + p->hits += 1; + hits += 1; + return file; +} + + +/*- + *----------------------------------------------------------------------- + * DirLookupSubdir -- + * Find if the file with the given name exists in the given path. + * + * Results: + * The path to the file or NULL. This path is guaranteed to be in a + * different part of memory than name and so may be safely free'd. + * + * Side Effects: + * If the file is found, it is added in the modification times hash + * table. + *----------------------------------------------------------------------- + */ +static char * +DirLookupSubdir(Path *p, const char *name) +{ + struct make_stat mst; + char *file; /* the current filename to check */ + + if (p != dot) { + file = str_concat3(p->name, "/", name); + } else { + /* + * Checking in dot -- DON'T put a leading ./ on the thing. + */ + file = bmake_strdup(name); + } + + DIR_DEBUG1("checking %s ...\n", file); + + if (cached_stat(file, &mst) == 0) { + nearmisses += 1; + return file; + } + free(file); + return NULL; +} + +/*- + *----------------------------------------------------------------------- + * DirLookupAbs -- + * Find if the file with the given name exists in the given path. + * + * Results: + * The path to the file, the empty string or NULL. If the file is + * the empty string, the search should be terminated. + * This path is guaranteed to be in a different part of memory + * than name and so may be safely free'd. + * + * Side Effects: + * None. + *----------------------------------------------------------------------- + */ +static char * +DirLookupAbs(Path *p, const char *name, const char *cp) +{ + char *p1; /* pointer into p->name */ + const char *p2; /* pointer into name */ + + DIR_DEBUG1(" %s ...\n", p->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 (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) { + continue; + } + if (*p1 != '\0' || p2 != cp - 1) { + return NULL; + } + + if (Hash_FindEntry(&p->files, cp) == NULL) { + DIR_DEBUG0(" must be here but isn't -- returning\n"); + /* Return empty string: terminates search */ + return bmake_strdup(""); + } + + p->hits += 1; + hits += 1; + DIR_DEBUG1(" returning %s\n", name); + return bmake_strdup(name); +} + +/*- + *----------------------------------------------------------------------- + * DirFindDot -- + * Find the file given on "." or curdir + * + * Results: + * The path to the file or NULL. This path is guaranteed to be in a + * different part of memory than name and so may be safely free'd. + * + * Side Effects: + * Hit counts change + *----------------------------------------------------------------------- + */ +static char * +DirFindDot(Boolean hasSlash MAKE_ATTR_UNUSED, const char *name, const char *cp) +{ + + if (Hash_FindEntry(&dot->files, cp) != NULL) { + DIR_DEBUG0(" in '.'\n"); + hits += 1; + dot->hits += 1; + return bmake_strdup(name); + } + if (cur && Hash_FindEntry(&cur->files, cp) != NULL) { + DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name); + hits += 1; + cur->hits += 1; + return str_concat3(cur->name, "/", cp); + } + + return NULL; +} + +/*- + *----------------------------------------------------------------------- + * Dir_FindFile -- + * Find the file with the given name along the given search path. + * + * Input: + * name the file to find + * path the Lst of directories to search + * + * Results: + * The path to the file or NULL. This path is guaranteed to be in a + * different part of memory than name and so may be safely free'd. + * + * Side Effects: + * If the file is found in a directory which 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. + *----------------------------------------------------------------------- + */ +char * +Dir_FindFile(const char *name, Lst path) +{ + LstNode ln; /* a list element */ + char *file; /* the current filename to check */ + Path *p; /* current path member */ + const char *cp; /* Terminal name of file */ + Boolean hasLastDot = FALSE; /* true 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) + */ + cp = strrchr(name, '/'); + if (cp) { + hasSlash = TRUE; + cp += 1; + } else { + hasSlash = FALSE; + cp = name; + } + + DIR_DEBUG1("Searching for %s ...", name); + + if (path == NULL) { + DIR_DEBUG0("couldn't open path, file not found\n"); + misses += 1; + return NULL; + } + + Lst_Open(path); + if ((ln = Lst_First(path)) != NULL) { + p = LstNode_Datum(ln); + if (p == 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 || (cp - 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(hasSlash, name, cp)) != NULL) { + Lst_Close(path); + return file; + } + + while ((ln = Lst_Next(path)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) { + Lst_Close(path); + return file; + } + } + + if (hasLastDot && (file = DirFindDot(hasSlash, name, cp)) != NULL) { + Lst_Close(path); + return file; + } + } + Lst_Close(path); + + /* + * 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 += 1; + return NULL; + } + + if (*cp == '\0') { + /* we were given a trailing "/" */ + cp = 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; + } + + Lst_Open(path); + while ((ln = Lst_Next(path)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if (p == dot) { + if (checkedDot) + continue; + checkedDot = TRUE; + } + if ((file = DirLookupSubdir(p, name)) != NULL) { + Lst_Close(path); + return file; + } + } + Lst_Close(path); + + 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, cp)) != NULL)) { + if (file[0] == '\0') { + free(file); + return NULL; + } + return file; + } + + Lst_Open(path); + while ((ln = Lst_Next(path)) != NULL) { + p = LstNode_Datum(ln); + if (p == dotLast) + continue; + if ((file = DirLookupAbs(p, name, cp)) != NULL) { + Lst_Close(path); + if (file[0] == '\0') { + free(file); + return NULL; + } + return file; + } + } + Lst_Close(path); + + if (hasLastDot && cur && + ((file = DirLookupAbs(cur, name, cp)) != 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 (cp == traling_dot) { + cp = strrchr(name, '/'); + cp += 1; + } + cp[-1] = '\0'; + (void)Dir_AddDir(path, name); + cp[-1] = '/'; + + bigmisses += 1; + ln = Lst_Last(path); + if (ln == NULL) { + return NULL; + } else { + p = LstNode_Datum(ln); + } + + if (Hash_FindEntry(&p->files, cp) != NULL) { + return bmake_strdup(name); + } else { + return NULL; + } +#else /* !notdef */ + DIR_DEBUG1(" Looking for \"%s\" ...\n", name); + + bigmisses += 1; + if (cached_stat(name, &mst) == 0) { + return bmake_strdup(name); + } + + DIR_DEBUG0(" failed. Returning NULL\n"); + return NULL; +#endif /* notdef */ +} + + +/*- + *----------------------------------------------------------------------- + * Dir_FindHereOrAbove -- + * 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 path we are looking for + * result the result of a successful search is placed here + * result_len the length of the result buffer + * (typically MAXPATHLEN + 1) + * + * Results: + * 0 on failure, 1 on success [in which case the found path is put + * in the result buffer]. + * + * Side Effects: + *----------------------------------------------------------------------- + */ +Boolean +Dir_FindHereOrAbove(const char *here, const char *search_path, + char *result, int result_len) +{ + struct make_stat mst; + char dirbase[MAXPATHLEN + 1], *dirbase_end; + char try[MAXPATHLEN + 1], *try_end; + + /* copy out our starting point */ + snprintf(dirbase, sizeof(dirbase), "%s", here); + dirbase_end = dirbase + strlen(dirbase); + + /* loop until we determine a result */ + while (TRUE) { + + /* try and stat(2) it ... */ + snprintf(try, sizeof(try), "%s/%s", 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! */ + } + + snprintf(result, result_len, "%s", try); + return TRUE; + } + + /* + * 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! */ + + } /* while (TRUE) */ + + return FALSE; +} + +/*- + *----------------------------------------------------------------------- + * 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. + *----------------------------------------------------------------------- + */ +int +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 && gn->path == NULL) { + gn->path = fullName; + } + + gn->mtime = mst.mst_mtime; + return gn->mtime; +} + +/*- + *----------------------------------------------------------------------- + * Dir_AddDir -- + * Add the given name to the end of the given path. The order of + * the arguments is backwards so ParseDoDependency can do a + * Lst_ForEach of its list of paths... + * + * Input: + * path the path to which the directory should be + * added + * XXX: Why would this ever be NULL, and what does + * that mean? + * name the name of the directory to add + * + * Results: + * none + * + * Side Effects: + * A structure is added to the list and the directory is + * read and hashed. + *----------------------------------------------------------------------- + */ +Path * +Dir_AddDir(Lst path, const char *name) +{ + LstNode ln = NULL; /* node in case Path structure is found */ + Path *p = NULL; /* pointer to new Path structure */ + DIR *d; /* for reading directory */ + struct dirent *dp; /* entry in directory */ + + if (path != NULL && strcmp(name, ".DOTLAST") == 0) { + ln = Lst_Find(path, DirFindName, name); + if (ln != NULL) + return LstNode_Datum(ln); + + dotLast->refCount++; + Lst_Prepend(path, dotLast); + } + + if (path != NULL) + ln = Lst_Find(openDirectories, DirFindName, name); + if (ln != NULL) { + p = LstNode_Datum(ln); + if (Lst_FindDatum(path, p) == NULL) { + p->refCount += 1; + Lst_Append(path, p); + } + return p; + } + + DIR_DEBUG1("Caching %s ...", name); + + if ((d = opendir(name)) != NULL) { + p = bmake_malloc(sizeof(Path)); + p->name = bmake_strdup(name); + p->hits = 0; + p->refCount = 1; + Hash_InitTable(&p->files, -1); + + 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)Hash_CreateEntry(&p->files, dp->d_name, NULL); + } + (void)closedir(d); + Lst_Append(openDirectories, p); + if (path != NULL) + Lst_Append(path, p); + } + DIR_DEBUG0("done\n"); + return p; +} + +/*- + *----------------------------------------------------------------------- + * Dir_CopyDir -- + * Callback function for duplicating a search path via Lst_Copy. + * Ups the reference count for the directory. + * + * Results: + * Returns the Path it was given. + *----------------------------------------------------------------------- + */ +void * +Dir_CopyDir(void *p) +{ + ((Path *)p)->refCount += 1; + + return p; +} + +/*- + *----------------------------------------------------------------------- + * 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, Lst path) +{ + Buffer buf; + LstNode ln; /* the node of the current directory */ + + Buf_Init(&buf, 0); + + if (path != NULL) { + Lst_Open(path); + while ((ln = Lst_Next(path)) != NULL) { + Path *p = LstNode_Datum(ln); + Buf_AddStr(&buf, " "); + Buf_AddStr(&buf, flag); + Buf_AddStr(&buf, p->name); + } + Lst_Close(path); + } + + return Buf_Destroy(&buf, FALSE); +} + +/*- + *----------------------------------------------------------------------- + * Dir_Destroy -- + * Nuke a directory descriptor, if possible. Callback procedure + * for the suffixes module when destroying a search path. + * + * Input: + * pp The directory descriptor to nuke + * + * Results: + * None. + * + * Side Effects: + * If no other path references this directory (refCount == 0), + * the Path and all its data are freed. + * + *----------------------------------------------------------------------- + */ +void +Dir_Destroy(void *pp) +{ + Path *p = (Path *)pp; + p->refCount -= 1; + + if (p->refCount == 0) { + LstNode ln; + + ln = Lst_FindDatum(openDirectories, p); + Lst_Remove(openDirectories, ln); + + Hash_DeleteTable(&p->files); + free(p->name); + free(p); + } +} + +/*- + *----------------------------------------------------------------------- + * Dir_ClearPath -- + * Clear out all elements of the given search path. This is different + * from destroying the list, notice. + * + * Input: + * path Path to clear + * + * Results: + * None. + * + * Side Effects: + * The path is set to the empty list. + * + *----------------------------------------------------------------------- + */ +void +Dir_ClearPath(Lst path) +{ + while (!Lst_IsEmpty(path)) { + Path *p = Lst_Dequeue(path); + Dir_Destroy(p); + } +} + + +/*- + *----------------------------------------------------------------------- + * Dir_Concat -- + * Concatenate two paths, adding the second to the end of the first. + * Makes sure to avoid duplicates. + * + * Input: + * path1 Dest + * path2 Source + * + * Results: + * None + * + * Side Effects: + * Reference counts for added dirs are upped. + * + *----------------------------------------------------------------------- + */ +void +Dir_Concat(Lst path1, Lst path2) +{ + LstNode ln; + Path *p; + + for (ln = Lst_First(path2); ln != NULL; ln = LstNode_Next(ln)) { + p = LstNode_Datum(ln); + if (Lst_FindDatum(path1, p) == NULL) { + p->refCount += 1; + Lst_Append(path1, p); + } + } +} + +static int +percentage(int num, int den) +{ + return den != 0 ? num * 100 / den : 0; +} + +/********** DEBUG INFO **********/ +void +Dir_PrintDirectories(void) +{ + LstNode ln; + + fprintf(debug_file, "#*** Directory Cache:\n"); + fprintf(debug_file, + "# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", + hits, misses, nearmisses, bigmisses, + percentage(hits, hits + bigmisses + nearmisses)); + fprintf(debug_file, "# %-20s referenced\thits\n", "directory"); + + Lst_Open(openDirectories); + while ((ln = Lst_Next(openDirectories)) != NULL) { + Path *p = LstNode_Datum(ln); + fprintf(debug_file, "# %-20s %10d\t%4d\n", p->name, p->refCount, + p->hits); + } + Lst_Close(openDirectories); +} + +static int +DirPrintDir(void *p, void *dummy MAKE_ATTR_UNUSED) +{ + fprintf(debug_file, "%s ", ((Path *)p)->name); + return 0; +} + +void +Dir_PrintPath(Lst path) +{ + Lst_ForEach(path, DirPrintDir, NULL); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/dir.h =================================================================== --- vendor/NetBSD/bmake/20200902/dir.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/dir.h (revision 365363) @@ -0,0 +1,116 @@ +/* $NetBSD: dir.h,v 1.23 2020/09/02 04:08:54 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 of a directory, remembering all the files that exist in that + * directory. */ +typedef struct { + char *name; /* Name of directory */ + int refCount; /* Number of paths with this directory */ + int hits; /* the number of times a file in this + * directory has been found */ + Hash_Table files; /* Hash set of files in directory */ +} Path; + +struct make_stat { + time_t mst_mtime; + mode_t mst_mode; +}; + +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 *, Lst, Lst); +char *Dir_FindFile(const char *, Lst); +Boolean Dir_FindHereOrAbove(const char *, const char *, char *, int); +int Dir_MTime(GNode *, Boolean); +Path *Dir_AddDir(Lst, const char *); +char *Dir_MakeFlags(const char *, Lst); +void Dir_ClearPath(Lst); +void Dir_Concat(Lst, Lst); +void Dir_PrintDirectories(void); +void Dir_PrintPath(Lst); +void Dir_Destroy(void *); +void *Dir_CopyDir(void *); + +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/20200902/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/20200902/enum.c =================================================================== --- vendor/NetBSD/bmake/20200902/enum.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/enum.c (revision 365363) @@ -0,0 +1,100 @@ +/* $NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 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_NATIVE +static char rcsid[] = "$NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 rillig Exp $"; +#else +#include +#ifndef lint +__RCSID("$NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 rillig Exp $"); +#endif +#endif + +#include +#include +#include + +#include "enum.h" + +/* 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/20200902/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/20200902/enum.h =================================================================== --- vendor/NetBSD/bmake/20200902/enum.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/enum.h (revision 365363) @@ -0,0 +1,193 @@ +/* $NetBSD: enum.h,v 1.9 2020/09/01 20:34:51 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 { + 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 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 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/20200902/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/20200902/for.c =================================================================== --- vendor/NetBSD/bmake/20200902/for.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/for.c (revision 365363) @@ -0,0 +1,467 @@ +/* $NetBSD: for.c,v 1.67 2020/08/30 19:56:02 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: for.c,v 1.67 2020/08/30 19:56:02 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: for.c,v 1.67 2020/08/30 19:56:02 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * for.c -- + * Functions to handle loops in a makefile. + * + * Interface: + * For_Eval Evaluate the loop in the passed line. + * For_Run Run accumulated loop + * + */ + +#include "make.h" +#include "strlist.h" + +#define FOR_SUB_ESCAPE_CHAR 1 +#define FOR_SUB_ESCAPE_BRACE 2 +#define FOR_SUB_ESCAPE_PAREN 4 + +/* + * For statements are of the form: + * + * .for in + * ... + * .endfor + * + * The trick is to look for the matching end inside for for loop + * To do that, we count the current nesting level of the for loops. + * and the .endfor statements, accumulating all the statements between + * the initial .for loop and the matching .endfor; + * then we evaluate the for loop for each variable in the varlist. + * + * Note that any nested fors are just passed through; they get handled + * recursively in For_Eval when we're expanding the enclosing for in + * For_Run. + */ + +static int forLevel = 0; /* Nesting level */ + +/* + * State of a for loop. + */ +typedef struct { + Buffer buf; /* Body of loop */ + strlist_t vars; /* Iteration variables */ + strlist_t items; /* Substitution items */ + char *parse_buf; + int short_var; + int sub_next; +} For; + +static For *accumFor; /* Loop being accumulated */ + + +static void +For_Free(For *arg) +{ + Buf_Destroy(&arg->buf, TRUE); + strlist_clean(&arg->vars); + strlist_clean(&arg->items); + free(arg->parse_buf); + + free(arg); +} + +/*- + *----------------------------------------------------------------------- + * For_Eval -- + * 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. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ +int +For_Eval(char *line) +{ + For *new_for; + char *ptr = line, *sub; + size_t len; + int escapes; + unsigned char ch; + Words words; + + /* Skip the '.' and any following whitespace */ + for (ptr++; *ptr && isspace((unsigned char)*ptr); ptr++) + continue; + + /* + * If we are not in a for loop quickly determine if the statement is + * a for. + */ + if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' || + !isspace((unsigned char)ptr[3])) { + if (ptr[0] == 'e' && strncmp(ptr + 1, "ndfor", 5) == 0) { + Parse_Error(PARSE_FATAL, "for-less endfor"); + return -1; + } + return 0; + } + ptr += 3; + + /* + * we found a for loop, and now we are going to parse it. + */ + + new_for = bmake_malloc(sizeof *new_for); + memset(new_for, 0, sizeof *new_for); + + /* Grab the variables. Terminate on "in". */ + for (;; ptr += len) { + while (*ptr && isspace((unsigned char)*ptr)) + ptr++; + if (*ptr == '\0') { + Parse_Error(PARSE_FATAL, "missing `in' in for"); + For_Free(new_for); + return -1; + } + for (len = 1; ptr[len] && !isspace((unsigned char)ptr[len]); len++) + continue; + if (len == 2 && ptr[0] == 'i' && ptr[1] == 'n') { + ptr += 2; + break; + } + if (len == 1) + new_for->short_var = 1; + strlist_add_str(&new_for->vars, bmake_strldup(ptr, len), len); + } + + if (strlist_num(&new_for->vars) == 0) { + Parse_Error(PARSE_FATAL, "no iteration variables in for"); + For_Free(new_for); + return -1; + } + + while (*ptr && isspace((unsigned char)*ptr)) + ptr++; + + /* + * Make a list with the remaining words + * The values are substituted as ${:U...} so we must \ escape + * characters that break that syntax. + * Variables are fully expanded - so it is safe for escape $. + * We can't do the escapes here - because we don't know whether + * we are substuting into ${...} or $(...). + */ + sub = Var_Subst(ptr, VAR_GLOBAL, VARE_WANTRES); + + /* + * Split into words allowing for quoted strings. + */ + words = Str_Words(sub, FALSE); + + free(sub); + + { + size_t n; + + for (n = 0; n < words.len; n++) { + ptr = words.words[n]; + if (!*ptr) + continue; + escapes = 0; + while ((ch = *ptr++)) { + switch (ch) { + case ':': + case '$': + case '\\': + escapes |= FOR_SUB_ESCAPE_CHAR; + break; + case ')': + escapes |= FOR_SUB_ESCAPE_PAREN; + break; + case /*{*/ '}': + escapes |= FOR_SUB_ESCAPE_BRACE; + break; + } + } + /* + * We have to dup words[n] to maintain the semantics of + * strlist. + */ + strlist_add_str(&new_for->items, bmake_strdup(words.words[n]), + escapes); + } + + Words_Free(words); + + if ((len = strlist_num(&new_for->items)) > 0 && + len % (n = strlist_num(&new_for->vars))) { + Parse_Error(PARSE_FATAL, + "Wrong number of words (%zu) in .for substitution list" + " with %zu vars", len, n); + /* + * Return 'success' so that the body of the .for loop is + * accumulated. + * Remove all items so that the loop doesn't iterate. + */ + strlist_clean(&new_for->items); + } + } + + Buf_Init(&new_for->buf, 0); + accumFor = new_for; + forLevel = 1; + return 1; +} + +/* + * Add another line to a .for loop. + * Returns 0 when the matching .endfor is reached. + */ + +int +For_Accum(char *line) +{ + char *ptr = line; + + if (*ptr == '.') { + + for (ptr++; *ptr && isspace((unsigned char)*ptr); ptr++) + continue; + + if (strncmp(ptr, "endfor", 6) == 0 && + (isspace((unsigned char)ptr[6]) || !ptr[6])) { + if (DEBUG(FOR)) + (void)fprintf(debug_file, "For: end for %d\n", forLevel); + if (--forLevel <= 0) + return 0; + } else if (strncmp(ptr, "for", 3) == 0 && + isspace((unsigned char)ptr[3])) { + forLevel++; + if (DEBUG(FOR)) + (void)fprintf(debug_file, "For: new loop %d\n", forLevel); + } + } + + Buf_AddStr(&accumFor->buf, line); + Buf_AddByte(&accumFor->buf, '\n'); + return 1; +} + + +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; +} + +static void +for_substitute(Buffer *cmds, strlist_t *items, unsigned int item_no, char ech) +{ + char ch; + + const char *item = strlist_str(items, item_no); + + /* If there were no escapes, or the only escape is the other variable + * terminator, then just substitute the full string */ + if (!(strlist_info(items, item_no) & + (ech == ')' ? ~FOR_SUB_ESCAPE_BRACE : ~FOR_SUB_ESCAPE_PAREN))) { + Buf_AddStr(cmds, item); + return; + } + + /* Escape ':', '$', '\\' and 'ech' - removed by :U processing */ + 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); + } +} + +static char * +For_Iterate(void *v_arg, size_t *ret_len) +{ + For *arg = v_arg; + int i; + char *var; + char *cp; + char *cmd_cp; + char *body_end; + char ch; + Buffer cmds; + size_t cmd_len; + + if (arg->sub_next + strlist_num(&arg->vars) > strlist_num(&arg->items)) { + /* No more iterations */ + For_Free(arg); + return NULL; + } + + free(arg->parse_buf); + arg->parse_buf = NULL; + + /* + * 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 substitions 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. + */ + + cmd_cp = Buf_GetAll(&arg->buf, &cmd_len); + body_end = cmd_cp + cmd_len; + Buf_Init(&cmds, cmd_len + 256); + for (cp = cmd_cp; (cp = strchr(cp, '$')) != NULL;) { + char ech; + ch = *++cp; + if ((ch == '(' && (ech = ')', 1)) || (ch == '{' && (ech = '}', 1))) { + cp++; + /* Check variable name against the .for loop variables */ + STRLIST_FOREACH(var, &arg->vars, i) { + size_t vlen = strlist_info(&arg->vars, i); + if (memcmp(cp, var, vlen) != 0) + continue; + if (cp[vlen] != ':' && cp[vlen] != ech && cp[vlen] != '\\') + continue; + /* Found a variable match. Replace with :U */ + Buf_AddBytesBetween(&cmds, cmd_cp, cp); + Buf_AddStr(&cmds, ":U"); + cp += vlen; + cmd_cp = cp; + for_substitute(&cmds, &arg->items, arg->sub_next + i, ech); + break; + } + continue; + } + if (ch == 0) + break; + /* Probably a single character name, ignore $$ and stupid ones. {*/ + if (!arg->short_var || strchr("}):$", ch) != NULL) { + cp++; + continue; + } + STRLIST_FOREACH(var, &arg->vars, i) { + if (var[0] != ch || var[1] != 0) + continue; + /* Found a variable match. Replace with ${:U} */ + Buf_AddBytesBetween(&cmds, cmd_cp, cp); + Buf_AddStr(&cmds, "{:U"); + cmd_cp = ++cp; + for_substitute(&cmds, &arg->items, arg->sub_next + i, /*{*/ '}'); + Buf_AddByte(&cmds, '}'); + break; + } + } + Buf_AddBytesBetween(&cmds, cmd_cp, body_end); + + cp = Buf_Destroy(&cmds, FALSE); + if (DEBUG(FOR)) + (void)fprintf(debug_file, "For: loop body:\n%s", cp); + + arg->sub_next += strlist_num(&arg->vars); + + arg->parse_buf = cp; + *ret_len = strlen(cp); + return cp; +} + +/* Run the for loop, imitating the actions of an include file. */ +void +For_Run(int lineno) +{ + For *arg; + + arg = accumFor; + accumFor = NULL; + + if (strlist_num(&arg->items) == 0) { + /* Nothing to expand - possibly due to an earlier syntax error. */ + For_Free(arg); + return; + } + + Parse_SetInput(NULL, lineno, -1, For_Iterate, arg); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/hash.c =================================================================== --- vendor/NetBSD/bmake/20200902/hash.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/hash.c (revision 365363) @@ -0,0 +1,404 @@ +/* $NetBSD: hash.c,v 1.29 2020/09/01 21:11:31 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: hash.c,v 1.29 2020/09/01 21:11:31 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: hash.c,v 1.29 2020/09/01 21:11:31 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/* hash.c -- + * + * This module contains routines to manipulate a hash table. + * See hash.h for a definition of the structure of the hash + * table. Hash tables grow automatically as the amount of + * information increases. + */ +#include "make.h" + +/* + * Forward references to local procedures that are used before they're + * defined: + */ + +static void RebuildTable(Hash_Table *); + +/* + * The following defines the ratio of # entries to # buckets + * at which we rebuild the table to make it larger. + */ + +#define rebuildLimit 3 + +/* The hash function(s) */ + +#ifndef HASH +/* The default: this one matches Gosling's emacs */ +#define HASH(h, key, p) do { \ + for (h = 0, p = key; *p;) \ + h = (h << 5) - h + *p++; \ + } while (0) + +#endif + +/* Sets up the hash table. + * + * Input: + * t Structure to to hold the table. + * numBuckets How many buckets to create for starters. This + * number is rounded up to a power of two. If + * <= 0, a reasonable default is chosen. The + * table will grow in size later as needed. + */ +void +Hash_InitTable(Hash_Table *t, int numBuckets) +{ + int i; + struct Hash_Entry **hp; + + /* + * Round up the size to a power of two. + */ + if (numBuckets <= 0) + i = 16; + else { + for (i = 2; i < numBuckets; i <<= 1) + continue; + } + t->numEntries = 0; + t->maxchain = 0; + t->bucketsSize = i; + t->bucketsMask = i - 1; + t->buckets = hp = bmake_malloc(sizeof(*hp) * i); + while (--i >= 0) + *hp++ = NULL; +} + +/* Removes everything from the hash table and frees up the memory space it + * occupied (except for the space in the Hash_Table structure). */ +void +Hash_DeleteTable(Hash_Table *t) +{ + struct Hash_Entry **hp, *h, *nexth = NULL; + int i; + + for (hp = t->buckets, i = t->bucketsSize; --i >= 0;) { + for (h = *hp++; h != NULL; h = nexth) { + nexth = h->next; + free(h); + } + } + free(t->buckets); + + /* + * Set up the hash table to cause memory faults on any future access + * attempts until re-initialization. + */ + t->buckets = NULL; +} + +/* Searches the hash table for an entry corresponding to the key. + * + * Input: + * t Hash table to search. + * key A hash key. + * + * Results: + * Returns a pointer to the entry for key, or NULL if the table contains + * no entry for the key. + */ +Hash_Entry * +Hash_FindEntry(Hash_Table *t, const char *key) +{ + Hash_Entry *e; + unsigned h; + const char *p; + int chainlen; + + if (t == NULL || t->buckets == NULL) { + return NULL; + } + HASH(h, key, p); + p = key; + chainlen = 0; +#ifdef DEBUG_HASH_LOOKUP + if (DEBUG(HASH)) + fprintf(debug_file, "%s: %p h=%x key=%s\n", __func__, + t, h, key); +#endif + for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) { + chainlen++; + if (e->namehash == h && strcmp(e->name, p) == 0) + break; + } + if (chainlen > t->maxchain) + t->maxchain = chainlen; + return e; +} + +/* Searches the hash table for an entry corresponding to the key. + * If no entry is found, then one is created. + * + * Input: + * t Hash table to search. + * key A hash key. + * newPtr Filled with TRUE if new entry created, + * FALSE otherwise. + */ +Hash_Entry * +Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr) +{ + Hash_Entry *e; + unsigned h; + const char *p; + int keylen; + int chainlen; + struct Hash_Entry **hp; + + /* + * Hash the key. As a side effect, save the length (strlen) of the + * key in case we need to create the entry. + */ + HASH(h, key, p); + keylen = p - key; + p = key; + chainlen = 0; +#ifdef DEBUG_HASH_LOOKUP + if (DEBUG(HASH)) + fprintf(debug_file, "%s: %p h=%x key=%s\n", __func__, + t, h, key); +#endif + for (e = t->buckets[h & t->bucketsMask]; e != NULL; e = e->next) { + chainlen++; + if (e->namehash == h && strcmp(e->name, p) == 0) { + if (newPtr != NULL) + *newPtr = FALSE; + break; + } + } + if (chainlen > t->maxchain) + t->maxchain = chainlen; + if (e) + return e; + + /* + * The desired entry isn't there. Before allocating a new entry, + * expand the table if necessary (and this changes the resulting + * bucket chain). + */ + if (t->numEntries >= rebuildLimit * t->bucketsSize) + RebuildTable(t); + e = bmake_malloc(sizeof(*e) + keylen); + hp = &t->buckets[h & t->bucketsMask]; + e->next = *hp; + *hp = e; + Hash_SetValue(e, NULL); + e->namehash = h; + (void)strcpy(e->name, p); + t->numEntries++; + + if (newPtr != NULL) + *newPtr = TRUE; + return e; +} + +/* Delete the given hash table entry and free memory associated with it. */ +void +Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e) +{ + Hash_Entry **hp, *p; + + if (e == NULL) + return; + for (hp = &t->buckets[e->namehash & t->bucketsMask]; + (p = *hp) != NULL; hp = &p->next) { + if (p == e) { + *hp = p->next; + free(p); + t->numEntries--; + return; + } + } + (void)write(2, "bad call to Hash_DeleteEntry\n", 29); + abort(); +} + +/* Sets things up for enumerating all entries in the hash table. + * + * Input: + * t Table to be searched. + * searchPtr Area in which to keep state about search. + * + * Results: + * The return value is the address of the first entry in + * the hash table, or NULL if the table is empty. + */ +Hash_Entry * +Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr) +{ + searchPtr->table = t; + searchPtr->nextBucket = 0; + searchPtr->entry = NULL; + return Hash_EnumNext(searchPtr); +} + +/* Returns the next entry in the hash table, or NULL if the end of the table + * is reached. + * + * Input: + * searchPtr Area used to keep state about search. + */ +Hash_Entry * +Hash_EnumNext(Hash_Search *searchPtr) +{ + Hash_Entry *e; + Hash_Table *t = searchPtr->table; + + /* + * The entry field points to the most recently returned + * entry, or is NULL if we are starting up. If not NULL, we have + * to start at the next one in the chain. + */ + e = searchPtr->entry; + if (e != NULL) + e = e->next; + /* + * If the chain ran out, or if we are starting up, we need to + * find the next nonempty chain. + */ + while (e == NULL) { + if (searchPtr->nextBucket >= t->bucketsSize) + return NULL; + e = t->buckets[searchPtr->nextBucket++]; + } + searchPtr->entry = e; + return e; +} + +/* Makes a new hash table that is larger than the old one. The entire hash + * table is moved, so any bucket numbers from the old table become invalid. */ +static void +RebuildTable(Hash_Table *t) +{ + Hash_Entry *e, *next = NULL, **hp, **xp; + int i, mask; + Hash_Entry **oldhp; + int oldsize; + + oldhp = t->buckets; + oldsize = i = t->bucketsSize; + i <<= 1; + t->bucketsSize = i; + t->bucketsMask = mask = i - 1; + t->buckets = hp = bmake_malloc(sizeof(*hp) * i); + while (--i >= 0) + *hp++ = NULL; + for (hp = oldhp, i = oldsize; --i >= 0;) { + for (e = *hp++; e != NULL; e = next) { + next = e->next; + xp = &t->buckets[e->namehash & mask]; + e->next = *xp; + *xp = e; + } + } + free(oldhp); + if (DEBUG(HASH)) + fprintf(debug_file, "%s: %p size=%d entries=%d maxchain=%d\n", + __func__, t, t->bucketsSize, t->numEntries, t->maxchain); + t->maxchain = 0; +} + +void +Hash_ForEach(Hash_Table *t, void (*action)(void *, void *), void *data) +{ + Hash_Search search; + Hash_Entry *e; + + for (e = Hash_EnumFirst(t, &search); + e != NULL; + e = Hash_EnumNext(&search)) + action(Hash_GetValue(e), data); +} + +void +Hash_DebugStats(Hash_Table *t, const char *name) +{ + if (DEBUG(HASH)) + fprintf(debug_file, "Hash_Table %s: size=%d numEntries=%d maxchain=%d\n", + name, t->bucketsSize, t->numEntries, t->maxchain); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/hash.h =================================================================== --- vendor/NetBSD/bmake/20200902/hash.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/hash.h (revision 365363) @@ -0,0 +1,131 @@ +/* $NetBSD: hash.h,v 1.21 2020/09/01 21:11:31 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 Hash_Entry { + struct Hash_Entry *next; /* Used to link together all the entries + * associated with the same bucket. */ + void *value; + unsigned namehash; /* hash value of key */ + char name[1]; /* key string, variable length */ +} Hash_Entry; + +/* The hash table containing the entries. */ +typedef struct Hash_Table { + Hash_Entry **buckets; /* Pointers to Hash_Entry, one + * for each bucket in the table. */ + int bucketsSize; + int numEntries; /* Number of entries in the table. */ + int bucketsMask; /* Used to select the bucket for a hash. */ + int maxchain; /* max length of chain detected */ +} Hash_Table; + +/* + * The following structure is used by the searching routines + * to record where we are in the search. + */ +typedef struct Hash_Search { + Hash_Table *table; /* Table being searched. */ + int nextBucket; /* Next bucket to check (after current). */ + Hash_Entry *entry; /* Next entry to check in current bucket. */ +} Hash_Search; + +static inline void * MAKE_ATTR_UNUSED +Hash_GetValue(Hash_Entry *h) +{ + return h->value; +} + +static inline void MAKE_ATTR_UNUSED +Hash_SetValue(Hash_Entry *h, void *datum) +{ + h->value = datum; +} + +void Hash_InitTable(Hash_Table *, int); +void Hash_DeleteTable(Hash_Table *); +Hash_Entry *Hash_FindEntry(Hash_Table *, const char *); +Hash_Entry *Hash_CreateEntry(Hash_Table *, const char *, Boolean *); +void Hash_DeleteEntry(Hash_Table *, Hash_Entry *); +Hash_Entry *Hash_EnumFirst(Hash_Table *, Hash_Search *); +Hash_Entry *Hash_EnumNext(Hash_Search *); +void Hash_ForEach(Hash_Table *, void (*)(void *, void *), void *); +void Hash_DebugStats(Hash_Table *, const char *); + +#endif /* MAKE_HASH_H */ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/job.c =================================================================== --- vendor/NetBSD/bmake/20200902/job.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/job.c (revision 365363) @@ -0,0 +1,3118 @@ +/* $NetBSD: job.c,v 1.227 2020/08/30 19:56:02 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: job.c,v 1.227 2020/08/30 19:56:02 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: job.c,v 1.227 2020/08/30 19:56:02 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * job.c -- + * handle the creation etc. of our child processes. + * + * Interface: + * 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_Init Called to initialize this module. in addition, + * any commands attached to the .BEGIN target + * are executed before this function returns. + * Hence, the makefile must have been parsed + * before this function is called. + * + * Job_End Cleanup any memory used. + * + * 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, as it were. + * + * 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" +# define STATIC static + +/* + * error handling variables + */ +static int errors = 0; /* number of errors reported */ +static int aborting = 0; /* why is the make aborting? */ +#define ABORT_ERROR 1 /* Because of an error */ +#define ABORT_INTERRUPT 2 /* Because it was interrupted */ +#define ABORT_WAIT 3 /* Waiting for jobs to finish */ +#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; + +/* + * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file + * is a char! So when we go above 127 we turn negative! + */ +#define FILENO(a) ((unsigned) fileno(a)) + +/* + * post-make command processing. The node postCommands is really just the + * .END target but we keep it around to avoid having to search for it + * all the time. + */ +static GNode *postCommands = NULL; + /* node containing commands to execute when + * everything else is done */ +static int numCommands; /* The number of commands actually printed + * for a target. Should this number be + * 0, no shell will be executed. */ + +/* + * Return values from JobStart. + */ +#define JOB_RUNNING 0 /* Job is running */ +#define JOB_ERROR 1 /* Error in starting the job */ +#define JOB_FINISHED 2 /* The job is already finished */ + +/* + * 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 prefedined 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, + FALSE, "", "", "", 0, + FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', + "", + "", +}, +#endif /* DEFSHELL_CUSTOM */ + /* + * SH description. Echo control is also possible and, under + * sun UNIX anyway, one can even control error checking. + */ +{ + "sh", + FALSE, "", "", "", 0, + FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', +#if defined(MAKE_NATIVE) && defined(__NetBSD__) + "q", +#else + "", +#endif + "", +}, + /* + * KSH description. + */ +{ + "ksh", + TRUE, "set +v", "set -v", "set +v", 6, + FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', + "v", + "", +}, + /* + * 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", + TRUE, "unset verbose", "set verbose", "unset verbose", 10, + FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"\n", "", "'\\\n'", '#', + "v", "e", +}, + /* + * UNKNOWN. + */ +{ + NULL, + FALSE, NULL, NULL, NULL, 0, + FALSE, NULL, NULL, NULL, NULL, 0, + NULL, NULL, +} +}; +static Shell *commandShell = &shells[DEFSHELL_INDEX]; /* this is the shell to + * which we pass all + * commands in the Makefile. + * It is set by the + * Job_ParseShell function */ +const char *shellPath = NULL, /* full pathname of + * executable image */ + *shellName = NULL; /* last component of shell */ +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 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 int 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" + +static const int npseudojobs = 2; /* number of pseudo-jobs */ + +#define TARG_FMT "%s %s ---\n" /* Default format */ +#define MESSAGE(fp, gn) \ + if (maxJobs != 1 && targPrefix && *targPrefix) \ + (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) + +static sigset_t caught_signals; /* Set of signals we handle */ + +static void JobChildSig(int); +static void JobContinueSig(int); +static Job *JobFindPid(int, int, Boolean); +static int JobPrintCommand(void *, void *); +static int JobSaveCommand(void *, void *); +static void JobClose(Job *); +static void JobExec(Job *, char **); +static void JobMakeArgv(Job *, char **); +static int JobStart(GNode *, int); +static char *JobOutput(Job *, char *, char *, int); +static void JobDoOutput(Job *, Boolean); +static Shell *JobMatchShell(const char *); +static void JobInterrupt(int, int) MAKE_ATTR_DEAD; +static void JobRestartJobs(void); +static void JobTokenAdd(void); +static void JobSigLock(sigset_t *); +static void JobSigUnlock(sigset_t *); +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; + + fprintf(debug_file, "job table @ %s\n", where); + for (job = job_table; job < job_table_end; job++) { + fprintf(debug_file, "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) +{ + if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) { + char *file = (gn->path == NULL ? gn->name : gn->path); + if (!noExecute && 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; + + if (pipe(job->jobPipe) == -1) + Punt("Cannot create pipe: %s", strerror(errno)); + + for (i = 0; i < 2; i++) { + /* Avoid using low numbered fds */ + fd = fcntl(job->jobPipe[i], F_DUPFD, minfd); + if (fd != -1) { + close(job->jobPipe[i]); + job->jobPipe[i] = fd; + } + } + + /* Set close-on-exec flag for both */ + if (fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC) == -1) + Punt("Cannot set close-on-exec: %s", strerror(errno)); + if (fcntl(job->jobPipe[1], 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->jobPipe[0], F_GETFL, 0); + if (flags == -1) + Punt("Cannot get flags: %s", strerror(errno)); + flags |= O_NONBLOCK; + if (fcntl(job->jobPipe[0], F_SETFL, flags) == -1) + Punt("Cannot set flags: %s", strerror(errno)); +} + +/*- + *----------------------------------------------------------------------- + * JobCondPassSig -- + * Pass a signal to a job + * + * Input: + * signop Signal to send it + * + * Side Effects: + * None, except the job may bite it. + * + *----------------------------------------------------------------------- + */ +static void +JobCondPassSig(int signo) +{ + Job *job; + + if (DEBUG(JOB)) { + (void)fprintf(debug_file, "JobCondPassSig(%d) called.\n", signo); + } + + for (job = job_table; job < job_table_end; job++) { + if (job->job_state != JOB_ST_RUNNING) + continue; + if (DEBUG(JOB)) { + (void)fprintf(debug_file, + "JobCondPassSig passing signal %d to child %d.\n", + signo, job->pid); + } + KILLPG(job->pid, signo); + } +} + +/*- + *----------------------------------------------------------------------- + * JobChldSig -- + * SIGCHLD handler. + * + * Input: + * signo The signal number we've received + * + * Results: + * None. + * + * Side Effects: + * 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; +} + + +/*- + *----------------------------------------------------------------------- + * JobContinueSig -- + * Resume all stopped jobs. + * + * Input: + * signo The signal number we've received + * + * Results: + * None. + * + * Side Effects: + * Jobs start running again. + * + *----------------------------------------------------------------------- + */ +static void +JobContinueSig(int signo MAKE_ATTR_UNUSED) +{ + /* + * Defer sending to SIGCONT to our stopped children until we return + * from the signal handler. + */ + while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && + errno == EAGAIN) + continue; +} + +/*- + *----------------------------------------------------------------------- + * JobPassSig -- + * Pass a signal on to all jobs, then resend to ourselves. + * + * Input: + * signo The signal number we've received + * + * Results: + * None. + * + * Side Effects: + * We die by the same signal. + * + *----------------------------------------------------------------------- + */ +MAKE_ATTR_DEAD static void +JobPassSig_int(int signo) +{ + /* Run .INTERRUPT target then exit */ + JobInterrupt(TRUE, signo); +} + +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)) { + (void)fprintf(debug_file, + "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 passign 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); +} + +/*- + *----------------------------------------------------------------------- + * JobFindPid -- + * Compare the pid of the job with the given pid and return 0 if they + * are equal. This function is called from Job_CatchChildren + * to find the job descriptor of the finished job. + * + * Input: + * job job to examine + * pid process id desired + * + * Results: + * Job with matching pid + * + * Side Effects: + * None + *----------------------------------------------------------------------- + */ +static Job * +JobFindPid(int pid, int 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; +} + +/*- + *----------------------------------------------------------------------- + * 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. + * This function is called from JobStart via Lst_ForEach. + * + * Input: + * cmdp command string to print + * jobp job for which to print it + * + * Results: + * Always 0, unless the command was "..." + * + * 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. + * If the command is "..." and we're not ignoring such things, + * tailCmds is set to the successor node of the cmd. + * numCommands is incremented if the command is actually printed. + *----------------------------------------------------------------------- + */ +static int +JobPrintCommand(void *cmdp, void *jobp) +{ + Boolean noSpecials; /* true if we shouldn't worry about + * inserting special commands into + * the input stream. */ + Boolean shutUp = FALSE; /* true if we put a no echo command + * into the command file */ + Boolean errOff = FALSE; /* true if we turned error checking + * off before printing the command + * and need to turn it back on */ + const char *cmdTemplate; /* Template to use when printing the + * command */ + char *cmdStart; /* Start of expanded command */ + char *escCmd = NULL; /* Command with quotes/backticks escaped */ + char *cmd = (char *)cmdp; + Job *job = (Job *)jobp; + + noSpecials = NoExecute(job->node); + + if (strcmp(cmd, "...") == 0) { + job->node->type |= OP_SAVE_CMDS; + if ((job->flags & JOB_IGNDOTS) == 0) { + LstNode dotsNode = Lst_FindDatum(job->node->commands, cmd); + job->tailCmds = dotsNode != NULL ? LstNode_Next(dotsNode) : NULL; + return 1; + } + return 0; + } + +#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ + (void)fprintf(debug_file, fmt, arg); \ + } \ + (void)fprintf(job->cmdFILE, fmt, arg); \ + (void)fflush(job->cmdFILE); + + numCommands += 1; + + cmdStart = cmd = Var_Subst(cmd, job->node, VARE_WANTRES); + + cmdTemplate = "%s\n"; + + /* + * Check for leading @' and -'s to control echoing and error checking. + */ + while (*cmd == '@' || *cmd == '-' || (*cmd == '+')) { + switch (*cmd) { + case '@': + shutUp = DEBUG(LOUD) ? FALSE : TRUE; + break; + case '-': + errOff = TRUE; + break; + case '+': + if (noSpecials) { + /* + * We're not actually executing anything... + * but this one needs to be - use compat mode just for it. + */ + CompatRunCommand(cmdp, job->node); + free(cmdStart); + return 0; + } + break; + } + cmd++; + } + + while (isspace((unsigned char) *cmd)) + cmd++; + + /* + * 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) { + int i, j; + + /* Worst that could happen is every char needs escaping. */ + escCmd = 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] == '"') + escCmd[j++] = '\\'; + escCmd[j] = cmd[i]; + } + escCmd[j] = '\0'; + } + + 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->ignErr); + DBPRINTF("%s\n", commandShell->echoOn); + } else { + DBPRINTF("%s\n", commandShell->ignErr); + } + } else if (commandShell->ignErr && + (*commandShell->ignErr != '\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 + * errCheck 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->errCheck, escCmd); + shutUp = TRUE; + } else { + if (!shutUp) { + DBPRINTF(commandShell->errCheck, escCmd); + } + } + cmdTemplate = commandShell->ignErr; + /* + * The error ignoration (hee hee) is already taken care + * of by the ignErr 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 errOut template, then setup commands to run + * through it. + */ + + if (!commandShell->hasErrCtl && commandShell->errOut && + (*commandShell->errOut != '\0')) { + if (!(job->flags & JOB_SILENT) && !shutUp) { + if (commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOff); + } + DBPRINTF(commandShell->errCheck, 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->ignErr; + else + cmdTemplate = commandShell->errOut; + 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->errCheck); + } + if (shutUp && commandShell->hasEchoCtl) { + DBPRINTF("%s\n", commandShell->echoOn); + } + return 0; +} + +/*- + *----------------------------------------------------------------------- + * JobSaveCommand -- + * Save a command to be executed when everything else is done. + * Callback function for JobFinish... + * + * Results: + * Always returns 0 + * + * Side Effects: + * The command is tacked onto the end of postCommands' commands list. + * + *----------------------------------------------------------------------- + */ +static int +JobSaveCommand(void *cmd, void *gn) +{ + cmd = Var_Subst((char *)cmd, (GNode *)gn, VARE_WANTRES); + Lst_Append(postCommands->commands, cmd); + return 0; +} + + +/*- + *----------------------------------------------------------------------- + * JobClose -- + * Called to close both input and output pipes when a job is finished. + * + * Results: + * Nada + * + * Side Effects: + * The file descriptors associated with the job are closed. + * + *----------------------------------------------------------------------- + */ +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 + * + * Results: + * None + * + * 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. + *----------------------------------------------------------------------- + */ +/*ARGSUSED*/ +static void +JobFinish (Job *job, WAIT_T status) +{ + Boolean done, return_job_token; + + if (DEBUG(JOB)) { + fprintf(debug_file, "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)) { + if (DEBUG(JOB)) { + (void)fprintf(debug_file, "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. In addition, any saved commands for the node are placed + * on the .END target. + */ + if (job->tailCmds != NULL) { + Lst_ForEachFrom(job->node->commands, job->tailCmds, + JobSaveCommand, + job->node); + } + 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 += 1; + job->job_state = JOB_ST_FREE; + } + + /* + * Set aborting if any error. + */ + if (errors && !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); + } +} + +/*- + *----------------------------------------------------------------------- + * Job_Touch -- + * Touch the given target. Called by JobStart when the -t flag was + * given + * + * Input: + * gn the node of the file to touch + * silent TRUE if should not print message + * + * Results: + * None + * + * Side Effects: + * The data modification of the file is changed. In addition, 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 || NoExecute(gn)) { + (void)fprintf(stdout, "touch %s\n", gn->name); + (void)fflush(stdout); + } + + if (NoExecute(gn)) { + return; + } + + if (gn->type & OP_ARCHV) { + Arch_Touch(gn); + } else if (gn->type & OP_LIB) { + Arch_TouchLib(gn); + } else { + char *file = gn->path ? gn->path : gn->name; + + 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); + } + } + } +} + +/*- + *----------------------------------------------------------------------- + * Job_CheckCommands -- + * Make sure the given node has all the commands it needs. + * + * Input: + * gn The target whose commands need verifying + * abortProc Function to abort with message + * + * Results: + * TRUE if the commands list is/was ok. + * + * Side Effects: + * The node will have commands from the .DEFAULT rule added to it + * if it needs them. + *----------------------------------------------------------------------- + */ +Boolean +Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) +{ + if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) && + ((gn->type & OP_LIB) == 0 || Lst_IsEmpty(gn->children))) { + /* + * No commands. Look for .DEFAULT rule from which we might infer + * commands + */ + if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) && + (gn->type & OP_SPECIAL) == 0) { + char *p1; + /* + * 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, Var_Value(TARGET, gn, &p1), gn); + bmake_free(p1); + } else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) { + /* + * The node wasn't the target of an operator we have no .DEFAULT + * 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. + */ + static const char msg[] = ": don't know how to make"; + + 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%s %s (ignored)\n", progname, + msg, gn->name); + (void)fflush(stdout); + } else if (keepgoing) { + (void)fprintf(stdout, "%s%s %s (continuing)\n", progname, + msg, gn->name); + (void)fflush(stdout); + return FALSE; + } else { + (*abortProc)("%s%s %s. Stop", progname, msg, gn->name); + return FALSE; + } + } + } + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * JobExec -- + * Execute the shell for the given job. Called from JobStart + * + * Input: + * job Job to execute + * + * Results: + * None. + * + * Side Effects: + * A shell is executed, outputs 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; + + (void)fprintf(debug_file, "Running %s %sly\n", job->node->name, "local"); + (void)fprintf(debug_file, "\tCommand: "); + for (i = 0; argv[i] != NULL; i++) { + (void)fprintf(debug_file, "%s ", argv[i]); + } + (void)fprintf(debug_file, "\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) { + execError("dup2", "job->cmdFILE"); + _exit(1); + } + if (fcntl(0, F_SETFD, 0) == -1) { + execError("fcntl clear close-on-exec", "stdin"); + _exit(1); + } + if (lseek(0, (off_t)0, SEEK_SET) == -1) { + execError("lseek to 0", "stdin"); + _exit(1); + } + + if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { + /* + * Pass job token pipe to submakes. + */ + if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) { + execError("clear close-on-exec", "tokenWaitJob.inPipe"); + _exit(1); + } + if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) { + execError("clear close-on-exec", "tokenWaitJob.outPipe"); + _exit(1); + } + } + + /* + * Set up the child's output to be routed through the pipe + * we've created for it. + */ + if (dup2(job->outPipe, 1) == -1) { + execError("dup2", "job->outPipe"); + _exit(1); + } + /* + * 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) { + execError("clear close-on-exec", "stdout"); + _exit(1); + } + if (dup2(1, 2) == -1) { + execError("dup2", "1, 2"); + _exit(1); + } + + /* + * 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); + execError("exec", shellPath); + _exit(1); + } + + /* 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)) { + fprintf(debug_file, "JobExec(%s): pid %d added to jobs table\n", + job->node->name, job->pid); + job_table_dump("job started"); + } + JobSigUnlock(&mask); +} + +/*- + *----------------------------------------------------------------------- + * JobMakeArgv -- + * Create the argv needed to execute the shell for a given job. + * + * + * Results: + * + * Side Effects: + * + *----------------------------------------------------------------------- + */ +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 != '-')) || + (commandShell->echo && (*commandShell->echo != '-'))) + { + /* + * 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 int +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) && !(noRecursiveExecute)) || + (!noExecute && !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; + Lst_ForEach(gn->commands, JobPrintCommand, 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 (NoExecute(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) { + Lst_ForEach(gn->commands, JobPrintCommand, 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 == 0) { + if (job->tailCmds != NULL) { + Lst_ForEachFrom(job->node->commands, job->tailCmds, + JobSaveCommand, + job->node); + } + 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, int msg) +{ + char *ecp; + + if (commandShell->noPrint) { + ecp = Str_FindSubstring(cp, commandShell->noPrint); + while (ecp != NULL) { + if (cp != ecp) { + *ecp = '\0'; + if (!beSilent && msg && job->node != lastNode) { + MESSAGE(stdout, job->node); + lastNode = job->node; + } + /* + * 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->noPLen; + 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++; + } + ecp = Str_FindSubstring(cp, commandShell->noPrint); + } 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, transfering 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 + * + * Results: + * None + * + * 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 */ + int nr; /* number of bytes read */ + int i; /* auxiliary index into outBuf */ + int max; /* limit for i (end of current data) */ + int 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 = 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--) { + 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], FALSE); + + /* + * 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 (!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) +{ +#ifdef notyet + /* + * Unfortunately it is too complicated to run .BEGIN, .END, + * and .INTERRUPT job in the parallel job module. This has + * the nice side effect that it avoids a lot of other problems. + */ + Lst lst = Lst_Init(); + 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 +} + +/*- + *----------------------------------------------------------------------- + * Job_CatchChildren -- + * Handle the exit of a child. Called from Make_Make. + * + * Input: + * block TRUE if should block on the wait + * + * Results: + * none. + * + * Side Effects: + * 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) { + if (DEBUG(JOB)) { + (void)fprintf(debug_file, "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)) { + if (DEBUG(JOB)) { + (void)fprintf(debug_file, "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); +} + +/*- + *----------------------------------------------------------------------- + * Job_CatchOutput -- + * 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. + * + * Results: + * None + * + * Side Effects: + * Output is read from pipes if we're piping. + * ----------------------------------------------------------------------- + */ +void +Job_CatchOutput(void) +{ + int nready; + Job *job; + 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; + } +} + +/*- + *----------------------------------------------------------------------- + * Job_Make -- + * Start the creation of a target. Basically a front-end for + * JobStart used by the Make module. + * + * Results: + * None. + * + * Side Effects: + * Another job is started. + * + *----------------------------------------------------------------------- + */ +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_CMD, VAR_SET_READONLY); + if (commandShell->exit == NULL) { + commandShell->exit = ""; + } + if (commandShell->echo == NULL) { + commandShell->echo = ""; + } + if (commandShell->hasErrCtl && *commandShell->exit) { + if (shellErrFlag && + strcmp(commandShell->exit, &shellErrFlag[1]) != 0) { + free(shellErrFlag); + shellErrFlag = NULL; + } + if (!shellErrFlag) { + int n = strlen(commandShell->exit) + 2; + + shellErrFlag = bmake_malloc(n); + if (shellErrFlag) { + snprintf(shellErrFlag, n, "-%s", commandShell->exit); + } + } + } else if (shellErrFlag) { + free(shellErrFlag); + shellErrFlag = NULL; + } +} + +/*- + * Returns 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); + } + + targPrefix = Var_Subst("${" MAKE_JOB_PREFIX "}", + VAR_GLOBAL, VARE_WANTRES); +} + +/* Initialize the process module. */ +void +Job_Init(void) +{ + Job_SetPrefix(); + /* Allocate space for all the job info */ + job_table = bmake_malloc(maxJobs * sizeof *job_table); + memset(job_table, 0, maxJobs * sizeof *job_table); + job_table_end = job_table + maxJobs; + wantToken = 0; + + aborting = 0; + 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 + maxJobs) * nfds_per_job()); + jobfds = bmake_malloc(sizeof(*jobfds) * + (npseudojobs + 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); + postCommands = Targ_FindNode(".END", TARG_CREATE); +} + +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 * +JobMatchShell(const char *name) +{ + Shell *sh; + + for (sh = shells; sh->name != NULL; 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; + + while (isspace((unsigned char)*line)) { + 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++) { + if (strncmp(*argv, "path=", 5) == 0) { + path = &argv[0][5]; + } else if (strncmp(*argv, "name=", 5) == 0) { + newShell.name = &argv[0][5]; + } else { + if (strncmp(*argv, "quiet=", 6) == 0) { + newShell.echoOff = &argv[0][6]; + } else if (strncmp(*argv, "echo=", 5) == 0) { + newShell.echoOn = &argv[0][5]; + } else if (strncmp(*argv, "filter=", 7) == 0) { + newShell.noPrint = &argv[0][7]; + newShell.noPLen = strlen(newShell.noPrint); + } else if (strncmp(*argv, "echoFlag=", 9) == 0) { + newShell.echo = &argv[0][9]; + } else if (strncmp(*argv, "errFlag=", 8) == 0) { + newShell.exit = &argv[0][8]; + } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) { + char c = argv[0][10]; + newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && + (c != 'T') && (c != 't')); + } else if (strncmp(*argv, "newline=", 8) == 0) { + newShell.newline = &argv[0][8]; + } else if (strncmp(*argv, "check=", 6) == 0) { + newShell.errCheck = &argv[0][6]; + } else if (strncmp(*argv, "ignore=", 7) == 0) { + newShell.ignErr = &argv[0][7]; + } else if (strncmp(*argv, "errout=", 7) == 0) { + newShell.errOut = &argv[0][7]; + } else if (strncmp(*argv, "comment=", 8) == 0) { + newShell.commentChar = argv[0][8]; + } else { + Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", + *argv); + 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 JobMatchShell + * 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 = JobMatchShell(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 += 1; + } + if (newShell.name != NULL) { + shellName = newShell.name; + } else { + shellName = path; + } + if (!fullSpec) { + if ((sh = JobMatchShell(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->errCheck == NULL) { + commandShell->errCheck = ""; + } + if (commandShell->ignErr == NULL) { + commandShell->ignErr = "%s\n"; + } + } + + /* + * Do not free up the words themselves, since they might be in use by the + * shell specification. + */ + free(words); + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * JobInterrupt -- + * Handle the receipt of an interrupt. + * + * Input: + * runINTERRUPT Non-zero if commands for the .INTERRUPT target + * should be executed + * signo signal received + * + * Results: + * None + * + * Side Effects: + * All children are killed. Another job will be started if the + * .INTERRUPT target was given. + *----------------------------------------------------------------------- + */ +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) { + if (DEBUG(JOB)) { + (void)fprintf(debug_file, + "JobInterrupt passing signal %d to child %d.\n", + signo, job->pid); + } + KILLPG(job->pid, signo); + } + } + + JobSigUnlock(&mask); + + if (runINTERRUPT && !touchFlag) { + interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); + if (interrupt != NULL) { + ignoreErrors = FALSE; + JobRun(interrupt); + } + } + Trace_Log(MAKEINTR, 0); + exit(signo); +} + +/* + *----------------------------------------------------------------------- + * Job_Finish -- + * Do final processing such as the running of the commands + * attached to the .END target. + * + * Results: + * Number of errors reported. + * + * Side Effects: + * None. + *----------------------------------------------------------------------- + */ +int +Job_Finish(void) +{ + if (postCommands != NULL && + (!Lst_IsEmpty(postCommands->commands) || + !Lst_IsEmpty(postCommands->children))) { + if (errors) { + Error("Errors reported so .END ignored"); + } else { + JobRun(postCommands); + } + } + return errors; +} + +/*- + *----------------------------------------------------------------------- + * Job_End -- + * Cleanup any memory used by the jobs module + * + * Results: + * None. + * + * Side Effects: + * Memory is freed + *----------------------------------------------------------------------- + */ +void +Job_End(void) +{ +#ifdef CLEANUP + free(shellArgv); +#endif +} + +/*- + *----------------------------------------------------------------------- + * Job_Wait -- + * Waits for all running jobs to finish and returns. Sets 'aborting' + * to ABORT_WAIT to prevent other jobs from starting. + * + * Results: + * None. + * + * Side Effects: + * Currently running jobs finish. + * + *----------------------------------------------------------------------- + */ +void +Job_Wait(void) +{ + aborting = ABORT_WAIT; + while (jobTokensRunning != 0) { + Job_CatchOutput(); + } + aborting = 0; +} + +/*- + *----------------------------------------------------------------------- + * Job_AbortAll -- + * 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. + * + * Results: + * None + * + * Side Effects: + * 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; +} + +/*- + *----------------------------------------------------------------------- + * JobRestartJobs -- + * Tries to restart stopped jobs if there are slots available. + * Called in process context in response to a SIGCONT. + * + * Results: + * None. + * + * Side Effects: + * Resumes jobs. + * + *----------------------------------------------------------------------- + */ +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)) { + if (DEBUG(JOB)) { + (void)fprintf(debug_file, "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)) { + fprintf(debug_file, "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) +{ + int i; + if (job->inPollfd == NULL) + Punt("Unwatching unwatched job"); + i = 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; +} + +/*- + *----------------------------------------------------------------------- + * JobTokenAdd -- + * Put a token into the job pipe so that some make process can start + * another job. + * + * Side Effects: + * Allows more build jobs to be spawned somewhere. + * + *----------------------------------------------------------------------- + */ + +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; + + if (DEBUG(JOB)) + fprintf(debug_file, "(%d) aborting %d, deposit token %c\n", + getpid(), aborting, JOB_TOKENS[aborting]); + while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) + continue; +} + +/*- + *----------------------------------------------------------------------- + * Job_ServerStartTokenAdd -- + * 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(); +} + +/*- + *----------------------------------------------------------------------- + * Job_TokenReturn -- + * Return a withdrawn token to the pool. + * + *----------------------------------------------------------------------- + */ + +void +Job_TokenReturn(void) +{ + jobTokensRunning--; + if (jobTokensRunning < 0) + Punt("token botch"); + if (jobTokensRunning || JOB_TOKENS[aborting] != '+') + JobTokenAdd(); +} + +/*- + *----------------------------------------------------------------------- + * Job_TokenWithdraw -- + * Attempt to withdraw a token from the pool. + * + * Results: + * Returns TRUE if a token was withdrawn, and FALSE if the pool + * is currently empty. + * + * Side Effects: + * If pool is empty, set wantToken so that we wake up + * when a token is released. + * + *----------------------------------------------------------------------- + */ + + +Boolean +Job_TokenWithdraw(void) +{ + char tok, tok1; + int count; + + wantToken = 0; + if (DEBUG(JOB)) + fprintf(debug_file, "Job_TokenWithdraw(%d): aborting %d, running %d\n", + getpid(), aborting, jobTokensRunning); + + if (aborting || (jobTokensRunning >= 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)); + } + if (DEBUG(JOB)) + fprintf(debug_file, "(%d) blocked for token\n", getpid()); + return FALSE; + } + + if (count == 1 && tok != '+') { + /* make being abvorted - remove any other job tokens */ + if (DEBUG(JOB)) + fprintf(debug_file, "(%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++; + if (DEBUG(JOB)) + fprintf(debug_file, "(%d) withdrew token\n", getpid()); + return TRUE; +} + +/*- + *----------------------------------------------------------------------- + * Job_RunTarget -- + * Run the named target if found. If a filename is specified, then + * set that to the sources. + * + * Results: + * None + * + * Side Effects: + * exits if the target fails. + * + *----------------------------------------------------------------------- + */ +Boolean +Job_RunTarget(const char *target, const char *fname) { + GNode *gn = Targ_FindNode(target, TARG_NOCREATE); + + 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/20200902/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/20200902/job.h =================================================================== --- vendor/NetBSD/bmake/20200902/job.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/job.h (revision 365363) @@ -0,0 +1,269 @@ +/* $NetBSD: job.h,v 1.47 2020/08/29 12:20:17 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 + */ + +/*- + * job.h -- + * Definitions pertaining to the 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 + +/*- + * Job Table definitions. + * + * Each job has several things associated with it: + * 1) The process id of the child shell + * 2) The graph node describing the target being made by this job + * 3) A LstNode for the first command to be saved after the job + * completes. This is NULL if there was no "..." in the job's + * commands. + * 4) An FILE* for writing out the commands. This is only + * used before the job is actually started. + * 5) The output is being caught via a pipe and + * the descriptors of our pipe, an array in which output is line + * buffered and the current position in that buffer are all + * maintained for each job. + * 6) A word of flags which determine how the module handles errors, + * echoing, etc. for the job + * + * When a job is finished, the Make_Update function is called on each of the + * parents of the node which was just remade. This takes care of the upward + * traversal of the dependency graph. + */ +struct pollfd; + + +#ifdef USE_META +# include "meta.h" +#endif + +#define JOB_BUFSIZE 1024 +typedef struct Job { + int pid; /* The child's process ID */ + GNode *node; /* The target the child is making */ + LstNode tailCmds; /* The node of the first command to be + * saved when the job has been run */ + FILE *cmdFILE; /* When creating the shell script, this is + * where the commands go */ + int exit_status; /* from wait4() in signal handler */ + char job_state; /* status of the job entry */ +#define JOB_ST_FREE 0 /* Job is available */ +#define JOB_ST_SETUP 1 /* Job is allocated but otherwise invalid */ +#define JOB_ST_RUNNING 3 /* Job is running, pid valid */ +#define JOB_ST_FINISHED 4 /* Job is done (ie after SIGCHILD) */ + char job_suspended; + short flags; /* Flags to control treatment of job */ +#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ +#define JOB_SILENT 0x002 /* no output */ +#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally + * if we can't export it and maxLocal is 0 */ +#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing + * commands */ +#define JOB_TRACED 0x400 /* we've sent 'set -x' */ + + int jobPipe[2]; /* Pipe for reading output from job */ + struct pollfd *inPollfd; /* pollfd associated with inPipe */ + char outBuf[JOB_BUFSIZE + 1]; + /* Buffer for storing the output of the + * job, line by line */ + int curPos; /* Current position in op_outBuf */ + +#ifdef USE_META + struct BuildMon bm; +#endif +} Job; + +#define inPipe jobPipe[0] +#define outPipe jobPipe[1] + +/*- + * Shell Specifications: + * Each shell type has associated with it the following information: + * 1) The string which must match the last character of the shell name + * for the shell to be considered of this type. The longest match + * wins. + * 2) A command to issue to turn off echoing of command lines + * 3) A command to issue to turn echoing back on again + * 4) What the shell prints, and its length, when given the echo-off + * command. This line will not be printed when received from the shell + * 5) A boolean to tell if the shell has the ability to control + * error checking for individual commands. + * 6) The string to turn this checking on. + * 7) The string to turn it off. + * 8) The command-flag to give to cause the shell to start echoing + * commands right away. + * 9) The command-flag to cause the shell to Lib_Exit when an error is + * detected in one of the commands. + * + * Some special stuff goes on if a shell doesn't have error control. In such + * a case, errCheck becomes a printf template for echoing the command, + * should echoing be on and ignErr becomes another printf template for + * executing the command while ignoring the return status. Finally errOut + * 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 '$ ` \ "'i + * characters in the command string to avoid common problems with + * echo "%s\n" as a template. + */ +typedef struct Shell { + const char *name; /* 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. + */ + 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; /* command to skip when printing output from + * shell. This is usually the command which + * was executed to turn off echoing */ + int noPLen; /* length of noPrint command */ + Boolean hasErrCtl; /* set if can control error checking for + * individual commands */ + const char *errCheck; /* string to turn error checking on */ + const char *ignErr; /* string to turn off error checking */ + const char *errOut; /* string to use for testing exit code */ + const char *newline; /* string literal that results in a newline + * character when it appears outside of any + * 'quote' or "quote" characters */ + char commentChar; /* character used by shell for comment lines */ + + /* + * command-line flags + */ + const char *echo; /* echo commands */ + const char *exit; /* exit on error */ +} Shell; + +extern const char *shellPath; +extern const char *shellName; +extern char *shellErrFlag; + +extern int jobTokensRunning; /* tokens currently "out" */ +extern int maxJobs; /* Max jobs we can run */ + +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_Empty(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/20200902/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/20200902/lst.c =================================================================== --- vendor/NetBSD/bmake/20200902/lst.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/lst.c (revision 365363) @@ -0,0 +1,641 @@ +/* $NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_INTTYPES_H +#include +#elif defined(HAVE_STDINT_H) +#include +#endif + +#include "make.h" + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 rillig Exp $"; +#else +#include +#ifndef lint +__RCSID("$NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 rillig Exp $"); +#endif /* not lint */ +#endif + +struct ListNode { + struct ListNode *prev; /* previous element in list */ + struct ListNode *next; /* next in list */ + uint8_t useCount; /* Count of functions using the node. + * node may not be deleted until count + * goes to 0 */ + Boolean deleted; /* List node should be removed when done */ + union { + void *datum; /* datum associated with this element */ + const GNode *gnode; /* alias, just for debugging */ + const char *str; /* alias, just for debugging */ + }; +}; + +typedef enum { + Head, Middle, Tail, Unknown +} Where; + +struct List { + LstNode first; /* first node in list */ + LstNode last; /* last node in list */ + + /* fields for sequential access */ + Boolean isOpen; /* true if list has been Lst_Open'ed */ + Where lastAccess; /* Where in the list the last access was */ + LstNode curr; /* current node, if open. NULL if + * *just* opened */ + LstNode prev; /* Previous node, if open. Used by Lst_Remove */ +}; + +/* Allocate and initialize a list node. + * + * The fields 'prev' and 'next' must be initialized by the caller. + */ +static LstNode +LstNodeNew(void *datum) +{ + LstNode node = bmake_malloc(sizeof *node); + node->useCount = 0; + node->deleted = FALSE; + node->datum = datum; + return node; +} + +static Boolean +LstIsEmpty(Lst list) +{ + return list->first == NULL; +} + +/* Create and initialize a new, empty list. */ +Lst +Lst_Init(void) +{ + Lst list = bmake_malloc(sizeof *list); + + list->first = NULL; + list->last = NULL; + list->isOpen = FALSE; + list->lastAccess = Unknown; + + return list; +} + +/* Duplicate an entire list, usually by copying the datum pointers. + * If copyProc is given, that function is used to create the new datum from the + * old datum, usually by creating a copy of it. */ +Lst +Lst_Copy(Lst list, LstCopyProc copyProc) +{ + Lst newList; + LstNode node; + + assert(list != NULL); + + newList = Lst_Init(); + + for (node = list->first; node != NULL; node = node->next) { + void *datum = copyProc != NULL ? copyProc(node->datum) : node->datum; + Lst_Append(newList, datum); + } + + return newList; +} + +/* Free a list and all its nodes. The list data itself are not freed though. */ +void +Lst_Free(Lst list) +{ + LstNode node; + LstNode next; + + assert(list != NULL); + + 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(Lst list, LstFreeProc freeProc) +{ + LstNode node; + LstNode next; + + assert(list != NULL); + assert(freeProc != NULL); + + 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 given piece of data before the given node in the + * given list. */ +void +Lst_InsertBefore(Lst list, LstNode node, void *datum) +{ + LstNode newNode; + + assert(list != NULL); + assert(!LstIsEmpty(list)); + assert(node != NULL); + assert(datum != NULL); + + newNode = LstNodeNew(datum); + newNode->prev = node->prev; + newNode->next = node; + + 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(Lst list, void *datum) +{ + LstNode node; + + assert(list != NULL); + assert(datum != NULL); + + node = LstNodeNew(datum); + node->prev = NULL; + node->next = list->first; + + 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(Lst list, void *datum) +{ + LstNode node; + + assert(list != NULL); + assert(datum != NULL); + + node = LstNodeNew(datum); + node->prev = list->last; + node->next = NULL; + + 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(Lst list, LstNode node) +{ + assert(list != NULL); + assert(node != NULL); + + /* + * unlink it from the list + */ + if (node->next != NULL) { + node->next->prev = node->prev; + } + if (node->prev != NULL) { + node->prev->next = node->next; + } + + /* + * if either the first or last of the list point to this node, + * adjust them accordingly + */ + if (list->first == node) { + list->first = node->next; + } + if (list->last == node) { + list->last = node->prev; + } + + /* + * Sequential access stuff. If the node we're removing is the current + * node in the list, reset the current node to the previous one. If the + * previous one was non-existent (prev == NULL), we set the + * end to be Unknown, since it is. + */ + if (list->isOpen && list->curr == node) { + list->curr = list->prev; + if (list->curr == NULL) { + list->lastAccess = Unknown; + } + } + + /* + * note that the datum is unmolested. The caller must free it as + * necessary and as expected. + */ + if (node->useCount == 0) { + free(node); + } else { + node->deleted = TRUE; + } +} + +/* Replace the datum in the given node with the new datum. */ +void +LstNode_Set(LstNode node, void *datum) +{ + assert(node != NULL); + assert(datum != NULL); + + node->datum = datum; +} + +/* Replace the datum in the given node to NULL. */ +void +LstNode_SetNull(LstNode node) +{ + assert(node != NULL); + + node->datum = NULL; +} + + +/* + * Node-specific functions + */ + +/* Return the first node from the given list, or NULL if the list is empty. */ +LstNode +Lst_First(Lst list) +{ + assert(list != NULL); + + return list->first; +} + +/* Return the last node from the given list, or NULL if the list is empty. */ +LstNode +Lst_Last(Lst list) +{ + assert(list != NULL); + + return list->last; +} + +/* Return the successor to the given node on its list, or NULL. */ +LstNode +LstNode_Next(LstNode node) +{ + assert(node != NULL); + + return node->next; +} + +/* Return the predecessor to the given node on its list, or NULL. */ +LstNode +LstNode_Prev(LstNode node) +{ + assert(node != NULL); + return node->prev; +} + +/* Return the datum stored in the given node. */ +void * +LstNode_Datum(LstNode node) +{ + assert(node != NULL); + return node->datum; +} + + +/* + * Functions for entire lists + */ + +/* Return TRUE if the given list is empty. */ +Boolean +Lst_IsEmpty(Lst list) +{ + assert(list != NULL); + + return LstIsEmpty(list); +} + +/* Return the first node from the list for which the match function returns + * TRUE, or NULL if none of the nodes matched. */ +LstNode +Lst_Find(Lst list, LstFindProc match, const void *matchArgs) +{ + return Lst_FindFrom(list, Lst_First(list), match, matchArgs); +} + +/* Return the first node from the list, starting at the given node, for which + * the match function returns TRUE, or NULL if none of the nodes matches. + * + * The start node may be NULL, in which case nothing is found. This allows + * for passing Lst_First or LstNode_Next as the start node. */ +LstNode +Lst_FindFrom(Lst list, LstNode node, LstFindProc match, const void *matchArgs) +{ + LstNode tln; + + assert(list != NULL); + assert(match != NULL); + + for (tln = node; tln != NULL; tln = tln->next) { + if (match(tln->datum, matchArgs)) + return tln; + } + + return NULL; +} + +/* Return the first node that contains the given datum, or NULL. */ +LstNode +Lst_FindDatum(Lst list, const void *datum) +{ + LstNode node; + + assert(list != NULL); + assert(datum != NULL); + + for (node = list->first; node != NULL; node = node->next) { + if (node->datum == datum) { + return node; + } + } + + return NULL; +} + +/* Apply the given function to each element of the given list. The function + * should return 0 if traversal should continue and non-zero if it should + * abort. */ +int +Lst_ForEach(Lst list, LstActionProc proc, void *procData) +{ + if (LstIsEmpty(list)) + return 0; /* XXX: Document what this value means. */ + return Lst_ForEachFrom(list, Lst_First(list), proc, procData); +} + +/* Apply the given function to each element of the given list, starting from + * the given node. The function should return 0 if traversal should continue, + * and non-zero if it should abort. */ +int +Lst_ForEachFrom(Lst list, LstNode node, + LstActionProc proc, void *procData) +{ + LstNode tln = node; + LstNode next; + Boolean done; + int result; + + assert(list != NULL); + assert(node != NULL); + assert(proc != NULL); + + do { + /* + * Take care of having the current element deleted out from under + * us. + */ + + next = tln->next; + + /* + * We're done with the traversal if + * - the next node to examine doesn't exist and + * - nothing's been added after the current node (check this + * after proc() has been called). + */ + done = next == NULL; + + tln->useCount++; + result = (*proc)(tln->datum, procData); + tln->useCount--; + + /* + * Now check whether a node has been added. + * Note: this doesn't work if this node was deleted before + * the new node was added. + */ + if (next != tln->next) { + next = tln->next; + done = 0; + } + + if (tln->deleted) { + free((char *)tln); + } + tln = next; + } while (!result && !LstIsEmpty(list) && !done); + + return result; +} + +/* Move all nodes from list2 to the end of list1. + * List2 is destroyed and freed. */ +void +Lst_MoveAll(Lst list1, Lst list2) +{ + assert(list1 != NULL); + assert(list2 != NULL); + + 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(Lst dst, Lst src) +{ + LstNode 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(Lst dst, Lst src) +{ + LstNode node; + for (node = src->first; node != NULL; node = node->next) + Lst_Append(dst, node->datum); +} + +/* + * these functions are for dealing with a list as a table, of sorts. + * An idea of the "current element" is kept and used by all the functions + * between Lst_Open() and Lst_Close(). + * + * The sequential functions access the list in a slightly different way. + * CurPtr points to their idea of the current node in the list and they + * access the list based on it. + */ + +/* Open a list for sequential access. A list can still be searched, etc., + * without confusing these functions. */ +void +Lst_Open(Lst list) +{ + assert(list != NULL); + assert(!list->isOpen); + + list->isOpen = TRUE; + list->lastAccess = LstIsEmpty(list) ? Head : Unknown; + list->curr = NULL; +} + +/* Return the next node for the given list, or NULL if the end has been + * reached. */ +LstNode +Lst_Next(Lst list) +{ + LstNode node; + + assert(list != NULL); + assert(list->isOpen); + + list->prev = list->curr; + + if (list->curr == NULL) { + if (list->lastAccess == Unknown) { + /* + * If we're just starting out, lastAccess will be Unknown. + * Then we want to start this thing off in the right + * direction -- at the start with lastAccess being Middle. + */ + list->curr = node = list->first; + list->lastAccess = Middle; + } else { + node = NULL; + list->lastAccess = Tail; + } + } else { + node = list->curr->next; + list->curr = node; + + if (node == list->first || node == NULL) { + /* + * If back at the front, then we've hit the end... + */ + list->lastAccess = Tail; + } else { + /* + * Reset to Middle if gone past first. + */ + list->lastAccess = Middle; + } + } + + return node; +} + +/* Close a list which was opened for sequential access. */ +void +Lst_Close(Lst list) +{ + assert(list != NULL); + assert(list->isOpen); + + list->isOpen = FALSE; + list->lastAccess = Unknown; +} + + +/* + * for using the list as a queue + */ + +/* Add the datum to the tail of the given list. */ +void +Lst_Enqueue(Lst list, void *datum) +{ + Lst_Append(list, datum); +} + +/* Remove and return the datum at the head of the given list. */ +void * +Lst_Dequeue(Lst list) +{ + void *datum; + + assert(list != NULL); + assert(!LstIsEmpty(list)); + + datum = list->first->datum; + Lst_Remove(list, list->first); + assert(datum != NULL); + return datum; +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/lst.h =================================================================== --- vendor/NetBSD/bmake/20200902/lst.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/lst.h (revision 365363) @@ -0,0 +1,179 @@ +/* $NetBSD: lst.h,v 1.60 2020/09/02 23:33:13 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 + +/* A doubly-linked list of pointers. */ +typedef struct List *Lst; +/* A single node in the doubly-linked list. */ +typedef struct ListNode *LstNode; + +/* Copy a node, usually by allocating a copy of the given object. + * For reference-counted objects, the original object may need to be + * modified, therefore the parameter is not const. */ +typedef void *LstCopyProc(void *); +/* Free the datum of a node, called before freeing the node itself. */ +typedef void LstFreeProc(void *); +/* Return TRUE if the datum matches the args, for Lst_Find. */ +typedef Boolean LstFindProc(const void *datum, const void *args); +/* An action for Lst_ForEach. */ +typedef int LstActionProc(void *datum, void *args); + +/* Create or destroy a list */ + +/* Create a new list. */ +Lst Lst_Init(void); +/* Duplicate an existing list. */ +Lst Lst_Copy(Lst, LstCopyProc); +/* Free the list, leaving the node data unmodified. */ +void Lst_Free(Lst); +/* Free the list, freeing the node data using the given function. */ +void Lst_Destroy(Lst, LstFreeProc); + +/* Get information about a list */ + +Boolean Lst_IsEmpty(Lst); +/* Return the first node of the list, or NULL. */ +LstNode Lst_First(Lst); +/* Return the last node of the list, or NULL. */ +LstNode Lst_Last(Lst); +/* Find the first node for which the function returns TRUE, or NULL. */ +LstNode Lst_Find(Lst, LstFindProc, const void *); +/* Find the first node for which the function returns TRUE, or NULL. + * The search starts at the given node, towards the end of the list. */ +LstNode Lst_FindFrom(Lst, LstNode, LstFindProc, const void *); +/* Find the first node that contains the given datum, or NULL. */ +LstNode Lst_FindDatum(Lst, const void *); + +/* Modify a list */ + +/* Insert a datum before the given node. */ +void Lst_InsertBefore(Lst, LstNode, void *); +/* Place a datum at the front of the list. */ +void Lst_Prepend(Lst, void *); +/* Place a datum at the end of the list. */ +void Lst_Append(Lst, void *); +/* Remove the node from the list. */ +void Lst_Remove(Lst, LstNode); +void Lst_PrependAll(Lst, Lst); +void Lst_AppendAll(Lst, Lst); +void Lst_MoveAll(Lst, Lst); + +/* Node-specific functions */ + +/* Return the successor of the node, or NULL. */ +LstNode LstNode_Next(LstNode); +/* Return the predecessor of the node, or NULL. */ +LstNode LstNode_Prev(LstNode); +/* Return the datum of the node. Usually not NULL. */ +void *LstNode_Datum(LstNode); +/* Replace the value of the node. */ +void LstNode_Set(LstNode, void *); +/* Set the value of the node to NULL. Having NULL in a list is unusual. */ +void LstNode_SetNull(LstNode); + +/* Iterating over a list, using a callback function */ + +/* Apply a function to each datum of the list, until the callback function + * returns non-zero. */ +int Lst_ForEach(Lst, LstActionProc, void *); +/* Apply a function to each datum of the list, starting at the node, + * until the callback function returns non-zero. */ +int Lst_ForEachFrom(Lst, LstNode, LstActionProc, void *); + +/* Iterating over a list while keeping track of the current node and possible + * concurrent modifications */ + +/* Start iterating the list. */ +void Lst_Open(Lst); +/* Return the next node, or NULL. */ +LstNode Lst_Next(Lst); +/* Finish iterating the list. */ +void Lst_Close(Lst); + +/* Using the list as a queue */ + +/* Add a datum at the tail of the queue. */ +void Lst_Enqueue(Lst, void *); +/* Remove the head node of the queue and return its datum. */ +void *Lst_Dequeue(Lst); + +#endif /* MAKE_LST_H */ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/main.c =================================================================== --- vendor/NetBSD/bmake/20200902/main.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/main.c (revision 365363) @@ -0,0 +1,2220 @@ +/* $NetBSD: main.c,v 1.331 2020/08/30 19:56:02 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: main.c,v 1.331 2020/08/30 19:56:02 rillig Exp $"; +#else +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: main.c,v 1.331 2020/08/30 19:56:02 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 +#include +#include + +#include "make.h" +#include "hash.h" +#include "dir.h" +#include "job.h" +#include "pathnames.h" +#include "trace.h" + +#ifdef USE_IOVEC +#include +#endif + +#ifndef DEFMAXLOCAL +#define DEFMAXLOCAL DEFMAXJOBS +#endif /* DEFMAXLOCAL */ + +#ifndef __arraycount +# define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) +#endif + +Lst create; /* Targets to be made */ +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 Boolean noBuiltins; /* -r flag */ +static Lst makefiles; /* ordered list of makefiles to read */ +static int printVars; /* -[vV] argument */ +#define COMPAT_VARS 1 +#define EXPAND_VARS 2 +static Lst variables; /* list of variables to print + * (for -v and -V) */ +int maxJobs; /* -j argument */ +static int maxJobTokens; /* -j argument */ +Boolean compatMake; /* -B argument */ +int debug; /* -d argument */ +Boolean debugVflag; /* -dV */ +Boolean noExecute; /* -n flag */ +Boolean noRecursiveExecute; /* -N flag */ +Boolean keepgoing; /* -k flag */ +Boolean queryFlag; /* -q flag */ +Boolean touchFlag; /* -t flag */ +Boolean enterFlag; /* -w flag */ +Boolean enterFlagObj; /* -w and objdir != srcdir */ +Boolean ignoreErrors; /* -i flag */ +Boolean beSilent; /* -s flag */ +Boolean oldVars; /* variable substitution style */ +Boolean checkEnvFirst; /* -e flag */ +Boolean parseWarnFatal; /* -W flag */ +static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */ +Boolean varNoExportEnv; /* -X flag */ +Boolean doing_depend; /* Set while reading .depend */ +static Boolean jobsRunning; /* TRUE if the jobs might be running */ +static const char * tracefile; +static void MainParseArgs(int, char **); +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; + +FILE *debug_file; + +Boolean forceJobs = FALSE; + +/* + * On some systems MACHINE is defined as something other than + * what we want. + */ +#ifdef FORCE_MACHINE +# undef MACHINE +# define MACHINE FORCE_MACHINE +#endif + +extern Lst 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 (!isalpha((unsigned char)*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_options(const char *argvalue) +{ + const char *modules; + const char *mode; + char *fname; + int len; + + for (modules = argvalue; *modules; ++modules) { + switch (*modules) { + case 'A': + debug = ~(0|DEBUG_LINT); + break; + case 'a': + debug |= DEBUG_ARCH; + break; + case 'C': + debug |= DEBUG_CWD; + break; + case 'c': + debug |= DEBUG_COND; + break; + case 'd': + debug |= DEBUG_DIR; + break; + case 'e': + debug |= DEBUG_ERROR; + break; + case 'f': + debug |= DEBUG_FOR; + break; + case 'g': + if (modules[1] == '1') { + debug |= DEBUG_GRAPH1; + ++modules; + } + else if (modules[1] == '2') { + debug |= DEBUG_GRAPH2; + ++modules; + } + else if (modules[1] == '3') { + debug |= DEBUG_GRAPH3; + ++modules; + } + break; + case 'h': + debug |= DEBUG_HASH; + break; + case 'j': + debug |= DEBUG_JOB; + break; + case 'L': + debug |= DEBUG_LINT; + break; + case 'l': + debug |= DEBUG_LOUD; + break; + case 'M': + debug |= DEBUG_META; + break; + case 'm': + debug |= DEBUG_MAKE; + break; + case 'n': + debug |= DEBUG_SCRIPT; + break; + case 'p': + debug |= DEBUG_PARSE; + break; + case 's': + debug |= DEBUG_SUFF; + break; + case 't': + debug |= DEBUG_TARG; + break; + case 'V': + debugVflag = TRUE; + break; + case 'v': + debug |= DEBUG_VAR; + break; + case 'x': + debug |= DEBUG_SHELL; + break; + case 'F': + if (debug_file != stdout && debug_file != stderr) + fclose(debug_file); + if (*++modules == '+') { + modules++; + mode = "a"; + } else + mode = "w"; + if (strcmp(modules, "stdout") == 0) { + debug_file = stdout; + goto debug_setbuf; + } + if (strcmp(modules, "stderr") == 0) { + debug_file = stderr; + goto debug_setbuf; + } + 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()); + debug_file = fopen(fname, mode); + if (!debug_file) { + fprintf(stderr, "Cannot open debug file %s\n", + fname); + usage(); + } + free(fname); + 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(debug_file, NULL, _IONBF, 0); + if (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; +} + +/*- + * MainParseArgs -- + * Parse a given argument vector. Called from main() and from + * Main_ParseArgLine() when the .MAKEFLAGS target is used. + * + * XXX: Deal with command line overriding .MAKEFLAGS in makefile + * + * Results: + * None + * + * Side Effects: + * Various global and local flags will be set depending on the flags + * given + */ +static void +MainParseArgs(int argc, char **argv) +{ + char *p; + char c = '?'; + int arginc; + char *argvalue; + const char *getopt_def; + struct stat sa, sb; + char *optscan; + Boolean inOption, dashDash = FALSE; + char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ + +#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w" +/* Can't actually use getopt(3) because rescanning is not portable */ + + getopt_def = OPTFLAGS; +rearg: + inOption = FALSE; + optscan = NULL; + while(argc > 1) { + char *getopt_spec; + 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 */ + getopt_spec = strchr(getopt_def, c); + if(c != '\0' && getopt_spec != NULL && getopt_spec[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 'B': + compatMake = TRUE; + Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); + Var_Set(MAKE_MODE, "compat", VAR_GLOBAL); + break; + case 'C': + 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; + break; + case 'D': + if (argvalue == NULL || argvalue[0] == 0) goto noarg; + Var_Set(argvalue, "1", VAR_GLOBAL); + Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'I': + if (argvalue == NULL) goto noarg; + Parse_AddIncludeDir(argvalue); + Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'J': + if (argvalue == NULL) goto noarg; + 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; + compatMake = TRUE; + } else { + Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + } + break; + case 'N': + noExecute = TRUE; + noRecursiveExecute = TRUE; + Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); + break; + case 'S': + keepgoing = FALSE; + Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); + break; + case 'T': + if (argvalue == NULL) goto noarg; + tracefile = bmake_strdup(argvalue); + Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'V': + case 'v': + if (argvalue == NULL) goto noarg; + printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS; + Lst_Append(variables, argvalue); + Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'W': + parseWarnFatal = TRUE; + break; + case 'X': + varNoExportEnv = TRUE; + Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); + break; + case 'd': + if (argvalue == NULL) goto noarg; + /* 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': + checkEnvFirst = TRUE; + Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); + break; + case 'f': + if (argvalue == NULL) goto noarg; + Lst_Append(makefiles, argvalue); + break; + case 'i': + ignoreErrors = TRUE; + Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); + break; + case 'j': + if (argvalue == NULL) goto noarg; + forceJobs = TRUE; + maxJobs = strtol(argvalue, &p, 0); + if (*p != '\0' || maxJobs < 1) { + (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n", + progname); + exit(1); + } + Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL); + maxJobTokens = maxJobs; + break; + case 'k': + keepgoing = TRUE; + Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); + break; + case 'm': + if (argvalue == NULL) goto noarg; + /* look for magic parent directory search string */ + if (strncmp(".../", argvalue, 4) == 0) { + if (!Dir_FindHereOrAbove(curdir, argvalue+4, + found_path, sizeof(found_path))) + break; /* nothing doing */ + (void)Dir_AddDir(sysIncPath, found_path); + } else { + (void)Dir_AddDir(sysIncPath, argvalue); + } + Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); + Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); + break; + case 'n': + noExecute = TRUE; + Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); + break; + case 'q': + queryFlag = TRUE; + /* Kind of nonsensical, wot? */ + Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); + break; + case 'r': + noBuiltins = TRUE; + Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); + break; + case 's': + beSilent = TRUE; + Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); + break; + case 't': + touchFlag = TRUE; + Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); + break; + case 'w': + enterFlag = TRUE; + Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL); + break; + case '-': + dashDash = TRUE; + break; + default: + case '?': +#ifndef MAKE_NATIVE + fprintf(stderr, "getopt(%s) -> %d (%c)\n", + OPTFLAGS, c, c); +#endif + usage(); + } + 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) + if (Parse_IsVar(argv[1])) { + Parse_DoVar(argv[1], VAR_CMD); + } else { + if (!*argv[1]) + Punt("illegal (null) argument."); + if (*argv[1] == '-' && !dashDash) + goto rearg; + Lst_Append(create, bmake_strdup(argv[1])); + } + + return; +noarg: + (void)fprintf(stderr, "%s: option requires an argument -- %c\n", + progname, c); + usage(); +} + +/*- + * Main_ParseArgLine -- + * Used by the parse module when a .MFLAGS or .MAKEFLAGS target + * is encountered and by main() when reading the .MAKEFLAGS envariable. + * Takes a line of arguments and breaks it into its + * component words and passes those words and the number of them to the + * MainParseArgs function. + * The line should have all its leading whitespace removed. + * + * Input: + * line Line to fracture + * + * Results: + * None + * + * Side Effects: + * Only those that come from the various arguments. + */ +void +Main_ParseArgLine(const char *line) +{ + Words words; + char *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 (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 (enterFlag && strcmp(objdir, curdir) != 0) + enterFlagObj = TRUE; + } + } + + return rc; +} + +static Boolean +Main_SetVarObjdir(const char *var, const char *suffix) +{ + char *path_freeIt; + const char *path = Var_Value(var, VAR_CMD, &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) + xpath = xpath_freeIt = Var_Subst(path, VAR_GLOBAL, + VARE_WANTRES); + + (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, for Lst_Find. */ +static Boolean +ReadMakefileSucceeded(const void *fname, const void *unused) +{ + return ReadMakefile(fname) == 0; +} + +/* Read and parse the makefile. + * Return TRUE if reading the makefile failed, for Lst_Find. */ +static Boolean +ReadMakefileFailed(const void *fname, const void *unused) +{ + return ReadMakefile(fname) != 0; +} + +int +str2Lst_Append(Lst lp, char *str, const char *sep) +{ + char *cp; + int n; + + if (!sep) + sep = " \t"; + + for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) { + 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) + mode = mode_freeIt = Var_Subst("${" MAKE_MODE ":tl}", + VAR_GLOBAL, VARE_WANTRES); + + if (mode[0] != '\0') { + if (strstr(mode, "compat")) { + compatMake = TRUE; + forceJobs = FALSE; + } +#if USE_META + if (strstr(mode, "meta")) + meta_mode_init(mode); +#endif + } + + free(mode_freeIt); +} + +static void +doPrintVars(void) +{ + LstNode ln; + Boolean expandVars; + + if (printVars == EXPAND_VARS) + expandVars = TRUE; + else if (debugVflag) + expandVars = FALSE; + else + expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE); + + for (ln = Lst_First(variables); ln != NULL; ln = LstNode_Next(ln)) { + char *var = LstNode_Datum(ln); + const char *value; + char *p1; + + if (strchr(var, '$')) { + value = p1 = Var_Subst(var, VAR_GLOBAL, VARE_WANTRES); + } else if (expandVars) { + char tmp[128]; + int len = snprintf(tmp, sizeof(tmp), "${%s}", var); + + if (len >= (int)sizeof(tmp)) + Fatal("%s: variable name too big: %s", + progname, var); + value = p1 = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES); + } else { + value = Var_Value(var, VAR_GLOBAL, &p1); + } + printf("%s\n", value ? value : ""); + bmake_free(p1); + } +} + +static Boolean +runTargets(void) +{ + Lst 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(create)) + targs = Parse_MainName(); + else + targs = Targ_FindList(create, TARG_CREATE); + + if (!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 (!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; +} + +/*- + * 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 sb, sa; + char *p1, *path; + char mdpath[MAXPATHLEN]; +#ifdef FORCE_MACHINE + const char *machine = FORCE_MACHINE; +#else + const char *machine = getenv("MACHINE"); +#endif + const char *machine_arch = getenv("MACHINE_ARCH"); + char *syspath = getenv("MAKESYSPATH"); + Lst sysMkPath; /* Path of sys.mk */ + char *cp = NULL, *start; + /* avoid faults on read-only strings */ + static char defsyspath[] = _PATH_DEFSYSPATH; + char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ + struct timeval rightnow; /* to initialize random seed */ + struct utsname utsname; + + /* default to writing debug to stderr */ + debug_file = stderr; + +#ifdef SIGINFO + (void)bmake_signal(SIGINFO, siginfo); +#endif + /* + * Set the seed to produce a different random sequence + * on each program execution. + */ + gettimeofday(&rightnow, NULL); + srandom(rightnow.tv_sec + rightnow.tv_usec); + + if ((progname = strrchr(argv[0], '/')) != NULL) + progname++; + else + progname = argv[0]; +#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) + /* + * get rid of resource limit on file descriptors + */ + { + 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 + + 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. + */ + if (!machine) { +#ifdef MAKE_NATIVE + machine = utsname.machine; +#else +#ifdef MAKE_MACHINE + machine = MAKE_MACHINE; +#else + machine = "unknown"; +#endif +#endif + } + + if (!machine_arch) { +#if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL) && defined(CTL_HW) && defined(HW_MACHINE_ARCH) + static char machine_arch_buf[sizeof(utsname.machine)]; + 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); + } + + machine_arch = machine_arch_buf; +#else +#ifndef MACHINE_ARCH +#ifdef MAKE_MACHINE_ARCH + machine_arch = MAKE_MACHINE_ARCH; +#else + machine_arch = "unknown"; +#endif +#else + machine_arch = MACHINE_ARCH; +#endif +#endif + } + + 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); + + create = Lst_Init(); + makefiles = Lst_Init(); + printVars = 0; + debugVflag = FALSE; + variables = Lst_Init(); + beSilent = FALSE; /* Print commands as executed */ + ignoreErrors = FALSE; /* Pay attention to non-zero returns */ + noExecute = FALSE; /* Execute all commands */ + noRecursiveExecute = FALSE; /* Execute all .MAKE targets */ + keepgoing = FALSE; /* Stop on error */ + allPrecious = FALSE; /* Remove targets when interrupted */ + deleteOnError = FALSE; /* Historical default behavior */ + queryFlag = FALSE; /* This is not just a check-run */ + noBuiltins = FALSE; /* Read the built-in rules */ + touchFlag = FALSE; /* Actually update targets */ + debug = 0; /* No debug verbosity, please. */ + jobsRunning = FALSE; + + maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */ + maxJobTokens = maxJobs; + compatMake = FALSE; /* No compat mode */ + 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(); + if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) { + /* + * Leave alone if it is an absolute path, or if it does + * not contain a '/' in which case we need to find it in + * the path, like execvp(3) and the shells do. + */ + p1 = argv[0]; + } else { + /* + * A relative path, canonicalize it. + */ + p1 = cached_realpath(argv[0], mdpath); + if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) { + p1 = argv[0]; /* realpath failed */ + } + } + Var_Set("MAKE", p1, VAR_GLOBAL); + Var_Set(".MAKE", p1, VAR_GLOBAL); + 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_CMD); + + /* + * 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 + 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 (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); + } + + /* + * 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 transform. + */ +#ifndef NO_PWD_OVERRIDE + if (!ignorePWD) { + char *pwd, *ptmp1 = NULL, *ptmp2 = NULL; + + if ((pwd = getenv("PWD")) != NULL && + Var_Value("MAKEOBJDIRPREFIX", VAR_CMD, &ptmp1) == NULL) { + const char *makeobjdir = Var_Value("MAKEOBJDIR", + VAR_CMD, &ptmp2); + + if (makeobjdir == NULL || !strchr(makeobjdir, '$')) { + if (stat(pwd, &sb) == 0 && + sa.st_ino == sb.st_ino && + sa.st_dev == sb.st_dev) + (void)strncpy(curdir, pwd, MAXPATHLEN); + } + } + bmake_free(ptmp1); + bmake_free(ptmp2); + } +#endif + Var_Set(".CURDIR", curdir, VAR_GLOBAL); + + /* + * 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. + */ + 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); + + /* + * 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); + + /* + * 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. + */ + if (!Lst_IsEmpty(create)) { + LstNode ln; + + for (ln = Lst_First(create); ln != NULL; ln = LstNode_Next(ln)) { + char *name = LstNode_Datum(ln); + Var_Append(".TARGETS", name, VAR_GLOBAL); + } + } else + Var_Set(".TARGETS", "", VAR_GLOBAL); + + + /* + * 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(defIncPath, start); + } else { + if (Dir_FindHereOrAbove(curdir, start+4, + found_path, sizeof(found_path))) { + (void)Dir_AddDir(defIncPath, found_path); + } + } + } + if (syspath != defsyspath) + free(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 (!noBuiltins) { + LstNode ln; + + sysMkPath = Lst_Init(); + Dir_Expand(_PATH_DEFSYSMK, + Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath, + sysMkPath); + if (Lst_IsEmpty(sysMkPath)) + Fatal("%s: no system rules (%s).", progname, + _PATH_DEFSYSMK); + ln = Lst_Find(sysMkPath, ReadMakefileSucceeded, NULL); + if (ln == NULL) + Fatal("%s: cannot open %s.", progname, + (char *)LstNode_Datum(Lst_First(sysMkPath))); + } + + if (!Lst_IsEmpty(makefiles)) { + LstNode ln; + + ln = Lst_Find(makefiles, ReadMakefileFailed, NULL); + if (ln != NULL) + Fatal("%s: cannot open %s.", progname, + (char *)LstNode_Datum(ln)); + } else { + p1 = Var_Subst("${" MAKEFILE_PREFERENCE "}", + VAR_CMD, VARE_WANTRES); + (void)str2Lst_Append(makefiles, p1, NULL); + (void)Lst_Find(makefiles, ReadMakefileSucceeded, NULL); + free(p1); + } + + /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ + if (!noBuiltins || !printVars) { + makeDependfile = Var_Subst("${.MAKE.DEPENDFILE:T}", + VAR_CMD, VARE_WANTRES); + doing_depend = TRUE; + (void)ReadMakefile(makeDependfile); + doing_depend = FALSE; + } + + if (enterFlagObj) + printf("%s: Entering directory `%s'\n", progname, objdir); + + MakeMode(NULL); + + Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); + bmake_free(p1); + + if (!forceJobs && !compatMake && + Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) { + char *value; + int n; + + value = Var_Subst("${.MAKE.JOBS}", VAR_GLOBAL, VARE_WANTRES); + n = 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 != maxJobs) { + Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); + Var_Append(MAKEFLAGS, value, VAR_GLOBAL); + } + maxJobs = n; + maxJobTokens = maxJobs; + forceJobs = TRUE; + free(value); + } + + /* + * Be compatible if user did not specify -j and did not explicitly + * turned compatibility on + */ + if (!compatMake && !forceJobs) { + compatMake = TRUE; + } + + if (!compatMake) + Job_ServerStart(maxJobTokens, jp_0, jp_1); + if (DEBUG(JOB)) + fprintf(debug_file, + "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", + jp_0, jp_1, maxJobs, maxJobTokens, compatMake ? 1 : 0); + + if (!printVars) + Main_ExportMAKEFLAGS(TRUE); /* initial export */ + + + /* + * 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 envariable, i.e. + * ::... + */ + if (Var_Exists("VPATH", VAR_CMD)) { + char *vpath, savec; + /* + * GCC stores string constants in read-only memory, but + * Var_Subst will want to write this thing, so store it + * in an array + */ + static char VPATH[] = "${VPATH}"; + + vpath = Var_Subst(VPATH, VAR_CMD, VARE_WANTRES); + path = vpath; + do { + /* 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); + } + + /* + * 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 (printVars) { + doPrintVars(); + outOfDate = FALSE; + } else { + outOfDate = runTargets(); + } + +#ifdef CLEANUP + Lst_Free(variables); + Lst_Free(makefiles); + Lst_Destroy(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 (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(); + + 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) + name = Dir_FindFile(fname, + Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); + 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_Size(&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(""); +} + +/*- + * Error -- + * Print an error message given its format. + * + * Results: + * None. + * + * Side Effects: + * The message is printed. + */ +/* VARARGS */ +void +Error(const char *fmt, ...) +{ + va_list ap; + FILE *err_file; + + err_file = 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; + } +} + +/*- + * Fatal -- + * Produce a Fatal error message. If jobs are running, waits for them + * to finish. + * + * Results: + * None + * + * Side Effects: + * The program exits + */ +/* VARARGS */ +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 */ +} + +/* + * Punt -- + * Major exception once jobs are being created. Kills all jobs, prints + * a message and exits. + * + * Results: + * None + * + * Side Effects: + * All children are killed indiscriminately and the program Lib_Exits + */ +/* VARARGS */ +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(); +} + +/*- + * DieHorribly -- + * Exit without giving a message. + * + * Results: + * None + * + * Side Effects: + * A big one... + */ +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 */ +} + +/* + * Finish -- + * Called when aborting due to errors in child shell to signal + * abnormal exit. + * + * Results: + * None + * + * Side Effects: + * The program exits + */ +void +Finish(int errors) + /* number of errors encountered in Make_Make */ +{ + if (dieQuietly(NULL, -1)) + exit(2); + Fatal("%d error%s", errors, errors == 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); +} + +/* + * execError -- + * Print why exec failed, avoiding stdio. + */ +void +execError(const char *af, const char *av) +{ +#ifdef USE_IOVEC + int i = 0; + struct iovec iov[8]; +#define IOADD(s) \ + (void)(iov[i].iov_base = UNCONST(s), \ + iov[i].iov_len = strlen(iov[i].iov_base), \ + i++) +#else +#define IOADD(s) (void)write(2, s, strlen(s)) +#endif + + IOADD(progname); + IOADD(": "); + IOADD(af); + IOADD("("); + IOADD(av); + IOADD(") failed ("); + IOADD(strerror(errno)); + IOADD(")\n"); + +#ifdef USE_IOVEC + while (writev(2, iov, 8) == -1 && errno == EAGAIN) + continue; +#endif +} + +/* + * 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(); + Hash_Entry *he, *nhe; + Hash_Search hs; + + he = Hash_EnumFirst(&cache->context, &hs); + while (he) { + nhe = Hash_EnumNext(&hs); + if (he->name[0] != '/') { + if (DEBUG(DIR)) + fprintf(stderr, "cached_realpath: purging %s\n", he->name); + Hash_DeleteEntry(&cache->context, he); + } + he = nhe; + } +} + +char * +cached_realpath(const char *pathname, char *resolved) +{ + GNode *cache; + const char *rp; + char *cp; + + if (!pathname || !pathname[0]) + return NULL; + + cache = get_cached_realpaths(); + + if ((rp = Var_Value(pathname, cache, &cp)) != 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(cp); + return rp ? resolved : NULL; +} + +int +PrintAddr(void *a, void *b) +{ + printf("%lx ", (unsigned long) a); + return b ? 0 : 0; +} + + +static int +addErrorCMD(void *cmdp, void *gnp MAKE_ATTR_UNUSED) +{ + if (cmdp == NULL) + return 1; /* stop */ + Var_Append(".ERROR_CMD", cmdp, VAR_GLOBAL); + return 0; +} + +/* + * 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", 1) == 0) + quietly = 0; + else if (bf >= 0) + quietly = bf; + else + quietly = (gn) ? ((gn->type & (OP_MAKE)) != 0) : 0; + } + return quietly; +} + +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) { + /* + * 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); + Lst_ForEach(gn->commands, addErrorCMD, gn); + } + expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}"; + cp = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); + printf("%s", cp); + free(cp); + fflush(stdout); + + /* + * Finally, see if there is a .ERROR target, and run it if so. + */ + en = Targ_FindNode(".ERROR", TARG_NOCREATE); + if (en) { + en->type |= OP_SPECIAL; + Compat_Make(en, en); + } +} + +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}@}"; + s = Var_Subst(expr, VAR_CMD, VARE_WANTRES); + 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 /. + */ + tmpdir = Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, + VARE_WANTRES); + 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 "fnamep" is provided set it to a copy of the filename created. + * Otherwise unlink the file once open. + */ +int +mkTempFile(const char *pattern, char **fnamep) +{ + static char *tmpdir = NULL; + char tfile[MAXPATHLEN]; + int fd; + + if (!pattern) + pattern = TMPPAT; + if (!tmpdir) + 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 (fnamep) { + *fnamep = 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) +{ + if (s) { + switch(*s) { + case '\0': /* not set - the default wins */ + break; + case '0': + case 'F': + case 'f': + case 'N': + case 'n': + bf = FALSE; + break; + case 'O': + case 'o': + switch (s[1]) { + case 'F': + case 'f': + bf = FALSE; + break; + default: + bf = TRUE; + break; + } + break; + default: + bf = TRUE; + break; + } + } + return bf; +} + +/* + * Return a Boolean based on setting of a knob. + * + * If the knob is not set, the supplied default is the return value. + * If set, anything that looks or smells like "No", "False", "Off", "0" etc, + * is FALSE, otherwise TRUE. + */ +Boolean +getBoolean(const char *name, Boolean fallback) +{ + char *expr = str_concat3("${", name, ":U:tl}"); + char *value = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); + Boolean res = s2Boolean(value, fallback); + free(value); + free(expr); + return res; +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/make-conf.h =================================================================== --- vendor/NetBSD/bmake/20200902/make-conf.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/make-conf.h (revision 365363) @@ -0,0 +1,164 @@ +/* $NetBSD: config.h,v 1.22 2020/09/01 17:40:34 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 suff.c 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"] + * SYSVVARSUB + * Recognize system V like ${VAR:x=y} variable substitutions + */ +#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 + +/* + * USE_IOVEC + * We have writev(2) + */ +#ifdef HAVE_SYS_UIO_H +# define USE_IOVEC +#endif + +#if defined(MAKE_NATIVE) && !defined(__ELF__) +# ifndef RANLIBMAG +# define RANLIBMAG "__.SYMDEF" +# endif +#endif Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/make.1 =================================================================== --- vendor/NetBSD/bmake/20200902/make.1 (nonexistent) +++ vendor/NetBSD/bmake/20200902/make.1 (revision 365363) @@ -0,0 +1,2450 @@ +.\" $NetBSD: make.1,v 1.289 2020/08/28 17:15:04 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 August 28, 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 integral +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 an integral 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/20200902/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/20200902/make.c =================================================================== --- vendor/NetBSD/bmake/20200902/make.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/make.c (revision 365363) @@ -0,0 +1,1561 @@ +/* $NetBSD: make.c,v 1.133 2020/08/30 14:11:42 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93"; +#else +__RCSID("$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 cmgn 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 cmgn 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 "enum.h" +#include "dir.h" +#include "job.h" + +static unsigned int checked = 1;/* Sequence # to detect recursion */ +static Lst toBeMade; /* 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 int MakeAddChild(void *, void *); +static int MakeFindChild(void *, void *); +static int MakeUnmark(void *, void *); +static int MakeAddAllSrc(void *, void *); +static int MakeTimeStamp(void *, void *); +static int MakeHandleUse(void *, void *); +static Boolean MakeStartJobs(void); +static int MakePrintStatus(void *, void *); +static int MakeCheckOrder(void *, void *); +static int MakeBuildChild(void *, void *); +static int MakeBuildParent(void *, void *); + +MAKE_ATTR_DEAD static void +make_abort(GNode *gn, int line) +{ + static int two = 2; + + fprintf(debug_file, "make_abort from line %d\n", line); + Targ_PrintNode(gn, &two); + Lst_ForEach(toBeMade, Targ_PrintNode, &two); + 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); +} + +/*- + *----------------------------------------------------------------------- + * Make_TimeStamp -- + * Set the cmgn field of a parent node based on the mtime stamp in its + * child. Called from MakeOODate via Lst_ForEach. + * + * Input: + * pgn the current parent + * cgn the child we've just examined + * + * Results: + * Always returns 0. + * + * Side Effects: + * The cmgn of the parent node will be changed if the mtime + * field of the child is greater than it. + *----------------------------------------------------------------------- + */ +int +Make_TimeStamp(GNode *pgn, GNode *cgn) +{ + if (pgn->cmgn == NULL || cgn->mtime > pgn->cmgn->mtime) { + pgn->cmgn = cgn; + } + return 0; +} + +/* + * Input: + * pgn the current parent + * cgn the child we've just examined + * + */ +static int +MakeTimeStamp(void *pgn, void *cgn) +{ + return Make_TimeStamp((GNode *)pgn, (GNode *)cgn); +} + +/*- + *----------------------------------------------------------------------- + * Make_OODate -- + * See if a given 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. + * + * Input: + * gn the node to check + * + * Results: + * TRUE if the node is out of date. FALSE otherwise. + * + * Side Effects: + * The mtime field of the node and the cmgn field of its parents + * will/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) { + fprintf(debug_file, "modified %s...", Targ_FmtTime(gn->mtime)); + } else { + fprintf(debug_file, "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 type OP_NOP) + * 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*. + */ + if (DEBUG(MAKE)) { + fprintf(debug_file, ".USE node..."); + } + oodate = FALSE; + } else if ((gn->type & OP_LIB) && + ((gn->mtime==0) || Arch_IsLib(gn))) { + if (DEBUG(MAKE)) { + fprintf(debug_file, "library..."); + } + + /* + * always out of date if no children and :: target + * or non-existent. + */ + oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || + (gn->cmgn == 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. + */ + if (DEBUG(MAKE)) { + fprintf(debug_file, ".JOIN node..."); + } + if (DEBUG(MAKE)) { + fprintf(debug_file, "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) { + fprintf(debug_file, "! operator..."); + } else if (gn->type & OP_PHONY) { + fprintf(debug_file, ".PHONY node..."); + } else { + fprintf(debug_file, ".EXEC node..."); + } + } + oodate = TRUE; + } else if ((gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime) || + (gn->cmgn == 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 (cmgn == 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->cmgn != NULL && gn->mtime < gn->cmgn->mtime) { + fprintf(debug_file, "modified before source %s...", + gn->cmgn->path ? gn->cmgn->path : gn->cmgn->name); + } else if (gn->mtime == 0) { + fprintf(debug_file, "non-existent and no sources..."); + } else { + fprintf(debug_file, ":: 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) + fprintf(debug_file, "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 aren't of type OP_NOP, + * have their mtime stay below their children's mtime to keep parents from + * thinking they're out-of-date. + */ + if (!oodate) { + Lst_ForEach(gn->parents, MakeTimeStamp, gn); + } + + return oodate; +} + +/*- + *----------------------------------------------------------------------- + * MakeAddChild -- + * Function used by Make_Run to add a child to the list l. + * It will only add the child if its make field is FALSE. + * + * Input: + * gnp the node to add + * lp the list to which to add it + * + * Results: + * Always returns 0 + * + * Side Effects: + * The given list is extended + *----------------------------------------------------------------------- + */ +static int +MakeAddChild(void *gnp, void *lp) +{ + GNode *gn = (GNode *)gnp; + Lst l = (Lst) lp; + + if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) { + if (DEBUG(MAKE)) + fprintf(debug_file, "MakeAddChild: need to examine %s%s\n", + gn->name, gn->cohort_num); + Lst_Enqueue(l, gn); + } + return 0; +} + +/*- + *----------------------------------------------------------------------- + * MakeFindChild -- + * Function used by Make_Run to find the pathname of a child + * that was already made. + * + * Input: + * gnp the node to find + * + * Results: + * Always returns 0 + * + * Side Effects: + * The path and mtime of the node and the cmgn of the parent are + * updated; the unmade children count of the parent is decremented. + *----------------------------------------------------------------------- + */ +static int +MakeFindChild(void *gnp, void *pgnp) +{ + GNode *gn = (GNode *)gnp; + GNode *pgn = (GNode *)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 .USE node + * pgn The target of the .USE node + */ +void +Make_HandleUse(GNode *cgn, GNode *pgn) +{ + LstNode ln; /* An element in the children list */ + +#ifdef DEBUG_SRC + if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) { + fprintf(debug_file, "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); + } + } + + Lst_Open(cgn->children); + while ((ln = Lst_Next(cgn->children)) != NULL) { + GNode *gn = LstNode_Datum(ln); + + /* + * 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); + } + gn->name = Var_Subst(gn->uname, pgn, VARE_WANTRES); + if (gn->uname && strcmp(gn->name, gn->uname) != 0) { + /* See if we have a target for this node. */ + GNode *tgn = Targ_FindNode(gn->name, TARG_NOCREATE); + if (tgn != NULL) + gn = tgn; + } + + Lst_Append(pgn->children, gn); + Lst_Append(gn->parents, pgn); + pgn->unmade += 1; + } + Lst_Close(cgn->children); + + pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM); +} + +/*- + *----------------------------------------------------------------------- + * MakeHandleUse -- + * Callback function for Lst_ForEach, 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. + * This function calls Make_HandleUse to copy the .USE node's commands, + * type flags and children to the parent node. + * + * Input: + * cgnp the child we've just examined + * pgnp the current parent + * + * Results: + * returns 0. + * + * Side Effects: + * After expansion, .USE child nodes are removed from the parent + * + *----------------------------------------------------------------------- + */ +static int +MakeHandleUse(void *cgnp, void *pgnp) +{ + GNode *cgn = (GNode *)cgnp; + GNode *pgn = (GNode *)pgnp; + LstNode ln; /* An element in the children list */ + int unmarked; + + unmarked = ((cgn->type & OP_MARK) == 0); + cgn->type |= OP_MARK; + + if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0) + return 0; + + 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... + */ + if ((ln = Lst_FindDatum(pgn->children, cgn)) != NULL) { + Lst_Remove(pgn->children, ln); + pgn->unmade--; + } + return 0; +} + + +/*- + *----------------------------------------------------------------------- + * Make_Recheck -- + * Check the modification time of a gnode, and update it as described + * in the comments below. + * + * Results: + * returns 0 if the gnode does not exist, or its filesystem + * time if it does. + * + * Side Effects: + * the gnode's modification time and path name are affected. + * + *----------------------------------------------------------------------- + */ +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 (NoExecute(gn) || (gn->type & OP_SAVE_CMDS) || + (mtime == 0 && !(gn->type & OP_WAIT))) { + if (DEBUG(MAKE)) { + fprintf(debug_file, " recheck(%s): update time from %s to now\n", + gn->name, Targ_FmtTime(gn->mtime)); + } + gn->mtime = now; + } + else { + if (DEBUG(MAKE)) { + fprintf(debug_file, " recheck(%s): current update time: %s\n", + gn->name, Targ_FmtTime(gn->mtime)); + } + } +#endif + return mtime; +} + +/*- + *----------------------------------------------------------------------- + * Make_Update -- + * 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. + * + * Input: + * cgn the child node + * + * Results: + * Always returns 0 + * + * Side Effects: + * 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 cmgn 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) +{ + GNode *pgn; /* the parent node */ + const char *cname; /* the child's name */ + LstNode ln; /* Element in parents and implicitParents lists */ + time_t mtime = -1; + char *p1; + Lst parents; + GNode *centurion; + + /* It is save to re-examine any nodes again */ + checked++; + + cname = Var_Value(TARGET, cgn, &p1); + bmake_free(p1); + + if (DEBUG(MAKE)) + fprintf(debug_file, "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 -= 1; + 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_ForEach(centurion->order_succ, MakeBuildParent, Lst_First(toBeMade)); + + /* Now mark all the parents as having one less unmade child */ + Lst_Open(parents); + while ((ln = Lst_Next(parents)) != NULL) { + pgn = LstNode_Datum(ln); + if (DEBUG(MAKE)) + fprintf(debug_file, "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 */ + if (DEBUG(MAKE)) + fprintf(debug_file, "- 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 unmake + * 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) { + if (DEBUG(MAKE)) + fprintf(debug_file, "- .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) { + if (DEBUG(MAKE)) + fprintf(debug_file, + "- centurion made %d, %d unmade cohorts\n", + centurion->made, centurion->unmade_cohorts); + continue; + } + + /* One more child of this parent is now made */ + pgn->unmade -= 1; + if (pgn->unmade < 0) { + if (DEBUG(MAKE)) { + fprintf(debug_file, "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)) { + if (DEBUG(MAKE)) + fprintf(debug_file, "- 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. + */ + if (DEBUG(MAKE)) + fprintf(debug_file, "- not deferred\n"); + continue; + } + assert(pgn->order_pred != NULL); + if (Lst_ForEach(pgn->order_pred, MakeCheckOrder, 0)) { + /* A .ORDER rule stops us building this */ + continue; + } + if (DEBUG(MAKE)) { + static int two = 2; + fprintf(debug_file, "- %s%s made, schedule %s%s (made %d)\n", + cgn->name, cgn->cohort_num, + pgn->name, pgn->cohort_num, pgn->made); + Targ_PrintNode(pgn, &two); + } + /* Ok, we can schedule the parent again */ + pgn->made = REQUESTED; + Lst_Enqueue(toBeMade, pgn); + } + Lst_Close(parents); + + /* + * Set the .PREFIX and .IMPSRC variables for all the implied parents + * of this node. + */ + Lst_Open(cgn->implicitParents); + { + const char *cpref = Var_Value(PREFIX, cgn, &p1); + + while ((ln = Lst_Next(cgn->implicitParents)) != NULL) { + pgn = LstNode_Datum(ln); + if (pgn->flags & REMAKE) { + Var_Set(IMPSRC, cname, pgn); + if (cpref != NULL) + Var_Set(PREFIX, cpref, pgn); + } + } + bmake_free(p1); + Lst_Close(cgn->implicitParents); + } +} + +/*- + *----------------------------------------------------------------------- + * MakeAddAllSrc -- + * Add a child's name to the ALLSRC and OODATE variables of the given + * node. Called from Make_DoAllVar via Lst_ForEach. A child is added 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...).. + * + * Results: + * Always returns 0 + * + * Side Effects: + * The ALLSRC variable for the given node is extended. + *----------------------------------------------------------------------- + */ +static int +MakeUnmark(void *cgnp, void *pgnp MAKE_ATTR_UNUSED) +{ + GNode *cgn = (GNode *)cgnp; + + cgn->type &= ~OP_MARK; + return 0; +} + +/* + * Input: + * cgnp The child to add + * pgnp The parent to whose ALLSRC variable it should + * be added + * + */ +static int +MakeAddAllSrc(void *cgnp, void *pgnp) +{ + GNode *cgn = (GNode *)cgnp; + GNode *pgn = (GNode *)pgnp; + + if (cgn->type & OP_MARK) + return 0; + cgn->type |= OP_MARK; + + if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) { + const char *child, *allsrc; + char *p1 = NULL, *p2 = NULL; + + if (cgn->type & OP_ARCHV) + child = Var_Value(MEMBER, cgn, &p1); + else + child = cgn->path ? cgn->path : cgn->name; + if (cgn->type & OP_JOIN) { + allsrc = Var_Value(ALLSRC, cgn, &p2); + } else { + allsrc = child; + } + if (allsrc != NULL) + Var_Append(ALLSRC, allsrc, pgn); + bmake_free(p2); + 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); + } + bmake_free(p1); + } + return 0; +} + +/*- + *----------------------------------------------------------------------- + * Make_DoAllVar -- + * 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. + * + * Results: + * None + * + * Side Effects: + * The ALLSRC and OODATE variables of the given node is filled in. + * If the node is a .JOIN node, its TARGET variable will be set to + * match its ALLSRC variable. + *----------------------------------------------------------------------- + */ +void +Make_DoAllVar(GNode *gn) +{ + if (gn->flags & DONE_ALLSRC) + return; + + Lst_ForEach(gn->children, MakeUnmark, gn); + Lst_ForEach(gn->children, MakeAddAllSrc, gn); + + if (!Var_Exists (OODATE, gn)) { + Var_Set(OODATE, "", gn); + } + if (!Var_Exists (ALLSRC, gn)) { + Var_Set(ALLSRC, "", gn); + } + + if (gn->type & OP_JOIN) { + char *p1; + Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn); + bmake_free(p1); + } + gn->flags |= DONE_ALLSRC; +} + +/*- + *----------------------------------------------------------------------- + * MakeStartJobs -- + * Start as many jobs as possible. + * + * Results: + * 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. + * + * Side Effects: + * Nodes are removed from the toBeMade queue and job table slots + * are filled. + * + *----------------------------------------------------------------------- + */ + +static int +MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED) +{ + GNode *bn = v_bn; + + if (bn->made >= MADE || !(bn->flags & REMAKE)) + return 0; + if (DEBUG(MAKE)) + fprintf(debug_file, "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; + + if (DEBUG(MAKE)) + fprintf(debug_file, "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_ForEach(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 */ + } + + if (DEBUG(MAKE)) + fprintf(debug_file, "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_ForEach(cn->cohorts, MakeBuildChild, toBeMade_next); + + /* + * If this node is a .WAIT node with unmade chlidren + * 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; +} + +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); + if (DEBUG(MAKE)) + fprintf(debug_file, "Examining %s%s...\n", + gn->name, gn->cohort_num); + + if (gn->made != REQUESTED) { + if (DEBUG(MAKE)) + fprintf(debug_file, "state %d\n", gn->made); + + make_abort(gn, __LINE__); + } + + if (gn->checked == checked) { + /* We've already looked at this node since a job finished... */ + if (DEBUG(MAKE)) + fprintf(debug_file, "already checked %s%s\n", + gn->name, gn->cohort_num); + gn->made = DEFERRED; + continue; + } + gn->checked = 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_ForEach(gn->children, MakeBuildChild, Lst_First(toBeMade)); + /* and drop this node on the floor */ + if (DEBUG(MAKE)) + fprintf(debug_file, "dropped %s%s\n", gn->name, gn->cohort_num); + continue; + } + + gn->made = BEINGMADE; + if (Make_OODate(gn)) { + if (DEBUG(MAKE)) { + fprintf(debug_file, "out-of-date\n"); + } + if (queryFlag) { + return TRUE; + } + Make_DoAllVar(gn); + Job_Make(gn); + have_token = 0; + } else { + if (DEBUG(MAKE)) { + fprintf(debug_file, "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; +} + +/*- + *----------------------------------------------------------------------- + * MakePrintStatus -- + * 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_ForEach. + * + * Input: + * gnp Node to examine + * cyclep True if gn->unmade being non-zero implies a + * cycle in the graph, not an error in an + * inferior. + * + * Results: + * Always returns 0. + * + * Side Effects: + * A message may be printed. + * + *----------------------------------------------------------------------- + */ +static int +MakePrintStatusOrder(void *ognp, void *gnp) +{ + GNode *ogn = ognp; + GNode *gn = gnp; + + if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED) + /* not waiting for this one */ + return 0; + + 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) && debug_file != stdout) { + fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s ", + gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); + GNode_FprintDetails(debug_file, "(", ogn, ")\n"); + } + return 0; +} + +static int +MakePrintStatus(void *gnp, void *v_errors) +{ + GNode *gn = (GNode *)gnp; + int *errors = v_errors; + + if (gn->flags & DONECYCLE) + /* We've completely processed this node before, don't do it again. */ + return 0; + + 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) && debug_file != stdout) { + fprintf(debug_file, "`%s%s' was not built", + gn->name, gn->cohort_num); + GNode_FprintDetails(debug_file, " (", gn, ")!\n"); + } + /* Most likely problem is actually caused by .ORDER */ + Lst_ForEach(gn->order_pred, MakePrintStatusOrder, gn); + break; + default: + /* Errors - already counted */ + printf("`%s%s' not remade because of errors.\n", + gn->name, gn->cohort_num); + if (DEBUG(MAKE) && debug_file != stdout) + fprintf(debug_file, "`%s%s' not remade because of errors.\n", + gn->name, gn->cohort_num); + break; + } + return 0; + } + + if (DEBUG(MAKE)) + fprintf(debug_file, "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; + Lst_ForEach(gn->children, MakePrintStatus, errors); + /* Mark that this node needn't be processed again */ + gn->flags |= DONECYCLE; + return 0; + } + + /* 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 1; + + /* Reporting for our children will give the rest of the loop */ + Lst_ForEach(gn->children, MakePrintStatus, errors); + return 0; +} + + +/*- + *----------------------------------------------------------------------- + * Make_ExpandUse -- + * Expand .USE nodes and create a new targets list + * + * Input: + * targs the initial list of targets + * + * Side Effects: + *----------------------------------------------------------------------- + */ +void +Make_ExpandUse(Lst targs) +{ + GNode *gn; /* a temporary pointer */ + Lst examine; /* List of targets to examine */ + + examine = Lst_Copy(targs, NULL); + + /* + * 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)) { + gn = Lst_Dequeue(examine); + + if (gn->flags & REMAKE) + /* We've looked at this one already */ + continue; + gn->flags |= REMAKE; + if (DEBUG(MAKE)) + fprintf(debug_file, "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, gn->path ? gn->path : gn->name, gn); + Lst_ForEach(gn->children, MakeUnmark, gn); + Lst_ForEach(gn->children, MakeHandleUse, gn); + + if ((gn->type & OP_MADE) == 0) + Suff_FindDeps(gn); + else { + /* Pretend we made all this node's children */ + Lst_ForEach(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_ForEach(gn->children, MakeAddChild, examine); + } + + Lst_Free(examine); +} + +/*- + *----------------------------------------------------------------------- + * Make_ProcessWait -- + * Convert .WAIT nodes into dependencies + * + * Input: + * targs the initial list of targets + * + *----------------------------------------------------------------------- + */ + +static int +link_parent(void *cnp, void *pnp) +{ + GNode *cn = cnp; + GNode *pn = pnp; + + Lst_Append(pn->children, cn); + Lst_Append(cn->parents, pn); + pn->unmade++; + return 0; +} + +static int +add_wait_dep(void *v_cn, void *v_wn) +{ + GNode *cn = v_cn; + GNode *wn = v_wn; + + if (cn == wn) + return 1; + + if (cn == NULL || wn == NULL) { + printf("bad wait dep %p %p\n", cn, wn); + exit(4); + } + if (DEBUG(MAKE)) + fprintf(debug_file, ".WAIT: add dependency %s%s -> %s\n", + cn->name, cn->cohort_num, wn->name); + + Lst_Append(wn->children, cn); + wn->unmade++; + Lst_Append(cn->parents, wn); + return 0; +} + +static void +Make_ProcessWait(Lst targs) +{ + GNode *pgn; /* 'parent' node we are examining */ + GNode *cgn; /* Each child in turn */ + LstNode owln; /* Previous .WAIT node */ + Lst examine; /* List of targets to examine */ + LstNode ln; + + /* + * 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); + + Lst_ForEach(targs, link_parent, pgn); + + /* Start building with the 'dummy' .MAIN' node */ + MakeBuildChild(pgn, NULL); + + examine = Lst_Init(); + Lst_Append(examine, pgn); + + while (!Lst_IsEmpty(examine)) { + pgn = Lst_Dequeue(examine); + + /* We only want to process each child-list once */ + if (pgn->flags & DONE_WAIT) + continue; + pgn->flags |= DONE_WAIT; + if (DEBUG(MAKE)) + fprintf(debug_file, "Make_ProcessWait: examine %s\n", pgn->name); + + if (pgn->type & OP_DOUBLEDEP) + Lst_PrependAll(examine, pgn->cohorts); + + owln = Lst_First(pgn->children); + Lst_Open(pgn->children); + for (; (ln = Lst_Next(pgn->children)) != NULL; ) { + cgn = LstNode_Datum(ln); + if (cgn->type & OP_WAIT) { + /* Make the .WAIT node depend on the previous children */ + Lst_ForEachFrom(pgn->children, owln, add_wait_dep, cgn); + owln = ln; + } else { + Lst_Append(examine, cgn); + } + } + Lst_Close(pgn->children); + } + + 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(Lst targs) +{ + int errors; /* Number of errors the Job module reports */ + + /* Start trying to make the current targets... */ + toBeMade = Lst_Init(); + + Make_ExpandUse(targs); + Make_ProcessWait(targs); + + if (DEBUG(MAKE)) { + fprintf(debug_file, "#***# full graph\n"); + Targ_PrintGraph(1); + } + + if (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. + */ + if (DEBUG(MAKE)) + fprintf(debug_file, "done: errors %d\n", errors); + if (errors == 0) { + Lst_ForEach(targs, MakePrintStatus, &errors); + if (DEBUG(MAKE)) { + fprintf(debug_file, "done: errors %d\n", errors); + if (errors) + Targ_PrintGraph(4); + } + } + return errors != 0; +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/make.h =================================================================== --- vendor/NetBSD/bmake/20200902/make.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/make.h (revision 365363) @@ -0,0 +1,595 @@ +/* $NetBSD: make.h,v 1.137 2020/09/02 23:42:58 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 +#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; +#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_ENUM_BOOLEAN) +typedef enum { FALSE, TRUE} Boolean; +#else +typedef int Boolean; +#endif +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ + +#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. + * + * These constants are bitwise-OR'ed together and placed in the 'type' field + * of each node. Any node that has a 'type' field which satisfies the OP_NOP + * function was never never on the left-hand side of an operator, though it + * may have been on the right-hand side... */ +typedef enum { + /* Execution of commands depends on children (:) */ + OP_DEPENDS = 1 << 0, + /* Always execute commands (!) */ + OP_FORCE = 1 << 1, + /* Execution of commands depends on children per line (::) */ + OP_DOUBLEDEP = 1 << 2, + + 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 errors 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 */ + OP_MEMBER = 1 << 30, + /* Target is a library */ + OP_LIB = 1 << 29, + /* Target is an archive construct */ + OP_ARCHV = 1 << 28, + /* Target has all the commands it should. Used when parsing to catch + * multiple commands for a target. */ + OP_HAS_COMMANDS = 1 << 27, + /* Saving commands on .END (Compat) */ + OP_SAVE_CMDS = 1 << 26, + /* Already processed by Suff_FindDeps */ + OP_DEPS_FOUND = 1 << 25, + /* Node found while expanding .ALLSRC */ + OP_MARK = 1 << 24 +} GNodeType; + +typedef enum { + 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; + +/* 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; + /* whether it is involved in this invocation of make */ + GNodeFlags flags; + + /* The state of processing on this node */ + GNodeMade made; + int unmade; /* The number of unmade children */ + + time_t mtime; /* Its modification time */ + struct GNode *cmgn; /* The youngest child */ + + /* 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. */ + Lst implicitParents; + + /* Other nodes of the same name for the :: operator. */ + Lst cohorts; + + /* The nodes that depend on this one, or in other words, the nodes for + * which this is a source. */ + Lst parents; + /* The nodes on which this one depends. */ + Lst 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. */ + Lst 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. */ + Lst order_succ; + + /* #n for this cohort */ + 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; + + /* The "local" variables that are specific to this target and this target + * only, such as $@, $<, $?. */ + Hash_Table context; + + /* The commands to be given to a shell to create this target. */ + Lst 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; + +#define NoExecute(gn) ((gn->type & OP_MAKE) ? noRecursiveExecute : noExecute) +/* + * OP_NOP will return TRUE if the node with the given type was not the + * object of a dependency operator + */ +#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000) + +#define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM) + +/* + * The TARG_ constants are used when calling the Targ_FindNode and + * Targ_FindList functions in targ.c. They simply tell the functions what to + * do if the desired node(s) is (are) not found. If the TARG_CREATE constant + * is given, a new, empty node will be created for the target, placed in the + * table of all targets and its address returned. If TARG_NOCREATE is given, + * a NULL pointer will be returned. + */ +#define TARG_NOCREATE 0x00 /* don't create it */ +#define TARG_CREATE 0x01 /* create node if not found */ +#define TARG_NOHASH 0x02 /* don't look in/add to hash table */ + +/* + * Error levels for parsing. PARSE_FATAL means the process cannot continue + * once the makefile has been parsed. PARSE_WARNING means it can. Passed + * as the first argument to Parse_Error. + */ +#define PARSE_INFO 3 +#define PARSE_WARNING 2 +#define PARSE_FATAL 1 + +/* + * Values returned by Cond_Eval. + */ +typedef enum { + 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 " (b)) ? (a) : (b)) +#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 + +#endif /* MAKE_MAKE_H */ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/make_malloc.c =================================================================== --- vendor/NetBSD/bmake/20200902/make_malloc.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/make_malloc.c (revision 365363) @@ -0,0 +1,101 @@ +/* $NetBSD: make_malloc.c,v 1.18 2020/09/02 06:10:44 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. + */ + +#ifdef MAKE_NATIVE +#include +__RCSID("$NetBSD: make_malloc.c,v 1.18 2020/09/02 06:10:44 rillig Exp $"); +#endif + +#include +#include +#include +#include + +#include "make.h" + +#ifndef USE_EMALLOC +static MAKE_ATTR_DEAD void enomem(void); + +/* 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/20200902/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/20200902/make_malloc.h =================================================================== --- vendor/NetBSD/bmake/20200902/make_malloc.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/make_malloc.h (revision 365363) @@ -0,0 +1,54 @@ +/* $NetBSD: make_malloc.h,v 1.10 2020/08/29 16:47:45 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(x) emalloc(x) +#define bmake_realloc(x,y) erealloc(x,y) +#define bmake_strdup(x) estrdup(x) +#define bmake_strldup(x,y) estrndup(x,y) +#endif +char *bmake_strsedup(const char *, const char *); + +/* Thin wrapper around free(3) to avoid the extra function call in case + * p is NULL, which on x86_64 costs about 12 machine instructions. + * Other platforms are similarly affected. + * + * 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 void MAKE_ATTR_UNUSED +bmake_free(void *p) +{ + if (p != NULL) + free(p); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/meta.c =================================================================== --- vendor/NetBSD/bmake/20200902/meta.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/meta.c (revision 365363) @@ -0,0 +1,1730 @@ +/* $NetBSD: meta.c,v 1.113 2020/09/02 04:08:54 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 Lst metaBailiwick; /* our scope of control */ +static char *metaBailiwickStr; /* string storage for the list */ +static Lst metaIgnorePaths; /* paths we deliberately ignore */ +static char *metaIgnorePathsStr; /* string storage for the list */ + +#ifndef MAKE_META_IGNORE_PATHS +#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS" +#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 n; + 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 { + error = 0; + fprintf(mfp, "\n-- filemon acquired metadata --\n"); + + while ((n = read(fd, buf, sizeof(buf))) > 0) { + if ((int)fwrite(buf, 1, 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 - (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) - (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 int p_len; + char *cmd = cmdp; + GNode *gn = gnp; + char *mp = NULL; + char *cp; + char *cp2; + int rc = 0; /* keep looking */ + + if (!p_make) { + p_make = Var_Value(".MAKE", gn, &cp); + p_len = strlen(p_make); + } + cp = strchr(cmd, '$'); + if ((cp)) { + mp = Var_Subst(cmd, gn, VARE_WANTRES); + 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 int +printCMD(void *cmdp, void *mfpp) +{ + meta_file_t *mfp = mfpp; + char *cmd = cmdp; + char *cmd_freeIt = NULL; + + if (strchr(cmd, '$')) { + cmd = cmd_freeIt = Var_Subst(cmd, mfp->gn, VARE_WANTRES); + } + fprintf(mfp->fp, "CMD %s\n", cmd); + free(cmd_freeIt); + return 0; +} + +/* + * Certain node types never get a .meta file + */ +#define SKIP_META_TYPE(_type) do { \ + if ((gn->type & __CONCAT(OP_, _type))) { \ + if (verbose) { \ + fprintf(debug_file, "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) + fprintf(debug_file, "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_ForEach(gn->commands, is_submake, gn)) { + if (DEBUG(META)) + fprintf(debug_file, "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) + fprintf(debug_file, "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) + fprintf(debug_file, "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; + char *p[5]; /* >= possible uses */ + int i; + + mf.fp = NULL; + i = 0; + + dname = Var_Value(".OBJDIR", gn, &p[i++]); + tname = Var_Value(TARGET, gn, &p[i++]); + + /* 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 */ + mp = Var_Subst("${" MAKE_META_PREFIX "}", gn, VARE_WANTRES); + 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 + if (DEBUG(META)) + fprintf(debug_file, "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; + + Lst_ForEach(gn->commands, printCMD, &mf); + + fprintf(mf.fp, "CWD %s\n", getcwd(buf, sizeof(buf))); + fprintf(mf.fp, "TARGET %s\n", tname); + cp = Var_Value(".OODATE", gn, &p[i++]); + 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: + for (i--; i >= 0; i--) { + bmake_free(p[i]); + } + + 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; + + 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_Init(); + metaBailiwickStr = Var_Subst("${.MAKE.META.BAILIWICK:O:u:tA}", + VAR_GLOBAL, VARE_WANTRES); + str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL); + /* + * We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS} + */ + metaIgnorePaths = Lst_Init(); + Var_Append(MAKE_META_IGNORE_PATHS, + "/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL); + metaIgnorePathsStr = Var_Subst("${" MAKE_META_IGNORE_PATHS ":O:u:tA}", + VAR_GLOBAL, VARE_WANTRES); + str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL); + + /* + * We ignore any paths that match ${.MAKE.META.IGNORE_PATTERNS} + */ + cp = NULL; + if (Var_Value(MAKE_META_IGNORE_PATTERNS, VAR_GLOBAL, &cp)) { + metaIgnorePatterns = TRUE; + bmake_free(cp); + } + cp = NULL; + if (Var_Value(MAKE_META_IGNORE_FILTER, VAR_GLOBAL, &cp)) { + metaIgnoreFilter = TRUE; + bmake_free(cp); + } +} + +/* + * 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", gn->path ? gn->path : gn->name, 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 int meta_prefix_len; + + if (!meta_prefix) { + char *cp2; + + meta_prefix = Var_Subst("${" MAKE_META_PREFIX "}", + VAR_GLOBAL, VARE_WANTRES); + if ((cp2 = strchr(meta_prefix, '$'))) + meta_prefix_len = 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], bufsz - o, fp) != NULL) { + check_newline: + x = o + 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((fs.st_size / 2), BUFSIZ); + if (newsz <= bufsz) + newsz = ROUNDUP(fs.st_size, BUFSIZ); + if (newsz <= bufsz) + return x; /* truncated */ + if (DEBUG(META)) + fprintf(debug_file, "growing buffer %u -> %u\n", + (unsigned)bufsz, (unsigned)newsz); + p = bmake_realloc(buf, newsz); + if (p) { + *bufp = buf = p; + *szp = bufsz = newsz; + /* fetch the rest */ + if (!fgets(&buf[x], bufsz - x, fp)) + return x; /* truncated! */ + goto check_newline; + } + } + } + return 0; +} + +/* Lst_ForEach 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_match(const void *p, const void *q) +{ + const char *path = p; + const char *prefix = q; + size_t n = strlen(prefix); + + if (strncmp(path, prefix, n) != 0) + return FALSE; + return path[n] == '\0' || path[n] == '/'; +} + +static Boolean +string_match(const void *p, const void *q) +{ + return strcmp(p, q) == 0; +} + + +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_ForEach(metaIgnorePaths, prefix_match, fname)) { +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "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}@}"; + pm = Var_Subst(expr, gn, VARE_WANTRES); + if (*pm) { +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "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); + fm = Var_Subst(fname, gn, VARE_WANTRES); + if (*fm == '\0') { +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "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'; \ + } + +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; + Lst missingFiles; + char *pa[4]; /* >= possible uses */ + int i; + int have_filemon = FALSE; + + if (oodate) + return oodate; /* we're done */ + + i = 0; + + dname = Var_Value(".OBJDIR", gn, &pa[i++]); + tname = Var_Value(TARGET, gn, &pa[i++]); + + /* if this succeeds fname3 is realpath of dname */ + if (!meta_needed(gn, dname, fname3, FALSE)) + goto oodate_out; + dname = fname3; + + missingFiles = Lst_Init(); + + /* + * 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 + if (DEBUG(META)) + fprintf(debug_file, "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; + LstNode ln; + 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); + + ln = Lst_First(gn->commands); + 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 + if (DEBUG(META)) + fprintf(debug_file, "%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; + char *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)) + fprintf(debug_file, "%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)) + fprintf(debug_file, "%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 + if (DEBUG(META)) + fprintf(debug_file, "%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 == '/' && !Lst_IsEmpty(missingFiles)) { + /* remove any missingFiles entries that match p */ + ln = Lst_Find(missingFiles, path_match, p); + if (ln != NULL) { + LstNode nln; + char *tp; + + do { + nln = Lst_FindFrom(missingFiles, + LstNode_Next(ln), + path_match, p); + tp = LstNode_Datum(ln); + Lst_Remove(missingFiles, ln); + free(tp); + } while ((ln = nln) != NULL); + } + } + if (buf[0] == 'M') { + /* the target of the mv is a file 'W'ritten */ +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "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 + if (DEBUG(META)) + fprintf(debug_file, "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_ForEach(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)) { + if (Lst_Find(missingFiles, string_match, p) == NULL) + Lst_Append(missingFiles, bmake_strdup(p)); + } + } + break; + check_link_src: + p = link_src; + link_src = NULL; +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "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 + if (DEBUG(META)) + fprintf(debug_file, "%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 + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: found: %s\n", fname, lineno, p); +#endif + if (!S_ISDIR(mst.mst_mode) && + mst.mst_mtime > gn->mtime) { + if (DEBUG(META)) + fprintf(debug_file, "%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... + */ + if (Lst_Find(missingFiles, string_match, p) == NULL) + Lst_Append(missingFiles, bmake_strdup(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 (ln == NULL) { + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: there were more build commands in the meta data file than there are now...\n", fname, lineno); + oodate = TRUE; + } else { + char *cmd = LstNode_Datum(ln); + 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; + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno); + } + cmd = Var_Subst(cmd, gn, VARE_WANTRES|VARE_UNDEFERR); + + 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) { + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: a build command has changed\n%s\nvs\n%s\n", fname, lineno, p, cmd); + if (!metaIgnoreCMDs) + oodate = TRUE; + } + free(cmd); + ln = LstNode_Next(ln); + } + } else if (strcmp(buf, "CWD") == 0) { + /* + * Check if there are extra commands now + * that weren't in the meta data file. + */ + if (!oodate && ln != NULL) { + if (DEBUG(META)) + fprintf(debug_file, "%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) { + if (DEBUG(META)) + fprintf(debug_file, "%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)) { + if (DEBUG(META)) + fprintf(debug_file, "%s: missing files: %s...\n", + fname, (char *)LstNode_Datum(Lst_First(missingFiles))); + oodate = TRUE; + } + if (!oodate && !have_filemon && filemonMissing) { + if (DEBUG(META)) + fprintf(debug_file, "%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, (cp - gn->path)) != 0) { + cp = NULL; /* not in .CURDIR */ + } + } + if (!cp) { + if (DEBUG(META)) + fprintf(debug_file, "%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, Var_Value(ALLSRC, gn, &cp), gn); + bmake_free(cp); + } + + oodate_out: + for (i--; i >= 0; i--) { + bmake_free(pa[i]); + } + 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) { + execError("dup2", "pipe"); + _exit(1); + } +} + +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/20200902/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/20200902/metachar.c =================================================================== --- vendor/NetBSD/bmake/20200902/metachar.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/metachar.c (revision 365363) @@ -0,0 +1,88 @@ +/* $NetBSD: metachar.c,v 1.6 2020/08/03 20:43:41 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 + +#if defined(__RCSID) && !defined(lint) +__RCSID("$NetBSD: metachar.c,v 1.6 2020/08/03 20:43:41 rillig Exp $"); +#endif + +#include "metachar.h" +/* + * 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. + * + * perhaps move it to ctype? + */ + +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/20200902/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/20200902/metachar.h =================================================================== --- vendor/NetBSD/bmake/20200902/metachar.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/metachar.h (revision 365363) @@ -0,0 +1,52 @@ +/* $NetBSD: metachar.h,v 1.7 2020/08/25 17:37:09 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 ismeta(c) _metachar[(c) & 0x7f] + +static inline int MAKE_ATTR_UNUSED +needshell(const char *cmd, int white) +{ + while (!ismeta(*cmd) && *cmd != ':' && *cmd != '=') { + if (white && isspace((unsigned char)*cmd)) + break; + cmd++; + } + + return *cmd != '\0'; +} + +#endif /* MAKE_METACHAR_H */ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/mk/ChangeLog =================================================================== --- vendor/NetBSD/bmake/20200902/mk/ChangeLog (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/ChangeLog (revision 365363) @@ -0,0 +1,1681 @@ +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/20200902/mk/FILES =================================================================== --- vendor/NetBSD/bmake/20200902/mk/FILES (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/FILES (revision 365363) @@ -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/20200902/mk/README =================================================================== --- vendor/NetBSD/bmake/20200902/mk/README (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/README (revision 365363) @@ -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/20200902/mk/auto.dep.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/auto.dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/auto.dep.mk (revision 365363) @@ -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/20200902/mk/auto.obj.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/auto.obj.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/auto.obj.mk (revision 365363) @@ -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/20200902/mk/autoconf.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/autoconf.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/autoconf.mk (revision 365363) @@ -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/20200902/mk/autodep.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/autodep.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/autodep.mk (revision 365363) @@ -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/20200902/mk/compiler.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/compiler.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/compiler.mk (revision 365363) @@ -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/20200902/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/20200902/mk/cython.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/cython.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/cython.mk (revision 365363) @@ -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/20200902/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/20200902/mk/dirdeps-cache-update.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dirdeps-cache-update.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dirdeps-cache-update.mk (revision 365363) @@ -0,0 +1,179 @@ +# $Id: dirdeps-cache-update.mk,v 1.21 2020/08/19 17:51:53 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) +# 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 +.if !target(${cache_update_dirdep}) +dirdeps: ${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 +.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/20200902/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/20200902/mk/dirdeps-options.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dirdeps-options.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dirdeps-options.mk (revision 365363) @@ -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/20200902/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/20200902/mk/dirdeps-targets.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dirdeps-targets.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dirdeps-targets.mk (revision 365363) @@ -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/20200902/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/20200902/mk/dirdeps.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dirdeps.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dirdeps.mk (revision 365363) @@ -0,0 +1,867 @@ +# $Id: dirdeps.mk,v 1.125 2020/08/26 21:49:45 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} +.elif ${TARGET_SPEC_VARS:[#]} > 10 +# seriously? better have jot(1) or equivalent to produce suitable sequence +_tspec_x := ${${JOT:Ujot} ${TARGET_SPEC_VARS:[#]}:L:sh} +.else +# we can provide the sequence ourselves +_tspec_x := ${1 2 3 4 5 6 7 8 9 10:L:[1..${TARGET_SPEC_VARS:[#]}]} +.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 + +# 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 \ + ${.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 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/20200902/mk/dpadd.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dpadd.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dpadd.mk (revision 365363) @@ -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/20200902/mk/files.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/files.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/files.mk (revision 365363) @@ -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/20200902/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/20200902/mk/gendirdeps.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/gendirdeps.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/gendirdeps.mk (revision 365363) @@ -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/20200902/mk/host-target.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/host-target.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/host-target.mk (revision 365363) @@ -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/20200902/mk/host.libnames.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/host.libnames.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/host.libnames.mk (revision 365363) @@ -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/20200902/mk/inc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/inc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/inc.mk (revision 365363) @@ -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/20200902/mk/init.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/init.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/init.mk (revision 365363) @@ -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/20200902/mk/install-mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/install-mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/install-mk (revision 365363) @@ -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.179 2020/08/26 21:49:45 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=20200826 +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/20200902/mk/install-new.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/install-new.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/install-new.mk (revision 365363) @@ -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/20200902/mk/java.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/java.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/java.mk (revision 365363) @@ -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/20200902/mk/lib.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/lib.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/lib.mk (revision 365363) @@ -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/20200902/mk/libnames.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/libnames.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/libnames.mk (revision 365363) @@ -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/20200902/mk/libs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/libs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/libs.mk (revision 365363) @@ -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/20200902/mk/links.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/links.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/links.mk (revision 365363) @@ -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/20200902/mk/manifest.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/manifest.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/manifest.mk (revision 365363) @@ -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/20200902/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/20200902/mk/meta.autodep.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta.autodep.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta.autodep.mk (revision 365363) @@ -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/20200902/mk/meta.stage.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta.stage.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta.stage.mk (revision 365363) @@ -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/20200902/mk/meta.subdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta.subdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta.subdir.mk (revision 365363) @@ -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/20200902/mk/meta.sys.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta.sys.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta.sys.mk (revision 365363) @@ -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/20200902/mk/meta2deps.py =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta2deps.py (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta2deps.py (revision 365363) @@ -0,0 +1,767 @@ +#!/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.33 2020/08/19 17:51:53 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) + + 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/20200902/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/20200902/mk/meta2deps.sh =================================================================== --- vendor/NetBSD/bmake/20200902/mk/meta2deps.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/meta2deps.sh (revision 365363) @@ -0,0 +1,405 @@ +#!/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.13 2020/08/19 17:51:53 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" +} + +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,;/^[CREFLM] /!d' -e "s,',,g" | + $_excludes | + 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} + 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 + 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 + _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/20200902/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/20200902/mk/mk-files.txt =================================================================== --- vendor/NetBSD/bmake/20200902/mk/mk-files.txt (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/mk-files.txt (revision 365363) @@ -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/20200902/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/20200902/mk/mkopt.sh =================================================================== --- vendor/NetBSD/bmake/20200902/mk/mkopt.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/mkopt.sh (revision 365363) @@ -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/20200902/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/20200902/mk/obj.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/obj.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/obj.mk (revision 365363) @@ -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/20200902/mk/options.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/options.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/options.mk (revision 365363) @@ -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/20200902/mk/own.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/own.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/own.mk (revision 365363) @@ -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/20200902/mk/prlist.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/prlist.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/prlist.mk (revision 365363) @@ -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/20200902/mk/prog.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/prog.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/prog.mk (revision 365363) @@ -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/20200902/mk/progs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/progs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/progs.mk (revision 365363) @@ -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/20200902/mk/rst2htm.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/rst2htm.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/rst2htm.mk (revision 365363) @@ -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/20200902/mk/scripts.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/scripts.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/scripts.mk (revision 365363) @@ -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/20200902/mk/srctop.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/srctop.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/srctop.mk (revision 365363) @@ -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/20200902/mk/stage-install.sh =================================================================== --- vendor/NetBSD/bmake/20200902/mk/stage-install.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/stage-install.sh (revision 365363) @@ -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/20200902/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/20200902/mk/sys/AIX.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/AIX.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/AIX.mk (revision 365363) @@ -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/20200902/mk/sys/Darwin.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/Darwin.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/Darwin.mk (revision 365363) @@ -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/20200902/mk/sys/Generic.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/Generic.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/Generic.mk (revision 365363) @@ -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/20200902/mk/sys/HP-UX.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/HP-UX.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/HP-UX.mk (revision 365363) @@ -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/20200902/mk/sys/IRIX.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/IRIX.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/IRIX.mk (revision 365363) @@ -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/20200902/mk/sys/Linux.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/Linux.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/Linux.mk (revision 365363) @@ -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/20200902/mk/sys/NetBSD.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/NetBSD.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/NetBSD.mk (revision 365363) @@ -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/20200902/mk/sys/OSF1.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/OSF1.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/OSF1.mk (revision 365363) @@ -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/20200902/mk/sys/OpenBSD.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/OpenBSD.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/OpenBSD.mk (revision 365363) @@ -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/20200902/mk/sys/SunOS.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/SunOS.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/SunOS.mk (revision 365363) @@ -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/20200902/mk/sys/UnixWare.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys/UnixWare.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys/UnixWare.mk (revision 365363) @@ -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/20200902/mk/sys.clean-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys.clean-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys.clean-env.mk (revision 365363) @@ -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/20200902/mk/sys.debug.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys.debug.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys.debug.mk (revision 365363) @@ -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/20200902/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/20200902/mk/sys.dependfile.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys.dependfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys.dependfile.mk (revision 365363) @@ -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/20200902/mk/sys.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys.mk (revision 365363) @@ -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/20200902/mk/sys.vars.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/sys.vars.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/sys.vars.mk (revision 365363) @@ -0,0 +1,85 @@ +# $Id: sys.vars.mk,v 1.5 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 +# + +# 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] + +# 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/20200902/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/20200902/mk/target-flags.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/target-flags.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/target-flags.mk (revision 365363) @@ -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/20200902/mk/warnings.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/warnings.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/warnings.mk (revision 365363) @@ -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/20200902/mk/whats.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/whats.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/whats.mk (revision 365363) @@ -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/20200902/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/20200902/mk/yacc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/yacc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/yacc.mk (revision 365363) @@ -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/20200902/mk/doc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/doc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/doc.mk (revision 365363) @@ -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/20200902/mk/ldorder.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/ldorder.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/ldorder.mk (revision 365363) @@ -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/20200902/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/20200902/mk/final.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/final.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/final.mk (revision 365363) @@ -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/20200902/mk/subdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/subdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/subdir.mk (revision 365363) @@ -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/20200902/mk/nls.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/nls.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/nls.mk (revision 365363) @@ -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/20200902/mk/dep.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/dep.mk (revision 365363) @@ -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/20200902/mk/man.mk =================================================================== --- vendor/NetBSD/bmake/20200902/mk/man.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/mk/man.mk (revision 365363) @@ -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/20200902/nonints.h =================================================================== --- vendor/NetBSD/bmake/20200902/nonints.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/nonints.h (revision 365363) @@ -0,0 +1,233 @@ +/* $NetBSD: nonints.h,v 1.102 2020/08/30 19:56:02 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 */ +Boolean Arch_ParseArchive(char **, Lst, GNode *); +void Arch_Touch(GNode *); +void Arch_TouchLib(GNode *); +time_t Arch_MTime(GNode *); +time_t Arch_MemMTime(GNode *); +void Arch_FindLib(GNode *, Lst); +Boolean Arch_LibOODate(GNode *); +void Arch_Init(void); +void Arch_End(void); +Boolean Arch_IsLib(GNode *); + +/* compat.c */ +int CompatRunCommand(void *, void *); +void Compat_Run(Lst); +int Compat_Make(void *, void *); + +/* cond.c */ +struct If; +CondEvalResult Cond_EvalExpression(const struct If *, char *, Boolean *, int, Boolean); +CondEvalResult Cond_Eval(char *); +void Cond_restore_depth(unsigned int); +unsigned int Cond_save_depth(void); + +/* for.c */ +int For_Eval(char *); +int For_Accum(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; +int PrintAddr(void *, void *); +void Finish(int) MAKE_ATTR_DEAD; +int eunlink(const char *); +void execError(const char *, const char *); +char *getTmpdir(void); +Boolean s2Boolean(const char *, Boolean); +Boolean getBoolean(const char *, Boolean); +char *cached_realpath(const char *, char *); + +/* parse.c */ +void Parse_Error(int, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3); +Boolean Parse_IsVar(char *); +void Parse_DoVar(char *, GNode *); +void Parse_AddIncludeDir(char *); +void Parse_File(const char *, int); +void Parse_Init(void); +void Parse_End(void); +void Parse_SetInput(const char *, int, int, char *(*)(void *, size_t *), void *); +Lst Parse_MainName(void); + +/* str.c */ +typedef struct { + char **words; + size_t len; + void *freeIt; +} Words; + +Words Str_Words(const char *, Boolean); +static inline void MAKE_ATTR_UNUSED +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 *); +char *Str_FindSubstring(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_ClearSuffixes(void); +Boolean Suff_IsTransform(char *); +GNode *Suff_AddTransform(char *); +int Suff_EndTransform(void *, void *); +void Suff_AddSuffix(const char *, GNode **); +Lst Suff_GetPath(char *); +void Suff_DoPaths(void); +void Suff_AddInclude(char *); +void Suff_AddLib(const char *); +void Suff_FindDeps(GNode *); +Lst Suff_FindPath(GNode *); +void Suff_SetNull(char *); +void Suff_Init(void); +void Suff_End(void); +void Suff_PrintAll(void); + +/* targ.c */ +void Targ_Init(void); +void Targ_End(void); +void Targ_Stats(void); +Lst Targ_List(void); +GNode *Targ_NewGN(const char *); +GNode *Targ_FindNode(const char *, int); +Lst Targ_FindList(Lst, int); +Boolean Targ_Ignore(GNode *); +Boolean Targ_Silent(GNode *); +Boolean Targ_Precious(GNode *); +void Targ_SetMain(GNode *); +int Targ_PrintCmd(void *, void *); +int Targ_PrintNode(void *, void *); +char *Targ_FmtTime(time_t); +void Targ_PrintType(int); +void Targ_PrintGraph(int); +void Targ_Propagate(void); + +/* var.c */ + +typedef enum { + /* Treat undefined variables as errors. */ + VARE_UNDEFERR = 0x01, + /* Expand and evaluate variables during parsing. */ + VARE_WANTRES = 0x02, + VARE_ASSIGN = 0x04 +} VarEvalFlags; + +typedef enum { + 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; + + +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 *, char **); +const char *Var_Parse(const char *, GNode *, VarEvalFlags, int *, void **); +char *Var_Subst(const char *, GNode *, VarEvalFlags); +void Var_Init(void); +void Var_End(void); +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 */ +void (*bmake_signal(int, void (*)(int)))(int); Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/os.sh =================================================================== --- vendor/NetBSD/bmake/20200902/os.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/os.sh (revision 365363) @@ -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/20200902/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/20200902/parse.c =================================================================== --- vendor/NetBSD/bmake/20200902/parse.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/parse.c (revision 365363) @@ -0,0 +1,3376 @@ +/* $NetBSD: parse.c,v 1.275 2020/09/01 17:38: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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: parse.c,v 1.275 2020/09/01 17:38:26 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: parse.c,v 1.275 2020/09/01 17:38:26 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * parse.c -- + * Functions to parse a makefile. + * + * One function, Parse_Init, must be called before any functions + * in this module are used. After that, the function Parse_File is the + * main entry point and controls most of the other functions in this + * module. + * + * Most important structures are kept in Lsts. Directories for + * the .include "..." function are kept in the 'parseIncPath' Lst, while + * those for the .include <...> are kept in the 'sysIncPath' Lst. The + * targets currently being defined are kept in the 'targets' Lst. + * + * The variables 'fname' and 'lineno' are used to track the name + * of the current file and the line number in that file so that error + * messages can be more meaningful. + * + * Interface: + * Parse_Init Initialization function which must be + * called before anything else in this module + * is used. + * + * Parse_End Cleanup the module + * + * Parse_File Function used to parse a makefile. It must + * be given the name of the file, which should + * already have been opened, and a function + * to call to read a character from the file. + * + * Parse_IsVar Returns 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 Function called when an error occurs in + * parsing. Used by the variable and + * conditional modules. + * Parse_MainName Returns a Lst of the main target to create. + */ + +#include +#include +#include +#include +#include + +#include "make.h" +#include "dir.h" +#include "job.h" +#include "pathnames.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 + +/* types and constants */ + +/* + * Structure for a file being read ("included file") + */ +typedef struct IFile { + char *fname; /* name of file */ + int lineno; /* current line number in file */ + int first_lineno; /* line number of start of text */ + int cond_depth; /* 'if' nesting when file opened */ + Boolean depending; /* state of doing_depend on EOF */ + char *P_str; /* point to base of string buffer */ + char *P_ptr; /* point to next char of string buffer */ + char *P_end; /* point to the end of string buffer */ + 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; + + +/* + * These values are returned by ParseEOF to tell Parse_File whether to + * CONTINUE parsing, i.e. it had only reached the end of an include file, + * or if it's DONE. + */ +#define CONTINUE 1 +#define DONE 0 + +/* + * Tokens for target attributes + */ +typedef enum { + Begin, /* .BEGIN */ + Default, /* .DEFAULT */ + DeleteOnError, /* .DELETE_ON_ERROR */ + End, /* .END */ + dotError, /* .ERROR */ + Ignore, /* .IGNORE */ + Includes, /* .INCLUDES */ + Interrupt, /* .INTERRUPT */ + Libs, /* .LIBS */ + Meta, /* .META */ + MFlags, /* .MFLAGS or .MAKEFLAGS */ + Main, /* .MAIN and we don't have anything user-specified to + * make */ + NoExport, /* .NOEXPORT */ + NoMeta, /* .NOMETA */ + NoMetaCmp, /* .NOMETA_CMP */ + NoPath, /* .NOPATH */ + Not, /* Not special */ + NotParallel, /* .NOTPARALLEL */ + Null, /* .NULL */ + ExObjdir, /* .OBJDIR */ + Order, /* .ORDER */ + Parallel, /* .PARALLEL */ + ExPath, /* .PATH */ + Phony, /* .PHONY */ +#ifdef POSIX + Posix, /* .POSIX */ +#endif + Precious, /* .PRECIOUS */ + ExShell, /* .SHELL */ + Silent, /* .SILENT */ + SingleShell, /* .SINGLESHELL */ + Stale, /* .STALE */ + Suffixes, /* .SUFFIXES */ + Wait, /* .WAIT */ + Attribute /* Generic attribute */ +} ParseSpecial; + +/* + * Other tokens + */ +#define LPAREN '(' +#define RPAREN ')' + + +/* 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 */ + +/* targets we're working on */ +static Lst targets; + +#ifdef CLEANUP +/* command lines for targets */ +static Lst targCmds; +#endif + +/* + * specType contains the SPECial TYPE of the current target. It is + * Not if the target is unspecial. If it *is* special, however, the children + * are linked as children of the parent but not vice versa. This variable is + * set in ParseDoDependency + */ +static ParseSpecial specType; + +/* + * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER + * seen, then set to each successive source on the line. + */ +static GNode *predecessor; + +/* parser state */ + +/* true if currently in a dependency line or its commands */ +static Boolean inLine; + +/* number of fatal errors */ +static int fatals = 0; + +/* + * Variables for doing includes + */ + +/* current file being read */ +static IFile *curFile; + +/* stack of IFiles generated by .includes */ +static Lst includes; + +/* include paths (lists of directories) */ +Lst parseIncPath; /* dirs for "..." includes */ +Lst sysIncPath; /* dirs for <...> includes */ +Lst defIncPath; /* 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 ("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 */ + int op; /* Operator when used as a source */ +} parseKeywords[] = { +{ ".BEGIN", Begin, 0 }, +{ ".DEFAULT", Default, 0 }, +{ ".DELETE_ON_ERROR", DeleteOnError, 0 }, +{ ".END", End, 0 }, +{ ".ERROR", dotError, 0 }, +{ ".EXEC", Attribute, OP_EXEC }, +{ ".IGNORE", Ignore, OP_IGNORE }, +{ ".INCLUDES", Includes, 0 }, +{ ".INTERRUPT", Interrupt, 0 }, +{ ".INVISIBLE", Attribute, OP_INVISIBLE }, +{ ".JOIN", Attribute, OP_JOIN }, +{ ".LIBS", Libs, 0 }, +{ ".MADE", Attribute, OP_MADE }, +{ ".MAIN", Main, 0 }, +{ ".MAKE", Attribute, OP_MAKE }, +{ ".MAKEFLAGS", MFlags, 0 }, +{ ".META", Meta, OP_META }, +{ ".MFLAGS", MFlags, 0 }, +{ ".NOMETA", NoMeta, OP_NOMETA }, +{ ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP }, +{ ".NOPATH", NoPath, OP_NOPATH }, +{ ".NOTMAIN", Attribute, OP_NOTMAIN }, +{ ".NOTPARALLEL", NotParallel, 0 }, +{ ".NO_PARALLEL", NotParallel, 0 }, +{ ".NULL", Null, 0 }, +{ ".OBJDIR", ExObjdir, 0 }, +{ ".OPTIONAL", Attribute, OP_OPTIONAL }, +{ ".ORDER", Order, 0 }, +{ ".PARALLEL", Parallel, 0 }, +{ ".PATH", ExPath, 0 }, +{ ".PHONY", Phony, OP_PHONY }, +#ifdef POSIX +{ ".POSIX", Posix, 0 }, +#endif +{ ".PRECIOUS", Precious, OP_PRECIOUS }, +{ ".RECURSIVE", Attribute, OP_MAKE }, +{ ".SHELL", ExShell, 0 }, +{ ".SILENT", Silent, OP_SILENT }, +{ ".SINGLESHELL", SingleShell, 0 }, +{ ".STALE", Stale, 0 }, +{ ".SUFFIXES", Suffixes, 0 }, +{ ".USE", Attribute, OP_USE }, +{ ".USEBEFORE", Attribute, OP_USEBEFORE }, +{ ".WAIT", Wait, 0 }, +}; + +/* local functions */ + +static int ParseIsEscaped(const char *, const char *); +static void ParseErrorInternal(const char *, size_t, int, const char *, ...) + MAKE_ATTR_PRINTFLIKE(4,5); +static void ParseVErrorInternal(FILE *, const char *, size_t, int, const char *, va_list) + MAKE_ATTR_PRINTFLIKE(5, 0); +static int ParseFindKeyword(const char *); +static int ParseLinkSrc(void *, void *); +static int ParseDoOp(void *, void *); +static void ParseDoSrc(int, const char *); +static int ParseFindMain(void *, void *); +static int ParseAddDir(void *, void *); +static int ParseClearPath(void *, void *); +static void ParseDoDependency(char *); +static int ParseAddCmd(void *, void *); +static void ParseHasCommands(void *); +static void ParseDoInclude(char *); +static void ParseSetParseFile(const char *); +static void ParseSetIncludedFile(void); +#ifdef GMAKEEXPORT +static void ParseGmakeExport(char *); +#endif +static int ParseEOF(void); +static char *ParseReadLine(void); +static void ParseFinishLine(void); +static void ParseMark(GNode *); + +/* 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 */ +}; + +/* + * Constructor/destructor for loadedfile + */ +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; +} + +/* + * 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; +#ifdef HAVE_MMAP + static long pagesize = 0; +#endif + 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 (load_getsize(fd, &lf->len)) { + /* found a size, try mmap */ +#ifdef _SC_PAGESIZE + if (pagesize == 0) + pagesize = sysconf(_SC_PAGESIZE); +#endif + if (pagesize <= 0) { + 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; + } + 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 += 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 */ + +/*- + *---------------------------------------------------------------------- + * ParseIsEscaped -- + * Check if the current character is escaped on the current line + * + * Results: + * 0 if the character is not backslash escaped, 1 otherwise + * + * Side Effects: + * None + *---------------------------------------------------------------------- + */ +static int +ParseIsEscaped(const char *line, const char *c) +{ + int active = 0; + for (;;) { + if (line == c) + return active; + if (*--c != '\\') + return active; + active = !active; + } +} + +/*- + *---------------------------------------------------------------------- + * ParseFindKeyword -- + * Look in the table of keywords for one matching the given string. + * + * Input: + * str String to find + * + * Results: + * The index of the keyword, or -1 if it isn't there. + * + * Side Effects: + * None + *---------------------------------------------------------------------- + */ +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; +} + +/*- + * ParseVErrorInternal -- + * Error message abort function for parsing. Prints out the context + * of the error (line number and file) as well as the message with + * two optional arguments. + * + * Results: + * None + * + * Side Effects: + * "fatals" is incremented if the level is PARSE_FATAL. + */ +/* VARARGS */ +static void +ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type, + const char *fmt, va_list ap) +{ + static Boolean fatal_warning_error_printed = FALSE; + char dirbuf[MAXPATHLEN+1]; + + (void)fprintf(f, "%s: ", progname); + + if (cfname != NULL) { + (void)fprintf(f, "\""); + if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) { + char *cp, *cp2; + const char *dir, *fname; + + /* + * Nothing is more annoying than not knowing + * which Makefile is the culprit; we try ${.PARSEDIR} + * and apply realpath(3) if not absolute. + */ + dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp); + if (dir == NULL) + dir = "."; + if (*dir != '/') { + dir = realpath(dir, dirbuf); + } + fname = Var_Value(".PARSEFILE", VAR_GLOBAL, &cp2); + if (fname == NULL) { + if ((fname = strrchr(cfname, '/'))) + fname++; + else + fname = cfname; + } + (void)fprintf(f, "%s/%s", dir, fname); + bmake_free(cp2); + bmake_free(cp); + } else + (void)fprintf(f, "%s", cfname); + + (void)fprintf(f, "\" line %d: ", (int)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 || parseWarnFatal) + fatals += 1; + if (parseWarnFatal && !fatal_warning_error_printed) { + Error("parsing warnings being treated as errors"); + fatal_warning_error_printed = TRUE; + } +} + +/*- + * ParseErrorInternal -- + * Error function + * + * Results: + * None + * + * Side Effects: + * None + */ +/* VARARGS */ +static void +ParseErrorInternal(const char *cfname, size_t clineno, int 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 (debug_file != stderr && debug_file != stdout) { + va_start(ap, fmt); + ParseVErrorInternal(debug_file, cfname, clineno, type, fmt, ap); + va_end(ap); + } +} + +/*- + * Parse_Error -- + * External interface to ParseErrorInternal; uses the default filename + * Line number. + * + * Results: + * None + * + * Side Effects: + * None + */ +/* VARARGS */ +void +Parse_Error(int type, const char *fmt, ...) +{ + va_list ap; + const char *fname; + size_t lineno; + + if (curFile == NULL) { + fname = NULL; + lineno = 0; + } else { + fname = curFile->fname; + lineno = curFile->lineno; + } + + va_start(ap, fmt); + (void)fflush(stdout); + ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); + va_end(ap); + + if (debug_file != stderr && debug_file != stdout) { + va_start(ap, fmt); + ParseVErrorInternal(debug_file, fname, lineno, type, fmt, ap); + va_end(ap); + } +} + + +/* + * ParseMessage + * Parse a .info .warning or .error directive + * + * The input is the line minus the ".". We substitute + * variables, print the message and exit(1) (for .error) or just print + * a warning if the directive is malformed. + */ +static Boolean +ParseMessage(char *line) +{ + int mtype; + + switch(*line) { + case 'i': + mtype = PARSE_INFO; + break; + case 'w': + mtype = PARSE_WARNING; + break; + case 'e': + mtype = PARSE_FATAL; + break; + default: + Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line); + return FALSE; + } + + while (isalpha((unsigned char)*line)) + line++; + if (!isspace((unsigned char)*line)) + return FALSE; /* not for us */ + while (isspace((unsigned char)*line)) + line++; + + line = Var_Subst(line, VAR_CMD, VARE_WANTRES); + Parse_Error(mtype, "%s", line); + free(line); + + if (mtype == PARSE_FATAL) { + /* Terminate immediately. */ + exit(1); + } + return TRUE; +} + +/*- + *--------------------------------------------------------------------- + * ParseLinkSrc -- + * Link the parent node to its new child. Used in a Lst_ForEach by + * ParseDoDependency. If the specType isn't 'Not', the parent + * isn't linked as a parent of the child. + * + * Input: + * pgnp The parent node + * cgpn The child node + * + * Results: + * Always = 0 + * + * Side Effects: + * New elements are added to the parents list of cgn and the + * children list of cgn. the unmade field of pgn is updated + * to reflect the additional child. + *--------------------------------------------------------------------- + */ +static int +ParseLinkSrc(void *pgnp, void *cgnp) +{ + GNode *pgn = (GNode *)pgnp; + GNode *cgn = (GNode *)cgnp; + + if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts)) + pgn = LstNode_Datum(Lst_Last(pgn->cohorts)); + Lst_Append(pgn->children, cgn); + if (specType == Not) + Lst_Append(cgn->parents, pgn); + pgn->unmade += 1; + if (DEBUG(PARSE)) { + fprintf(debug_file, "# %s: added child %s - %s\n", __func__, + pgn->name, cgn->name); + Targ_PrintNode(pgn, 0); + Targ_PrintNode(cgn, 0); + } + return 0; +} + +/*- + *--------------------------------------------------------------------- + * ParseDoOp -- + * Apply the parsed operator to the given target node. Used in a + * Lst_ForEach call by ParseDoDependency once all targets have + * been found and their operator parsed. If the previous and new + * operators are incompatible, a major error is taken. + * + * Input: + * gnp The node to which the operator is to be applied + * opp The operator to apply + * + * Results: + * Always 0 + * + * Side Effects: + * The type field of the node is altered to reflect any new bits in + * the op. + *--------------------------------------------------------------------- + */ +static int +ParseDoOp(void *gnp, void *opp) +{ + GNode *gn = (GNode *)gnp; + int op = *(int *)opp; + /* + * If the dependency mask of the operator and the node don't match and + * the node has actually had an operator applied to it before, and + * the operator actually has some dependency information in it, complain. + */ + if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && + !OP_NOP(gn->type) && !OP_NOP(op)) + { + Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); + return 1; + } + + 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_FindNode(gn->name, TARG_NOHASH); + 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 += 1; + snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", + gn->unmade_cohorts); + } 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 0; +} + +/*- + *--------------------------------------------------------------------- + * ParseDoSrc -- + * Given the name of a source, figure out if it is an attribute + * 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 and apply it if so. Otherwise, make the + * source be a child of the targets in the list 'targets' + * + * Input: + * tOp operator (if any) from special targets + * src name of the source to handle + * + * Results: + * None + * + * Side Effects: + * Operator bits may be added to the list of targets or to the source. + * The targets may have a new source added to their lists of children. + *--------------------------------------------------------------------- + */ +static void +ParseDoSrc(int tOp, const char *src) +{ + GNode *gn = NULL; + static int wait_number = 0; + char wait_src[16]; + + if (*src == '.' && isupper ((unsigned char)src[1])) { + int keywd = ParseFindKeyword(src); + if (keywd != -1) { + int op = parseKeywords[keywd].op; + if (op != 0) { + if (targets != NULL) + Lst_ForEach(targets, ParseDoOp, &op); + return; + } + if (parseKeywords[keywd].spec == 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_FindNode(wait_src, TARG_NOHASH); + if (doing_depend) + ParseMark(gn); + gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; + if (targets != NULL) + Lst_ForEach(targets, ParseLinkSrc, gn); + return; + } + } + } + + switch (specType) { + case Main: + /* + * 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(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); + return; + + case Order: + /* + * Create proper predecessor/successor links between the previous + * source and the current one. + */ + gn = Targ_FindNode(src, TARG_CREATE); + if (doing_depend) + ParseMark(gn); + if (predecessor != NULL) { + Lst_Append(predecessor->order_succ, gn); + Lst_Append(gn->order_pred, predecessor); + if (DEBUG(PARSE)) { + fprintf(debug_file, "# %s: added Order dependency %s - %s\n", + __func__, predecessor->name, gn->name); + Targ_PrintNode(predecessor, 0); + Targ_PrintNode(gn, 0); + } + } + /* + * The current source now becomes the predecessor for the next one. + */ + predecessor = gn; + break; + + default: + /* + * 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_FindNode(src, TARG_CREATE); + if (doing_depend) + ParseMark(gn); + if (tOp) { + gn->type |= tOp; + } else { + if (targets != NULL) + Lst_ForEach(targets, ParseLinkSrc, gn); + } + break; + } +} + +/*- + *----------------------------------------------------------------------- + * ParseFindMain -- + * Find a real target in the list and set it to be the main one. + * Called by ParseDoDependency when a main target hasn't been found + * yet. + * + * Input: + * gnp Node to examine + * + * Results: + * 0 if main not found yet, 1 if it is. + * + * Side Effects: + * mainNode is changed and Targ_SetMain is called. + * + *----------------------------------------------------------------------- + */ +static int +ParseFindMain(void *gnp, void *dummy MAKE_ATTR_UNUSED) +{ + GNode *gn = (GNode *)gnp; + if (!(gn->type & OP_NOTARGET)) { + mainNode = gn; + Targ_SetMain(gn); + return 1; + } else { + return 0; + } +} + +/*- + *----------------------------------------------------------------------- + * ParseAddDir -- + * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going + * + * Results: + * === 0 + * + * Side Effects: + * See Dir_AddDir. + * + *----------------------------------------------------------------------- + */ +static int +ParseAddDir(void *path, void *name) +{ + (void)Dir_AddDir((Lst) path, (char *)name); + return 0; +} + +/*- + *----------------------------------------------------------------------- + * ParseClearPath -- + * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going + * + * Results: + * === 0 + * + * Side Effects: + * See Dir_ClearPath + * + *----------------------------------------------------------------------- + */ +static int +ParseClearPath(void *path, void *dummy MAKE_ATTR_UNUSED) +{ + Dir_ClearPath((Lst) path); + return 0; +} + +/*- + *--------------------------------------------------------------------- + * ParseDoDependency -- + * Parse the dependency line in line. + * + * Input: + * line the line to parse + * + * Results: + * None + * + * Side Effects: + * The nodes of the sources are linked as children to the nodes of the + * targets. Some nodes may be created. + * + * We parse a dependency line by first extracting words from the line and + * finding nodes in the list of all targets with that name. This is done + * until a character is encountered which is an operator character. Currently + * these are only ! and :. At this point the operator is parsed and the + * pointer into the line advanced until the first source is encountered. + * The parsed operator is applied to each node in the 'targets' list, + * which is where the nodes found for the targets are kept, by means of + * the ParseDoOp function. + * The sources are read in much the same way as the targets were except + * that now 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 are handled specially. These are the ones detailed + * by the specType variable. + * The storing of transformation rules 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 */ + GNode *gn = NULL; /* a general purpose temporary node */ + int op; /* the operator on the line */ + char savec; /* a place to save a character */ + Lst paths; /* List of search paths to alter when parsing + * a list of .PATH targets */ + int tOp; /* operator from special target */ + Lst sources; /* list of archive source names after + * expansion */ + Lst curTargs; /* list of target names to be found and added + * to the targets list */ + char *lstart = line; + + if (DEBUG(PARSE)) + fprintf(debug_file, "ParseDoDependency(%s)\n", line); + tOp = 0; + + specType = Not; + paths = NULL; + + curTargs = Lst_Init(); + + /* + * First, grind through the targets. + */ + + do { + /* + * 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. */ + for (cp = line; *cp && (ParseIsEscaped(lstart, cp) || + !(isspace((unsigned char)*cp) || + *cp == '!' || *cp == ':' || *cp == LPAREN)); + cp++) { + 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. + */ + int length; + void *freeIt; + + (void)Var_Parse(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES, + &length, &freeIt); + free(freeIt); + cp += length - 1; + } + } + + /* + * 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 == LPAREN) { + /* + * 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_CMD)) { + Parse_Error(PARSE_FATAL, + "Error in archive specification: \"%s\"", line); + goto out; + } else { + /* Done with this word; on to the next. */ + cp = line; + continue; + } + } + + if (!*cp) { + /* + * 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. + */ + if ((strncmp(line, "<<<<<<", 6) == 0) || + (strncmp(line, "======", 6) == 0) || + (strncmp(line, ">>>>>>", 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; + while (isspace((unsigned char)*dirstart)) + dirstart++; + dirend = dirstart; + while (isalnum((unsigned char)*dirend) || *dirend == '-') + dirend++; + Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"", + (int)(dirend - dirstart), dirstart); + } else + Parse_Error(PARSE_FATAL, "Need an operator"); + goto out; + } + + /* Insert a null terminator. */ + savec = *cp; + *cp = '\0'; + + /* + * Got the word. See if it's a special target and if so set + * specType to match it. + */ + if (*line == '.' && isupper ((unsigned char)line[1])) { + /* + * See if the target is a special target that must have it + * or its sources handled specially. + */ + int keywd = ParseFindKeyword(line); + if (keywd != -1) { + if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { + Parse_Error(PARSE_FATAL, "Mismatched special targets"); + goto out; + } + + specType = parseKeywords[keywd].spec; + tOp = parseKeywords[keywd].op; + + /* + * 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 + */ + switch (specType) { + case ExPath: + if (paths == NULL) { + paths = Lst_Init(); + } + Lst_Append(paths, dirSearchPath); + break; + case Main: + if (!Lst_IsEmpty(create)) { + specType = Not; + } + break; + case Begin: + case End: + case Stale: + case dotError: + case Interrupt: + gn = Targ_FindNode(line, TARG_CREATE); + if (doing_depend) + ParseMark(gn); + gn->type |= OP_NOTMAIN|OP_SPECIAL; + Lst_Append(targets, gn); + break; + case Default: + gn = Targ_NewGN(".DEFAULT"); + gn->type |= (OP_NOTMAIN|OP_TRANSFORM); + Lst_Append(targets, gn); + DEFAULT = gn; + break; + case DeleteOnError: + deleteOnError = TRUE; + break; + case NotParallel: + maxJobs = 1; + break; + case SingleShell: + compatMake = TRUE; + break; + case Order: + predecessor = NULL; + break; + default: + break; + } + } else if (strncmp(line, ".PATH", 5) == 0) { + /* + * .PATH has to be handled specially. + * Call on the suffix module to give us a path to + * modify. + */ + Lst path; + + specType = ExPath; + path = Suff_GetPath(&line[5]); + if (path == NULL) { + Parse_Error(PARSE_FATAL, + "Suffix '%s' not defined (yet)", + &line[5]); + goto out; + } else { + if (paths == NULL) { + paths = Lst_Init(); + } + Lst_Append(paths, path); + } + } + } + + /* + * Have word in line. Get or create its node and stick it at + * the end of the targets list + */ + if (specType == Not && *line != '\0') { + 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... + */ + Lst emptyPath = Lst_Init(); + + 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); + + if (!Suff_IsTransform (targName)) { + gn = Targ_FindNode(targName, TARG_CREATE); + } else { + gn = Suff_AddTransform(targName); + } + if (doing_depend) + ParseMark(gn); + + Lst_Append(targets, gn); + } + } else if (specType == ExPath && *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 (specType != Not && specType != ExPath) { + Boolean warning = FALSE; + + 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"); + } + } else { + while (*cp && isspace ((unsigned char)*cp)) { + cp++; + } + } + line = cp; + } while (*line && (ParseIsEscaped(lstart, line) || + (*line != '!' && *line != ':'))); + + /* + * Don't need the list of target names anymore... + */ + Lst_Free(curTargs); + curTargs = NULL; + + if (targets != NULL && !Lst_IsEmpty(targets)) { + switch(specType) { + default: + Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); + break; + case Default: + case Stale: + case Begin: + case End: + case dotError: + case Interrupt: + /* + * These four create nodes on which to hang commands, so + * targets shouldn't be empty... + */ + case Not: + /* + * Nothing special here -- targets can be empty if it wants. + */ + break; + } + } + + /* + * Have now parsed all the target names. Must parse the operator next. The + * result is left in op . + */ + if (*cp == '!') { + op = OP_FORCE; + } else if (*cp == ':') { + if (cp[1] == ':') { + op = OP_DOUBLEDEP; + cp++; + } else { + op = OP_DEPENDS; + } + } else { + Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" + : "Missing dependency operator"); + goto out; + } + + /* Advance beyond the operator */ + cp++; + + /* + * 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. + */ + if (targets != NULL) + Lst_ForEach(targets, ParseDoOp, &op); + + /* + * Onward to the sources. + * + * LINE will now point to the first source word, if any, or the + * end of the string if not. + */ + while (*cp && isspace ((unsigned char)*cp)) { + 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) { + switch (specType) { + case Suffixes: + Suff_ClearSuffixes(); + break; + case Precious: + allPrecious = TRUE; + break; + case Ignore: + ignoreErrors = TRUE; + break; + case Silent: + beSilent = TRUE; + break; + case ExPath: + if (paths != NULL) + Lst_ForEach(paths, ParseClearPath, NULL); + Dir_SetPATH(); + break; +#ifdef POSIX + case Posix: + Var_Set("%POSIX", "1003.2", VAR_GLOBAL); + break; +#endif + default: + break; + } + } else if (specType == 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 == ExShell) { + if (!Job_ParseShell(line)) { + Parse_Error(PARSE_FATAL, "improper shell specification"); + goto out; + } + *line = '\0'; + } else if (specType == NotParallel || specType == SingleShell || + specType == DeleteOnError) { + *line = '\0'; + } + + /* + * NOW GO FOR THE SOURCES + */ + if (specType == Suffixes || specType == ExPath || + specType == Includes || specType == Libs || + specType == Null || specType == ExObjdir) + { + while (*line) { + /* + * 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. + */ + while (*cp && !isspace ((unsigned char)*cp)) { + cp++; + } + savec = *cp; + *cp = '\0'; + switch (specType) { + case Suffixes: + Suff_AddSuffix(line, &mainNode); + break; + case ExPath: + if (paths != NULL) + Lst_ForEach(paths, ParseAddDir, line); + break; + case Includes: + Suff_AddInclude(line); + break; + case Libs: + Suff_AddLib(line); + break; + case Null: + Suff_SetNull(line); + break; + case ExObjdir: + Main_SetObjdir("%s", line); + break; + default: + break; + } + *cp = savec; + if (savec != '\0') { + cp++; + } + while (*cp && isspace ((unsigned char)*cp)) { + cp++; + } + line = cp; + } + if (paths) { + Lst_Free(paths); + paths = NULL; + } + if (specType == ExPath) + Dir_SetPATH(); + } else { + assert(paths == NULL); + while (*line) { + /* + * 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 (; *cp && !isspace ((unsigned char)*cp); cp++) { + if (*cp == LPAREN && cp > line && cp[-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 (*cp == LPAREN) { + sources = Lst_Init(); + if (!Arch_ParseArchive(&line, sources, VAR_CMD)) { + Parse_Error(PARSE_FATAL, + "Error in source archive spec \"%s\"", line); + goto out; + } + + while (!Lst_IsEmpty(sources)) { + gn = Lst_Dequeue(sources); + ParseDoSrc(tOp, gn->name); + } + Lst_Free(sources); + cp = line; + } else { + if (*cp) { + *cp = '\0'; + cp += 1; + } + + ParseDoSrc(tOp, line); + } + while (*cp && isspace ((unsigned char)*cp)) { + cp++; + } + line = cp; + } + } + + if (mainNode == NULL && targets != NULL) { + /* + * 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. + */ + Lst_ForEach(targets, ParseFindMain, NULL); + } + +out: + if (paths != NULL) + Lst_Free(paths); + if (curTargs != NULL) + Lst_Free(curTargs); +} + +/*- + *--------------------------------------------------------------------- + * Parse_IsVar -- + * Return TRUE if the passed line is a variable assignment. A variable + * assignment consists of a single word followed by optional whitespace + * followed by either a += or an = operator. + * This function is used both by the Parse_File function and main when + * parsing the command-line arguments. + * + * Input: + * line the line to check + * + * Results: + * TRUE if it is. FALSE if it ain't + * + * Side Effects: + * none + *--------------------------------------------------------------------- + */ +Boolean +Parse_IsVar(char *line) +{ + Boolean wasSpace = FALSE; /* set TRUE if found a space */ + char ch; + int level = 0; +#define ISEQOPERATOR(c) \ + (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) + + /* + * Skip to variable name + */ + while (*line == ' ' || *line == '\t') + line++; + + /* Scan for one of the assignment operators outside a variable expansion */ + while ((ch = *line++) != 0) { + if (ch == '(' || ch == '{') { + level++; + continue; + } + if (ch == ')' || ch == '}') { + level--; + continue; + } + if (level != 0) + continue; + while (ch == ' ' || ch == '\t') { + ch = *line++; + wasSpace = TRUE; + } +#ifdef SUNSHCMD + if (ch == ':' && strncmp(line, "sh", 2) == 0) { + line += 2; + continue; + } +#endif + if (ch == '=') + return TRUE; + if (*line == '=' && ISEQOPERATOR(ch)) + return TRUE; + if (wasSpace) + return FALSE; + } + + return FALSE; +} + +/*- + *--------------------------------------------------------------------- + * Parse_DoVar -- + * Take the variable assignment in the passed line and do it in the + * global context. + * + * 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++ =". + * + * Input: + * line a line guaranteed to be a variable assignment. + * This reduces error checks + * ctxt Context in which to do the assignment + * + * Results: + * none + * + * Side Effects: + * the variable structure of the given variable name is altered in the + * global context. + *--------------------------------------------------------------------- + */ +void +Parse_DoVar(char *line, GNode *ctxt) +{ + char *cp; /* pointer into line */ + enum { + VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL + } type; /* Type of assignment */ + char *opc; /* ptr to operator character to + * null-terminate the variable name */ + Boolean freeCp = FALSE; /* TRUE if cp needs to be freed, + * i.e. if any variable expansion was + * performed */ + int depth; + + /* + * Skip to variable name + */ + while (*line == ' ' || *line == '\t') + line++; + + /* + * Skip to operator character, nulling out whitespace as we go + * XXX Rather than counting () and {} we should look for $ and + * then expand the variable. + */ + for (depth = 0, cp = line; depth > 0 || *cp != '='; cp++) { + if (*cp == '(' || *cp == '{') { + depth++; + continue; + } + if (*cp == ')' || *cp == '}') { + depth--; + continue; + } + if (depth == 0 && isspace ((unsigned char)*cp)) { + *cp = '\0'; + } + } + opc = cp-1; /* operator is the previous character */ + *cp++ = '\0'; /* nuke the = */ + + /* + * Check operator type + */ + switch (*opc) { + case '+': + type = VAR_APPEND; + *opc = '\0'; + break; + + case '?': + /* + * If the variable already has a value, we don't do anything. + */ + *opc = '\0'; + if (Var_Exists(line, ctxt)) { + return; + } else { + type = VAR_NORMAL; + } + break; + + case ':': + type = VAR_SUBST; + *opc = '\0'; + break; + + case '!': + type = VAR_SHELL; + *opc = '\0'; + break; + + default: +#ifdef SUNSHCMD + while (opc > line && *opc != ':') + opc--; + + if (strncmp(opc, ":sh", 3) == 0) { + type = VAR_SHELL; + *opc = '\0'; + break; + } +#endif + type = VAR_NORMAL; + break; + } + + while (isspace((unsigned char)*cp)) + cp++; + + if (DEBUG(LINT)) { + if (type != VAR_SUBST && strchr(cp, '$') != NULL) { + /* sanity check now */ + char *cp2; + + cp2 = Var_Subst(cp, ctxt, VARE_ASSIGN); + free(cp2); + } + } + + if (type == VAR_APPEND) { + Var_Append(line, cp, ctxt); + } else if (type == VAR_SUBST) { + /* + * Allow variables in the old value to be undefined, but leave their + * invocation 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(line, ctxt)) + Var_Set(line, "", ctxt); + + cp = Var_Subst(cp, ctxt, VARE_WANTRES|VARE_ASSIGN); + oldVars = oldOldVars; + freeCp = TRUE; + + Var_Set(line, cp, ctxt); + } else if (type == VAR_SHELL) { + char *res; + const char *error; + + if (strchr(cp, '$') != NULL) { + /* + * There's a dollar sign in the command, so perform variable + * expansion on the whole thing. The resulting string will need + * freeing when we're done. + */ + cp = Var_Subst(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES); + freeCp = TRUE; + } + + res = Cmd_Exec(cp, &error); + Var_Set(line, res, ctxt); + free(res); + + if (error) + Parse_Error(PARSE_WARNING, error, cp); + } else { + /* + * Normal assignment -- just do it. + */ + Var_Set(line, cp, ctxt); + } + if (strcmp(line, MAKEOVERRIDES) == 0) + Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ + else if (strcmp(line, ".CURDIR") == 0) { + /* + * Somone is being (too?) clever... + * Let's pretend they know what they are doing and + * re-initialize the 'cur' Path. + */ + Dir_InitCur(cp); + Dir_SetPATH(); + } else if (strcmp(line, MAKE_JOB_PREFIX) == 0) { + Job_SetPrefix(); + } else if (strcmp(line, MAKE_EXPORTED) == 0) { + Var_Export(cp, FALSE); + } + if (freeCp) + free(cp); +} + + +/* + * 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 || !isalnum((unsigned char)ptr[-1])) + && !isalnum((unsigned char)ptr[vals[i].len])) + return TRUE; + } + return FALSE; +} + +/*- + * ParseAddCmd -- + * Lst_ForEach function to add a command line to all targets + * + * Input: + * gnp the node to which the command is to be added + * cmd the command to add + * + * Results: + * Always 0 + * + * Side Effects: + * A new element is added to the commands list of the node, + * and the node can be marked as a submake node if the command is + * determined to be that. + */ +static int +ParseAddCmd(void *gnp, void *cmd) +{ + GNode *gn = (GNode *)gnp; + + /* Add to last (ie current) cohort for :: targets */ + if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts)) + gn = LstNode_Datum(Lst_Last(gn->cohorts)); + + /* 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 { +#ifdef notyet + /* 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, gn->lineno, PARSE_WARNING, + "using previous script for \"%s\" defined here", + gn->name); +#endif + } + return 0; +} + +/*- + *----------------------------------------------------------------------- + * ParseHasCommands -- + * Callback procedure for Parse_File when destroying the list of + * targets on the last dependency line. Marks a target as already + * having commands if it does, to keep from having shell commands + * on multiple dependency lines. + * + * Input: + * gnp Node to examine + * + * Results: + * None + * + * Side Effects: + * OP_HAS_COMMANDS may be set for the target. + * + *----------------------------------------------------------------------- + */ +static void +ParseHasCommands(void *gnp) +{ + GNode *gn = (GNode *)gnp; + if (!Lst_IsEmpty(gn->commands)) { + gn->type |= OP_HAS_COMMANDS; + } +} + +/*- + *----------------------------------------------------------------------- + * Parse_AddIncludeDir -- + * Add a directory to the path searched for included makefiles + * bracketed by double-quotes. Used by functions in main.c + * + * Input: + * dir The name of the directory to add + * + * Results: + * None. + * + * Side Effects: + * The directory is appended to the list. + * + *----------------------------------------------------------------------- + */ +void +Parse_AddIncludeDir(char *dir) +{ + (void)Dir_AddDir(parseIncPath, dir); +} + +/*- + *--------------------------------------------------------------------- + * ParseDoInclude -- + * Push to another file. + * + * The input is the line minus the `.'. A file spec is a string + * enclosed in <> or "". The former is looked for only in sysIncPath. + * The latter in . and the directories specified by -I command line + * options + * + * Results: + * None + * + * Side Effects: + * A structure is added to the includes Lst and readProc, lineno, + * fname and curFILE are altered for the new file + *--------------------------------------------------------------------- + */ + +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; + Lst 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 + */ + fullname = Dir_FindFile(file, + Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); + } + + 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); + + ParseSetIncludedFile(); + /* 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[7 + silent]; + + /* 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. + */ + file = Var_Subst(file, VAR_CMD, VARE_WANTRES); + + Parse_include_file(file, endc == '>', *line == 'd', silent); + free(file); +} + + +/*- + *--------------------------------------------------------------------- + * ParseSetIncludedFile -- + * Set the .INCLUDEDFROMFILE variable to the contents of .PARSEFILE + * and the .INCLUDEDFROMDIR variable to the contents of .PARSEDIR + * + * Results: + * None + * + * Side Effects: + * The .INCLUDEDFROMFILE variable is overwritten by the contents + * of .PARSEFILE and the .INCLUDEDFROMDIR variable is overwriten + * by the contents of .PARSEDIR + *--------------------------------------------------------------------- + */ +static void +ParseSetIncludedFile(void) +{ + const char *pf, *pd; + char *pf_freeIt, *pd_freeIt; + + pf = Var_Value(".PARSEFILE", VAR_GLOBAL, &pf_freeIt); + Var_Set(".INCLUDEDFROMFILE", pf, VAR_GLOBAL); + pd = Var_Value(".PARSEDIR", VAR_GLOBAL, &pd_freeIt); + Var_Set(".INCLUDEDFROMDIR", pd, VAR_GLOBAL); + + if (DEBUG(PARSE)) + fprintf(debug_file, "%s: ${.INCLUDEDFROMDIR} = `%s' " + "${.INCLUDEDFROMFILE} = `%s'\n", __func__, pd, pf); + + bmake_free(pf_freeIt); + bmake_free(pd_freeIt); +} +/*- + *--------------------------------------------------------------------- + * ParseSetParseFile -- + * Set the .PARSEDIR and .PARSEFILE variables to the dirname and + * basename of the given filename + * + * Results: + * None + * + * Side Effects: + * The .PARSEDIR and .PARSEFILE variables are overwritten by the + * dirname and basename of the given filename. + *--------------------------------------------------------------------- + */ +static void +ParseSetParseFile(const char *filename) +{ + char *slash, *dirname; + const char *pd, *pf; + + slash = strrchr(filename, '/'); + if (slash == NULL) { + Var_Set(".PARSEDIR", pd = curdir, VAR_GLOBAL); + Var_Set(".PARSEFILE", pf = filename, VAR_GLOBAL); + dirname = NULL; + } else { + dirname = bmake_strsedup(filename, slash); + Var_Set(".PARSEDIR", pd = dirname, VAR_GLOBAL); + Var_Set(".PARSEFILE", pf = slash + 1, VAR_GLOBAL); + } + if (DEBUG(PARSE)) + fprintf(debug_file, "%s: ${.PARSEDIR} = `%s' ${.PARSEFILE} = `%s'\n", + __func__, pd, pf); + free(dirname); +} + +/* + * Track the makefiles we read - so makefiles can + * set dependencies on them. + * Avoid adding anything more than once. + */ + +static void +ParseTrackInput(const char *name) +{ + char *fp = NULL; + + const char *old = Var_Value(MAKE_MAKEFILES, VAR_GLOBAL, &fp); + if (old) { + size_t name_len = strlen(name); + const char *ep = old + strlen(old) - name_len; + /* does it contain name? */ + for (; old != NULL; old = strchr(old, ' ')) { + if (*old == ' ') + old++; + if (old >= ep) + break; /* cannot contain name */ + if (memcmp(old, name, name_len) == 0 + && (old[name_len] == 0 || old[name_len] == ' ')) + goto cleanup; + } + } + Var_Append (MAKE_MAKEFILES, name, VAR_GLOBAL); + cleanup: + bmake_free(fp); +} + + +/*- + *--------------------------------------------------------------------- + * Parse_setInput -- + * Start Parsing from the given source + * + * Results: + * None + * + * Side Effects: + * A structure is added to the includes Lst and readProc, lineno, + * fname and curFile are altered for the new file + *--------------------------------------------------------------------- + */ +void +Parse_SetInput(const char *name, int line, int fd, + char *(*nextbuf)(void *, size_t *), void *arg) +{ + char *buf; + size_t len; + + if (name == NULL) + name = curFile->fname; + else + ParseTrackInput(name); + + if (DEBUG(PARSE)) + fprintf(debug_file, "%s: file %s, line %d, fd %d, nextbuf %p, arg %p\n", + __func__, name, line, fd, nextbuf, arg); + + if (fd == -1 && nextbuf == NULL) + /* sanity */ + return; + + if (curFile != NULL) + /* Save exiting file info */ + Lst_Prepend(includes, curFile); + + /* Allocate and fill in new structure */ + curFile = bmake_malloc(sizeof *curFile); + + /* + * 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->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->P_str = buf; + curFile->P_ptr = buf; + curFile->P_end = buf+len; + + curFile->cond_depth = Cond_save_depth(); + ParseSetParseFile(name); +} + +/*- + *----------------------------------------------------------------------- + * IsInclude -- + * Check if the line is an include directive + * + * Results: + * TRUE if it is. + * + * Side Effects: + * None + * + *----------------------------------------------------------------------- + */ +static Boolean +IsInclude(const char *line, Boolean sysv) +{ + static const char inc[] = "include"; + static const size_t inclen = sizeof(inc) - 1; + + /* 'd' is not valid for sysv */ + int o = strchr(sysv ? "s-" : "ds-", *line) != NULL; + + if (strncmp(line + o, inc, inclen) != 0) + return FALSE; + + /* Space is not mandatory for BSD .include */ + return !sysv || isspace((unsigned char)line[inclen + o]); +} + + +#ifdef SYSVINCLUDE +/*- + *----------------------------------------------------------------------- + * IsSysVInclude -- + * Check if the line is a SYSV include directive + * + * Results: + * TRUE if it is. + * + * Side Effects: + * None + * + *----------------------------------------------------------------------- + */ +static Boolean +IsSysVInclude(const char *line) +{ + const char *p; + + if (!IsInclude(line, TRUE)) + return FALSE; + + /* Avoid interpeting a dependency line as an include */ + for (p = line; (p = strchr(p, ':')) != NULL;) { + if (*++p == '\0') { + /* end of line -> dependency */ + return FALSE; + } + if (*p == ':' || isspace((unsigned char)*p)) { + /* :: operator or ': ' -> dependency */ + return FALSE; + } + } + return TRUE; +} + +/*- + *--------------------------------------------------------------------- + * ParseTraditionalInclude -- + * Push to another file. + * + * The input is the current line. The file name(s) are + * following the "include". + * + * Results: + * None + * + * Side Effects: + * A structure is added to the includes Lst and readProc, lineno, + * fname and curFILE are altered for the new file + *--------------------------------------------------------------------- + */ +static void +ParseTraditionalInclude(char *line) +{ + char *cp; /* current position in file spec */ + int done = 0; + int silent = line[0] != 'i'; + char *file = &line[silent + 7]; + char *all_files; + + if (DEBUG(PARSE)) { + fprintf(debug_file, "%s: %s\n", __func__, file); + } + + /* + * Skip over whitespace + */ + while (isspace((unsigned char)*file)) + file++; + + /* + * Substitute for any variables in the file name before trying to + * find the thing. + */ + all_files = Var_Subst(file, VAR_CMD, VARE_WANTRES); + + 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 && !isspace((unsigned char) *cp); cp++) + continue; + + if (*cp) + *cp = '\0'; + else + done = 1; + + Parse_include_file(file, FALSE, FALSE, silent); + } +out: + free(all_files); +} +#endif + +#ifdef GMAKEEXPORT +/*- + *--------------------------------------------------------------------- + * ParseGmakeExport -- + * Parse export = + * + * And set the environment with it. + * + * Results: + * None + * + * Side Effects: + * None + *--------------------------------------------------------------------- + */ +static void +ParseGmakeExport(char *line) +{ + char *variable = &line[6]; + char *value; + + if (DEBUG(PARSE)) { + fprintf(debug_file, "%s: %s\n", __func__, variable); + } + + /* + * Skip over whitespace + */ + while (isspace((unsigned char)*variable)) + 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. + */ + value = Var_Subst(value, VAR_CMD, VARE_WANTRES); + setenv(variable, value, 1); + free(value); +} +#endif + +/*- + *--------------------------------------------------------------------- + * ParseEOF -- + * 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: + * CONTINUE if there's more to do. DONE if not. + * + * Side Effects: + * The old curFILE, is closed. The includes list is shortened. + * lineno, curFILE, and fname are changed if CONTINUE is returned. + *--------------------------------------------------------------------- + */ +static int +ParseEOF(void) +{ + char *ptr; + size_t len; + + assert(curFile->nextbuf != NULL); + + doing_depend = curFile->depending; /* restore this */ + /* get next input buffer, if any */ + ptr = curFile->nextbuf(curFile->nextbuf_arg, &len); + curFile->P_ptr = ptr; + curFile->P_str = ptr; + curFile->P_end = ptr + len; + curFile->lineno = curFile->first_lineno; + if (ptr != NULL) { + /* Iterate again */ + return CONTINUE; + } + + /* 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->P_str); + free(curFile); + + if (Lst_IsEmpty(includes)) { + curFile = NULL; + /* 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 DONE; + } + + curFile = Lst_Dequeue(includes); + if (DEBUG(PARSE)) + fprintf(debug_file, "ParseEOF: returning to file %s, line %d\n", + curFile->fname, curFile->lineno); + + /* Restore the PARSEDIR/PARSEFILE variables */ + ParseSetParseFile(curFile->fname); + return CONTINUE; +} + +#define PARSE_RAW 1 +#define PARSE_SKIP 2 + +static char * +ParseGetLine(int flags, int *length) +{ + 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->P_ptr; + ptr = line; + line_end = line; + escaped = NULL; + comment = NULL; + for (;;) { + if (cf->P_end != NULL && ptr == cf->P_end) { + /* end of buffer */ + ch = 0; + break; + } + ch = *ptr; + if (ch == 0 || (ch == '\\' && ptr[1] == 0)) { + if (cf->P_end == NULL) + /* End of string (aka for loop) data */ + break; + /* see if there is more we can parse */ + while (ptr++ < cf->P_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 (!isspace((unsigned char)ch)) + /* We are not interested in trailing whitespace */ + line_end = ptr; + } + + /* Save next 'to be processed' location */ + cf->P_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) */ + *length = line_end - line; + 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) { + *length = line_end - line; + 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 && isspace((unsigned char)tp[-1])) + tp--; + + *tp = 0; + *length = tp - line; + return line; +} + +/*- + *--------------------------------------------------------------------- + * ParseReadLine -- + * Read an entire line from the input file. Called only by Parse_File. + * + * Results: + * A line w/o its newline + * + * Side Effects: + * Only those associated with reading a character + *--------------------------------------------------------------------- + */ +static char * +ParseReadLine(void) +{ + char *line; /* Result */ + int lineLength; /* Length of result */ + int lineno; /* Saved line # */ + int rval; + + for (;;) { + line = ParseGetLine(0, &lineLength); + 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_Eval(line)) { + case COND_SKIP: + /* Skip to next conditional that evaluates to COND_PARSE. */ + do { + line = ParseGetLine(PARSE_SKIP, &lineLength); + } while (line && Cond_Eval(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, &lineLength); + 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; + } +} + +/*- + *----------------------------------------------------------------------- + * ParseFinishLine -- + * Handle the end of a dependency group. + * + * Results: + * Nothing. + * + * Side Effects: + * inLine set FALSE. 'targets' list destroyed. + * + *----------------------------------------------------------------------- + */ +static void +ParseFinishLine(void) +{ + if (inLine) { + if (targets != NULL) { + Lst_ForEach(targets, Suff_EndTransform, NULL); + Lst_Destroy(targets, ParseHasCommands); + } + targets = NULL; + inLine = FALSE; + } +} + + +/*- + *--------------------------------------------------------------------- + * Parse_File -- + * Parse a file into its component parts, incorporating it into the + * current dependency graph. This is the main function and controls + * almost every other function in this module + * + * Input: + * name the name of the file being read + * fd Open file to makefile to parse + * + * Results: + * None + * + * Side Effects: + * closes fd. + * Loads. Nodes are added to the list of all targets, nodes and links + * are added to the dependency graph. etc. etc. etc. + *--------------------------------------------------------------------- + */ +void +Parse_File(const char *name, int fd) +{ + char *cp; /* pointer into the line */ + char *line; /* the line we're working on */ + struct loadedfile *lf; + + lf = loadfile(name, fd); + + inLine = FALSE; + fatals = 0; + + if (name == NULL) + name = "(stdin)"; + + Parse_SetInput(name, 0, -1, loadedfile_nextbuf, lf); + curFile->lf = lf; + + do { + for (; (line = ParseReadLine()) != NULL; ) { + if (DEBUG(PARSE)) + fprintf(debug_file, "ParseReadLine (%d): '%s'\n", + curFile->lineno, line); + 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 '.'. + */ + for (cp = line + 1; isspace((unsigned char)*cp); cp++) { + continue; + } + if (IsInclude(cp, FALSE)) { + ParseDoInclude(cp); + continue; + } + if (strncmp(cp, "undef", 5) == 0) { + char *cp2; + for (cp += 5; isspace((unsigned char) *cp); cp++) + continue; + for (cp2 = cp; !isspace((unsigned char) *cp2) && + *cp2 != '\0'; cp2++) + continue; + *cp2 = '\0'; + Var_Delete(cp, VAR_GLOBAL); + continue; + } else if (strncmp(cp, "export", 6) == 0) { + for (cp += 6; isspace((unsigned char) *cp); cp++) + continue; + Var_Export(cp, TRUE); + continue; + } else if (strncmp(cp, "unexport", 8) == 0) { + Var_UnExport(cp); + continue; + } else if (strncmp(cp, "info", 4) == 0 || + strncmp(cp, "error", 5) == 0 || + strncmp(cp, "warning", 7) == 0) { + if (ParseMessage(cp)) + continue; + } + } + + if (*line == '\t') { + /* + * If a line starts with a tab, it can only hope to be + * a creation command. + */ + cp = line + 1; + shellCommand: + for (; isspace ((unsigned char)*cp); cp++) { + continue; + } + if (*cp) { + if (!inLine) + Parse_Error(PARSE_FATAL, + "Unassociated shell command \"%s\"", + cp); + /* + * So long as it's not a blank line and we're actually + * in a dependency spec, add the command to the list of + * commands of all targets in the dependency spec + */ + if (targets) { + cp = bmake_strdup(cp); + Lst_ForEach(targets, ParseAddCmd, cp); +#ifdef CLEANUP + Lst_Append(targCmds, cp); +#endif + } + } + continue; + } + +#ifdef SYSVINCLUDE + if (IsSysVInclude(line)) { + /* + * It's an S3/S5-style "include". + */ + ParseTraditionalInclude(line); + continue; + } +#endif +#ifdef GMAKEEXPORT + if (strncmp(line, "export", 6) == 0 && + isspace((unsigned char) line[6]) && + strchr(line, ':') == NULL) { + /* + * It's a Gmake "export". + */ + ParseGmakeExport(line); + continue; + } +#endif + if (Parse_IsVar(line)) { + ParseFinishLine(); + Parse_DoVar(line, VAR_GLOBAL); + continue; + } + +#ifndef POSIX + /* + * To make life easier on novices, if the line is indented we + * first make sure the line has a dependency operator in it. + * If it doesn't have an operator and we're in a dependency + * line's script, we assume it's actually a shell command + * and add it to the current list of targets. + */ + cp = line; + if (isspace((unsigned char) line[0])) { + while (isspace((unsigned char) *cp)) + cp++; + while (*cp && (ParseIsEscaped(line, cp) || + *cp != ':' && *cp != '!')) { + cp++; + } + if (*cp == '\0') { + if (inLine) { + Parse_Error(PARSE_WARNING, + "Shell command needs a leading tab"); + goto shellCommand; + } + } + } +#endif + ParseFinishLine(); + + /* + * For some reason - probably to make the parser impossible - + * a ';' can be used to separate commands from dependencies. + * Attempt to avoid ';' inside substitution patterns. + */ + { + int level = 0; + + for (cp = line; *cp != 0; cp++) { + if (*cp == '\\' && cp[1] != 0) { + cp++; + continue; + } + if (*cp == '$' && + (cp[1] == '(' || cp[1] == '{')) { + level++; + continue; + } + if (level > 0) { + if (*cp == ')' || *cp == '}') { + level--; + continue; + } + } else if (*cp == ';') { + break; + } + } + } + if (*cp != 0) + /* Terminate the dependency list at the ';' */ + *cp++ = 0; + else + cp = NULL; + + /* + * We now know it's a dependency line so it needs to have all + * variables expanded before being parsed. Tell the variable + * module to complain if some variable is undefined... + */ + line = Var_Subst(line, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES); + + /* + * Need a non-circular list for the target nodes + */ + if (targets != NULL) + Lst_Free(targets); + + targets = Lst_Init(); + inLine = TRUE; + + ParseDoDependency(line); + free(line); + + /* If there were commands after a ';', add them now */ + if (cp != NULL) { + goto shellCommand; + } + } + /* + * Reached EOF, but it may be just EOF of an include file... + */ + } while (ParseEOF() == CONTINUE); + + if (fatals) { + (void)fflush(stdout); + (void)fprintf(stderr, + "%s: Fatal errors encountered -- cannot continue", + progname); + PrintOnError(NULL, NULL); + exit(1); + } +} + +/*- + *--------------------------------------------------------------------- + * Parse_Init -- + * initialize the parsing module + * + * Results: + * none + * + * Side Effects: + * the parseIncPath list is initialized... + *--------------------------------------------------------------------- + */ +void +Parse_Init(void) +{ + mainNode = NULL; + parseIncPath = Lst_Init(); + sysIncPath = Lst_Init(); + defIncPath = Lst_Init(); + includes = Lst_Init(); +#ifdef CLEANUP + targCmds = Lst_Init(); +#endif +} + +void +Parse_End(void) +{ +#ifdef CLEANUP + Lst_Destroy(targCmds, free); + if (targets) + Lst_Free(targets); + Lst_Destroy(defIncPath, Dir_Destroy); + Lst_Destroy(sysIncPath, Dir_Destroy); + Lst_Destroy(parseIncPath, Dir_Destroy); + Lst_Free(includes); /* Should be empty now */ +#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. + * + *----------------------------------------------------------------------- + */ +Lst +Parse_MainName(void) +{ + Lst mainList; /* result list */ + + mainList = Lst_Init(); + + 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; +} + +/*- + *----------------------------------------------------------------------- + * ParseMark -- + * Add the filename and lineno to the GNode so that we remember + * where it was first defined. + * + * Side Effects: + * None. + * + *----------------------------------------------------------------------- + */ +static void +ParseMark(GNode *gn) +{ + gn->fname = curFile->fname; + gn->lineno = curFile->lineno; +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/str.c =================================================================== --- vendor/NetBSD/bmake/20200902/str.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/str.c (revision 365363) @@ -0,0 +1,424 @@ +/* $NetBSD: str.c,v 1.64 2020/08/30 19:56:02 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: str.c,v 1.64 2020/08/30 19:56:02 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)str.c 5.8 (Berkeley) 6/1/90"; +#else +__RCSID("$NetBSD: str.c,v 1.64 2020/08/30 19:56:02 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +#include "make.h" + +/* 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 = MAX((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 = (char)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_FindSubstring -- See if a string contains a particular substring. + * + * Input: + * string String to search. + * substring Substring to find in string. + * + * Results: If string contains substring, the return value is the location of + * the first matching instance of substring in string. If string doesn't + * contain substring, the return value is NULL. Matching is done on an exact + * character-for-character basis with no wildcards or special characters. + * + * Side effects: None. + */ +char * +Str_FindSubstring(const char *string, const char *substring) +{ + const char *a, *b; + + /* + * First scan quickly through the two strings looking for a single- + * character match. When it's found, then compare the rest of the + * substring. + */ + + for (b = substring; *string != 0; string++) { + if (*string != *b) + continue; + a = string; + for (;;) { + if (*b == 0) + return UNCONST(string); + if (*a++ != *b++) + break; + } + b = substring; + } + return NULL; +} + +/* + * 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/20200902/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/20200902/strlist.c =================================================================== --- vendor/NetBSD/bmake/20200902/strlist.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/strlist.c (revision 365363) @@ -0,0 +1,91 @@ +/* $NetBSD: strlist.c,v 1.6 2020/08/25 17:37:09 rillig Exp $ */ + +/*- + * Copyright (c) 2008 - 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * 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 NetBSD Foundation 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 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_NATIVE +static char rcsid[] = "$NetBSD: strlist.c,v 1.6 2020/08/25 17:37:09 rillig Exp $"; +#else +#include +#ifndef lint +__RCSID("$NetBSD: strlist.c,v 1.6 2020/08/25 17:37:09 rillig Exp $"); +#endif /* not lint */ +#endif + +#include "make.h" +#include "strlist.h" + +void +strlist_init(strlist_t *sl) +{ + sl->sl_num = 0; + sl->sl_max = 0; + sl->sl_items = NULL; +} + +void +strlist_clean(strlist_t *sl) +{ + char *str; + int i; + + STRLIST_FOREACH(str, sl, i) + free(str); + free(sl->sl_items); + + sl->sl_num = 0; + sl->sl_max = 0; + sl->sl_items = NULL; +} + +void +strlist_add_str(strlist_t *sl, char *str, unsigned int info) +{ + unsigned int n; + strlist_item_t *items; + + if (str == NULL) + return; + + n = sl->sl_num + 1; + sl->sl_num = n; + items = sl->sl_items; + if (n >= sl->sl_max) { + items = bmake_realloc(items, (n + 7) * sizeof *sl->sl_items); + sl->sl_items = items; + sl->sl_max = n + 6; + } + items += n - 1; + items->si_str = str; + items->si_info = info; + items[1].si_str = NULL; /* STRLIST_FOREACH() terminator */ +} Property changes on: vendor/NetBSD/bmake/20200902/strlist.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/20200902/strlist.h =================================================================== --- vendor/NetBSD/bmake/20200902/strlist.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/strlist.h (revision 365363) @@ -0,0 +1,62 @@ +/* $NetBSD: strlist.h,v 1.4 2020/08/13 03:54:57 rillig Exp $ */ + +/*- + * Copyright (c) 2008 - 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * 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 NetBSD Foundation 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 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_STRLIST_H +#define MAKE_STRLIST_H + +typedef struct { + char *si_str; + unsigned int si_info; +} strlist_item_t; + +typedef struct { + unsigned int sl_num; + unsigned int sl_max; + strlist_item_t *sl_items; +} strlist_t; + +void strlist_init(strlist_t *); +void strlist_clean(strlist_t *); +void strlist_add_str(strlist_t *, char *, unsigned int); + +#define strlist_num(sl) ((sl)->sl_num) +#define strlist_str(sl, n) ((sl)->sl_items[n].si_str) +#define strlist_info(sl, n) ((sl)->sl_items[n].si_info) +#define strlist_set_info(sl, n, v) ((void)((sl)->sl_items[n].si_info = (v))) + +#define STRLIST_FOREACH(v, sl, index) \ + if ((sl)->sl_items != NULL) \ + for (index = 0; (v = strlist_str(sl, index)) != NULL; index++) + +#endif /* MAKE_STRLIST_H */ Property changes on: vendor/NetBSD/bmake/20200902/strlist.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/20200902/suff.c =================================================================== --- vendor/NetBSD/bmake/20200902/suff.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/suff.c (revision 365363) @@ -0,0 +1,2253 @@ +/* $NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; +#else +__RCSID("$NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 Cleanup 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" + +#define SUFF_DEBUG0(fmt) \ + if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt) + +#define SUFF_DEBUG1(fmt, arg1) \ + if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1) + +#define SUFF_DEBUG2(fmt, arg1, arg2) \ + if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2) + +#define SUFF_DEBUG3(fmt, arg1, arg2, arg3) \ + if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2, arg3) + +static Lst sufflist; /* Lst of suffixes */ +#ifdef CLEANUP +static Lst suffClean; /* Lst of suffixes to be cleaned */ +#endif +static Lst srclist; /* Lst of sources */ +static Lst transforms; /* Lst of transformation rules */ + +static int sNum = 0; /* Counter for assigning suffix numbers */ + +typedef enum { + 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); + +/* + * Structure describing an individual suffix. + */ +typedef struct Suff { + char *name; /* The suffix itself, such as ".c" */ + int nameLen; /* Length of the name, to avoid strlen calls */ + SuffFlags flags; /* Type of suffix */ + Lst searchPath; /* The path along which files of this suffix + * may be found */ + int sNum; /* The suffix number */ + int refCount; /* Reference count of list membership */ + Lst parents; /* Suffixes we have a transformation to */ + Lst children; /* Suffixes we have a transformation from */ + Lst ref; /* List of lists 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 + Lst cp; /* Debug; children list */ +#endif +} Src; + +/* + * A structure for passing more than one argument to the Lst-library-invoked + * function... + */ +typedef struct { + Lst l; + Src *s; +} LstSrc; + +typedef struct { + GNode **gn; + Suff *s; + Boolean r; +} GNodeSuff; + +static Suff *suffNull; /* The NULL suffix for this run */ +static Suff *emptySuff; /* The empty suffix required for POSIX + * single-suffix transformation rules */ + + +static void SuffUnRef(void *, void *); +static void SuffFree(void *); +static void SuffInsert(Lst, Suff *); +static void SuffRemove(Lst, Suff *); +static Boolean SuffParseTransform(char *, Suff **, Suff **); +static int SuffRebuildGraph(void *, void *); +static int SuffScanTargets(void *, void *); +static int SuffAddSrc(void *, void *); +static void SuffAddLevel(Lst, Src *); +static void SuffExpandChildren(LstNode, GNode *); +static void SuffExpandWildcards(LstNode, GNode *); +static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); +static void SuffFindDeps(GNode *, Lst); +static void SuffFindArchiveDeps(GNode *, Lst); +static void SuffFindNormalDeps(GNode *, Lst); +static int SuffPrintName(void *, void *); +static int SuffPrintSuff(void *, void *); +static int SuffPrintTrans(void *, void *); + + /*************** 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; +} + +typedef struct { + char *ename; /* The end of the name */ + int len; /* Length of the name */ +} SuffSuffGetSuffixArgs; + +/* See if suff is a suffix of str. str->ename should point to THE END + * of the string to check. (THE END == the null byte) + * + * Input: + * s possible suffix + * str string to examine + * + * Results: + * NULL if it ain't, pointer to character in str before suffix if + * it is. + */ +static char * +SuffSuffGetSuffix(const Suff *s, const SuffSuffGetSuffixArgs *str) +{ + char *p1; /* Pointer into suffix name */ + char *p2; /* Pointer into string being examined */ + + if (str->len < s->nameLen) + return NULL; /* this string is shorter than the suffix */ + + p1 = s->name + s->nameLen; + p2 = str->ename; + + while (p1 >= s->name && *p1 == *p2) { + p1--; + p2--; + } + + return p1 == s->name - 1 ? p2 : NULL; +} + +/* Predicate form of SuffSuffGetSuffix, for Lst_Find. */ +static Boolean +SuffSuffIsSuffix(const void *s, const void *sd) +{ + return SuffSuffGetSuffix(s, sd) != NULL; +} + +/* See if the suffix has the desired name. */ +static Boolean +SuffSuffHasName(const void *s, const void *desiredName) +{ + return strcmp(((const Suff *)s)->name, desiredName) == 0; +} + +/* See if the suffix name is a prefix of the string. Care must be taken when + * using this to search for transformations and what-not, since there could + * well be two suffixes, one of which is a prefix of the other... */ +static Boolean +SuffSuffIsPrefix(const void *s, const void *str) +{ + return SuffStrIsPrefix(((const Suff *)s)->name, str) != NULL; +} + +/* See if the graph node has the desired name. */ +static Boolean +SuffGNHasName(const void *gn, const void *desiredName) +{ + return strcmp(((const GNode *)gn)->name, desiredName) == 0; +} + + /*********** Maintenance Functions ************/ + +static void +SuffUnRef(void *lp, void *sp) +{ + Lst l = (Lst) lp; + + LstNode ln = Lst_FindDatum(l, sp); + if (ln != NULL) { + Lst_Remove(l, ln); + ((Suff *)sp)->refCount--; + } +} + +/* Free up all memory associated with the given suffix structure. */ +static void +SuffFree(void *sp) +{ + Suff *s = (Suff *)sp; + + if (s == suffNull) + suffNull = NULL; + + if (s == emptySuff) + emptySuff = NULL; + +#ifdef notdef + /* 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(Lst l, Suff *s) +{ + SuffUnRef(l, s); + if (s->refCount == 0) { + SuffUnRef(sufflist, s); + SuffFree(s); + } +} + +/* Insert the suffix into the list keeping the list ordered by suffix numbers. + * + * Input: + * l the list where in s should be inserted + * s the suffix to insert + */ +static void +SuffInsert(Lst l, Suff *s) +{ + LstNode ln; /* current element in l we're examining */ + Suff *s2 = NULL; /* the suffix descriptor in this element */ + + Lst_Open(l); + while ((ln = Lst_Next(l)) != NULL) { + s2 = LstNode_Datum(ln); + if (s2->sNum >= s->sNum) { + break; + } + } + Lst_Close(l); + + SUFF_DEBUG2("inserting %s(%d)...", s->name, s->sNum); + + if (ln == NULL) { + SUFF_DEBUG0("at end of list\n"); + Lst_Append(l, s); + s->refCount++; + Lst_Append(s->ref, l); + } else if (s2->sNum != s->sNum) { + SUFF_DEBUG2("before %s(%d)\n", s2->name, s2->sNum); + Lst_InsertBefore(l, ln, s); + s->refCount++; + Lst_Append(s->ref, l); + } else { + SUFF_DEBUG0("already there\n"); + } +} + +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_Init(); + s->children = Lst_Init(); + s->parents = Lst_Init(); + s->ref = Lst_Init(); + 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_Init(); + sNum = 0; + if (suffNull) + SuffFree(suffNull); + emptySuff = suffNull = SuffNew(""); + + Dir_Concat(suffNull->searchPath, dirSearchPath); + suffNull->flags = SUFF_NULL; +} + +/* Parse a transformation string to find its two component suffixes. + * + * Input: + * str String being parsed + * out_src Place to store source of trans. + * out_targ Place to store target of trans. + * + * Results: + * TRUE if the string is a valid transformation, FALSE otherwise. + */ +static Boolean +SuffParseTransform(char *str, Suff **out_src, Suff **out_targ) +{ + LstNode srcLn; /* element in suffix list of trans source*/ + Suff *src; /* Source of transformation */ + LstNode targLn; /* element in suffix list of trans target*/ + char *str2; /* Extra pointer (maybe target suffix) */ + LstNode singleLn; /* element in suffix list of any suffix + * that exactly matches str */ + Suff *single = NULL;/* Source of possible transformation to + * null suffix */ + + srcLn = NULL; + singleLn = 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 (;;) { + if (srcLn == NULL) { + srcLn = Lst_Find(sufflist, SuffSuffIsPrefix, str); + } else { + srcLn = Lst_FindFrom(sufflist, LstNode_Next(srcLn), + SuffSuffIsPrefix, str); + } + if (srcLn == NULL) { + /* + * Ran out of source suffixes -- no such rule + */ + if (singleLn != 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 = single; + *out_targ = suffNull; + return TRUE; + } + return FALSE; + } + src = LstNode_Datum(srcLn); + str2 = str + src->nameLen; + if (*str2 == '\0') { + single = src; + singleLn = srcLn; + } else { + targLn = Lst_Find(sufflist, SuffSuffHasName, str2); + if (targLn != NULL) { + *out_src = src; + *out_targ = LstNode_Datum(targLn); + return TRUE; + } + } + } +} + +/* Return TRUE if the given string is a transformation rule, that is, a + * concatenation of two known suffixes. */ +Boolean +Suff_IsTransform(char *str) +{ + Suff *src, *targ; + + return SuffParseTransform(str, &src, &targ); +} + +/* Add the transformation rule described by the line to the list of rules + * and place the transformation itself in the graph. + * + * The node is placed on the end of the transforms Lst and links are made + * between the two suffixes mentioned in the target name. + + * Input: + * line name of transformation to add + * + * Results: + * The node created for the transformation in the transforms list + */ +GNode * +Suff_AddTransform(char *line) +{ + GNode *gn; /* GNode of transformation rule */ + Suff *s, /* source suffix */ + *t; /* target suffix */ + LstNode ln; /* Node for existing transformation */ + Boolean ok; + + ln = Lst_Find(transforms, SuffGNHasName, line); + if (ln == NULL) { + /* + * Make a new graph node for the transformation. It will be filled in + * by the Parse module. + */ + gn = Targ_NewGN(line); + 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. + */ + gn = LstNode_Datum(ln); + Lst_Free(gn->commands); + Lst_Free(gn->children); + gn->commands = Lst_Init(); + gn->children = Lst_Init(); + } + + gn->type = OP_TRANSFORM; + + ok = SuffParseTransform(line, &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. + * This is a callback procedure for the Parse module via Lst_ForEach. + * + * If the node has no commands or children, the children and parents lists + * of the affected suffixes are altered. + * + * Input: + * gnp Node for transformation + * + * Results: + * 0, so that Lst_ForEach continues + */ +int +Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED) +{ + GNode *gn = (GNode *)gnp; + + if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts)) + gn = LstNode_Datum(Lst_Last(gn->cohorts)); + 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)) { + Lst 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); + } + + return 0; +} + +/* Called from Suff_AddSuffix via Lst_ForEach 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: + * transformp Transformation to test + * sp Suffix to rebuild + * + * Results: + * 0, so that Lst_ForEach continues + */ +static int +SuffRebuildGraph(void *transformp, void *sp) +{ + GNode *transform = (GNode *)transformp; + Suff *s = (Suff *)sp; + char *cp; + LstNode ln; + Suff *s2; + SuffSuffGetSuffixArgs sd; + + /* + * First see if it is a transformation from this suffix. + */ + cp = UNCONST(SuffStrIsPrefix(s->name, transform->name)); + if (cp != NULL) { + ln = Lst_Find(sufflist, SuffSuffHasName, cp); + if (ln != NULL) { + /* + * Found target. Link in and return, since it can't be anything + * else. + */ + s2 = LstNode_Datum(ln); + SuffInsert(s2->children, s); + SuffInsert(s->parents, s2); + return 0; + } + } + + /* + * Not from, maybe to? + */ + sd.len = strlen(transform->name); + sd.ename = transform->name + sd.len; + cp = SuffSuffGetSuffix(s, &sd); + if (cp != NULL) { + /* + * Null-terminate the source suffix in order to find it. + */ + cp[1] = '\0'; + ln = Lst_Find(sufflist, SuffSuffHasName, transform->name); + /* + * Replace the start of the target suffix + */ + cp[1] = s->name[0]; + if (ln != NULL) { + /* + * Found it -- establish the proper relationship + */ + s2 = LstNode_Datum(ln); + SuffInsert(s->children, s2); + SuffInsert(s2->parents, s); + } + } + return 0; +} + +/* Called from Suff_AddSuffix via Lst_ForEach to 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: + * 1 if a new main target has been selected, 0 otherwise. + */ +static int +SuffScanTargets(void *targetp, void *gsp) +{ + GNode *target = (GNode *)targetp; + GNodeSuff *gs = (GNodeSuff *)gsp; + Suff *s, *t; + char *ptr; + + if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) { + *gs->gn = target; + Targ_SetMain(target); + return 1; + } + + if (target->type == OP_TRANSFORM) + return 0; + + if ((ptr = strstr(target->name, gs->s->name)) == NULL || + ptr == target->name) + return 0; + + if (SuffParseTransform(target->name, &s, &t)) { + if (*gs->gn == target) { + gs->r = TRUE; + *gs->gn = NULL; + Targ_SetMain(NULL); + } + Lst_Free(target->children); + target->children = Lst_Init(); + 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 0; +} + +/* 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 **gn) +{ + Suff *s; /* new suffix descriptor */ + LstNode ln; + GNodeSuff gs; + + ln = Lst_Find(sufflist, SuffSuffHasName, name); + if (ln == NULL) { + s = SuffNew(name); + + Lst_Append(sufflist, s); + /* + * We also look at our existing targets list to see if adding + * this suffix will make one of our current targets mutate into + * a suffix rule. This is ugly, but other makes treat all targets + * that start with a . as suffix rules. + */ + gs.gn = gn; + gs.s = s; + gs.r = FALSE; + Lst_ForEach(Targ_List(), SuffScanTargets, &gs); + /* + * Look for any existing transformations from or to this suffix. + * XXX: Only do this after a Suff_ClearSuffixes? + */ + Lst_ForEach(transforms, SuffRebuildGraph, s); + } +} + +/* Return the search path for the given suffix, or NULL. */ +Lst +Suff_GetPath(char *sname) +{ + LstNode ln; + Suff *s; + + ln = Lst_Find(sufflist, SuffSuffHasName, sname); + if (ln == NULL) { + return NULL; + } else { + s = LstNode_Datum(ln); + return s->searchPath; + } +} + +/* 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) +{ + Suff *s; + LstNode ln; + char *ptr; + Lst inIncludes; /* Cumulative .INCLUDES path */ + Lst inLibs; /* Cumulative .LIBS path */ + + + inIncludes = Lst_Init(); + inLibs = Lst_Init(); + + Lst_Open(sufflist); + while ((ln = Lst_Next(sufflist)) != NULL) { + s = LstNode_Datum(ln); + if (!Lst_IsEmpty(s->searchPath)) { +#ifdef INCLUDES + if (s->flags & SUFF_INCLUDE) { + Dir_Concat(inIncludes, s->searchPath); + } +#endif /* INCLUDES */ +#ifdef LIBRARIES + if (s->flags & SUFF_LIBRARY) { + Dir_Concat(inLibs, s->searchPath); + } +#endif /* LIBRARIES */ + Dir_Concat(s->searchPath, dirSearchPath); + } else { + Lst_Destroy(s->searchPath, Dir_Destroy); + s->searchPath = Lst_Copy(dirSearchPath, Dir_CopyDir); + } + } + Lst_Close(sufflist); + + 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(char *sname) +{ + LstNode ln; + Suff *s; + + ln = Lst_Find(sufflist, SuffSuffHasName, sname); + if (ln != NULL) { + s = LstNode_Datum(ln); + s->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) +{ + LstNode ln; + Suff *s; + + ln = Lst_Find(sufflist, SuffSuffHasName, sname); + if (ln != NULL) { + s = LstNode_Datum(ln); + s->flags |= SUFF_LIBRARY; + } +} + + /********** Implicit Source Search Functions *********/ + +/* 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: + * sp suffix for which to create a Src structure + * lsp list and parent for the new Src + * + * Results: + * 0, so that Lst_ForEach continues + */ +static int +SuffAddSrc(void *sp, void *lsp) +{ + Suff *s = (Suff *)sp; + LstSrc *ls = (LstSrc *)lsp; + Src *s2; /* new Src structure */ + Src *targ; /* Target structure */ + + targ = ls->s; + + if ((s->flags & SUFF_NULL) && (*s->name != '\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... + */ + s2 = bmake_malloc(sizeof(Src)); + s2->file = bmake_strdup(targ->pref); + s2->pref = targ->pref; + s2->parent = targ; + s2->node = NULL; + s2->suff = s; + s->refCount++; + s2->children = 0; + targ->children += 1; + Lst_Append(ls->l, s2); +#ifdef DEBUG_SRC + s2->cp = Lst_Init(); + Lst_Append(targ->cp, s2); + fprintf(debug_file, "1 add %p %p to %p:", targ, s2, ls->l); + Lst_ForEach(ls->l, PrintAddr, NULL); + fprintf(debug_file, "\n"); +#endif + } + s2 = bmake_malloc(sizeof(Src)); + s2->file = str_concat2(targ->pref, s->name); + s2->pref = targ->pref; + s2->parent = targ; + s2->node = NULL; + s2->suff = s; + s->refCount++; + s2->children = 0; + targ->children += 1; + Lst_Append(ls->l, s2); +#ifdef DEBUG_SRC + s2->cp = Lst_Init(); + Lst_Append(targ->cp, s2); + fprintf(debug_file, "2 add %p %p to %p:", targ, s2, ls->l); + Lst_ForEach(ls->l, PrintAddr, NULL); + fprintf(debug_file, "\n"); +#endif + + return 0; +} + +/* 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(Lst l, Src *targ) +{ + LstSrc ls; + + ls.s = targ; + ls.l = l; + + Lst_ForEach(targ->suff->children, SuffAddSrc, &ls); +} + +/* Free the first Src in the list that doesn't have a reference count. + * Return whether a Src was removed. */ +static Boolean +SuffRemoveSrc(Lst l) +{ + LstNode ln; + Src *s; + + Lst_Open(l); + +#ifdef DEBUG_SRC + fprintf(debug_file, "cleaning %lx: ", (unsigned long) l); + Lst_ForEach(l, PrintAddr, NULL); + fprintf(debug_file, "\n"); +#endif + + while ((ln = Lst_Next(l)) != NULL) { + s = LstNode_Datum(ln); + if (s->children == 0) { + free(s->file); + if (!s->parent) + free(s->pref); + else { +#ifdef DEBUG_SRC + LstNode ln2 = Lst_FindDatum(s->parent->cp, s); + if (ln2 != NULL) + Lst_Remove(s->parent->cp, ln2); +#endif + --s->parent->children; + } +#ifdef DEBUG_SRC + fprintf(debug_file, "free: [l=%p] p=%p %d\n", l, s, s->children); + Lst_Free(s->cp); +#endif + Lst_Remove(l, ln); + free(s); + Lst_Close(l); + return TRUE; + } +#ifdef DEBUG_SRC + else { + fprintf(debug_file, "keep: [l=%p] p=%p %d: ", l, s, s->children); + Lst_ForEach(s->cp, PrintAddr, NULL); + fprintf(debug_file, "\n"); + } +#endif + } + + Lst_Close(l); + + 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(Lst srcs, Lst slst) +{ + Src *s; /* current Src */ + Src *rs; /* returned Src */ + char *ptr; + + rs = NULL; + + while (!Lst_IsEmpty(srcs)) { + s = Lst_Dequeue(srcs); + + SUFF_DEBUG1("\ttrying %s...", s->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(s->file, TARG_NOCREATE) != NULL) { +#ifdef DEBUG_SRC + fprintf(debug_file, "remove %p from %p\n", s, srcs); +#endif + rs = s; + break; + } + + if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) { + rs = s; +#ifdef DEBUG_SRC + fprintf(debug_file, "remove %p from %p\n", s, srcs); +#endif + free(ptr); + break; + } + + SUFF_DEBUG0("not there\n"); + + SuffAddLevel(srcs, s); + Lst_Append(slst, s); + } + + if (rs) { + SUFF_DEBUG0("got it\n"); + } + return rs; +} + +/* 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, Lst slst) +{ + LstNode ln; /* General-purpose list node */ + GNode *t, /* Target GNode */ + *s; /* Source GNode */ + int prefLen;/* The length of the defined prefix */ + Suff *suff; /* Suffix on matching beastie */ + Src *ret; /* Return value */ + char *cp; + + t = targ->node; + Lst_Open(t->children); + prefLen = strlen(targ->pref); + + for (;;) { + ln = Lst_Next(t->children); + if (ln == NULL) { + Lst_Close(t->children); + return NULL; + } + s = LstNode_Datum(ln); + + if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->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(s->name, '/'); + if (cp == NULL) { + cp = s->name; + } else { + cp++; + } + if (strncmp(cp, targ->pref, prefLen) != 0) + continue; + /* + * The node matches the prefix ok, see if it has a known + * suffix. + */ + ln = Lst_Find(sufflist, SuffSuffHasName, &cp[prefLen]); + if (ln == 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. + */ + suff = LstNode_Datum(ln); + + /* XXX: Can targ->suff be NULL here? */ + if (targ->suff != NULL && + Lst_FindDatum(suff->parents, targ->suff) != NULL) + break; + } + + /* + * 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 = bmake_malloc(sizeof(Src)); + ret->file = bmake_strdup(s->name); + ret->pref = targ->pref; + ret->suff = suff; + suff->refCount++; + ret->parent = targ; + ret->node = s; + ret->children = 0; + targ->children += 1; +#ifdef DEBUG_SRC + ret->cp = Lst_Init(); + fprintf(debug_file, "3 add %p %p\n", targ, ret); + Lst_Append(targ->cp, ret); +#endif + Lst_Append(slst, ret); + SUFF_DEBUG1("\tusing existing source %s\n", s->name); + Lst_Close(t->children); + return ret; +} + +/* Expand the names of any children of a given node that contain variable + * invocations 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(LstNode cln, GNode *pgn) +{ + GNode *cgn = LstNode_Datum(cln); + 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); + cp = Var_Subst(cgn->name, pgn, VARE_UNDEFERR|VARE_WANTRES); + + { + Lst members = Lst_Init(); + + 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; + for (cp = start; *cp != '\0'; cp++) { + if (*cp == ' ' || *cp == '\t') { + /* + * White-space -- terminate element, find the node, + * add it, skip any further spaces. + */ + *cp++ = '\0'; + gn = Targ_FindNode(start, TARG_CREATE); + Lst_Append(members, gn); + while (*cp == ' ' || *cp == '\t') { + cp++; + } + /* + * Adjust cp for increment at start of loop, but + * set start to first non-space. + */ + start = cp--; + } else if (*cp == '$') { + /* + * Start of a variable spec -- contact variable module + * to find the end so we can skip over it. + */ + const char *junk; + int len; + void *freeIt; + + junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES, + &len, &freeIt); + if (junk != var_Error) { + cp += len - 1; + } + + free(freeIt); + } else if (*cp == '\\' && cp[1] != '\0') { + /* + * Escaped something -- skip over it + */ + cp++; + } + } + + if (cp != start) { + /* + * Stuff left over -- add it to the list too + */ + gn = Targ_FindNode(start, TARG_CREATE); + 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(LstNode_Prev(cln), 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(LstNode cln, GNode *pgn) +{ + GNode *cgn = LstNode_Datum(cln); + GNode *gn; /* New source 8) */ + char *cp; /* Expanded value */ + Lst explist; /* List of expansions */ + + if (!Dir_HasWildcards(cgn->name)) + return; + + /* + * Expand the word along the chosen path + */ + explist = Lst_Init(); + Dir_Expand(cgn->name, Suff_FindPath(cgn), explist); + + while (!Lst_IsEmpty(explist)) { + /* + * Fetch next expansion off the list and find its GNode + */ + cp = Lst_Dequeue(explist); + + SUFF_DEBUG1("%s...", cp); + gn = Targ_FindNode(cp, TARG_CREATE); + + /* 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. + */ +Lst +Suff_FindPath(GNode* gn) +{ + Suff *suff = gn->suffix; + + if (suff == NULL) { + SuffSuffGetSuffixArgs sd; /* Search string data */ + LstNode ln; + sd.len = strlen(gn->name); + sd.ename = gn->name + sd.len; + ln = Lst_Find(sufflist, SuffSuffIsSuffix, &sd); + + SUFF_DEBUG1("Wildcard expanding \"%s\"...", gn->name); + if (ln != NULL) + suff = LstNode_Datum(ln); + /* XXX: Here we can save the suffix so we don't have to do this again */ + } + + if (suff != NULL) { + SUFF_DEBUG1("suffix is \"%s\"...", suff->name); + return suff->searchPath; + } else { + /* + * Use default search path + */ + return dirSearchPath; + } +} + +/* 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) +{ + LstNode 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 += 1; + + /* + * Locate the transformation rule itself + */ + tname = str_concat2(s->name, t->name); + ln = Lst_Find(transforms, SuffGNHasName, tname); + free(tname); + + if (ln == 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; + } + + gn = LstNode_Datum(ln); + + SUFF_DEBUG3("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); + + /* + * Record last child for expansion purposes + */ + ln = Lst_Last(tGn->children); + + /* + * 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 ? LstNode_Next(ln) : NULL; ln != NULL; ln = nln) { + nln = LstNode_Next(ln); + 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, Lst slst) +{ + char *eoarch; /* End of archive portion */ + char *eoname; /* End of member portion */ + GNode *mem; /* Node for member */ + LstNode 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_FindNode(name, TARG_CREATE); + SuffFindDeps(mem, slst); + + /* + * Create the link between the two nodes right off + */ + Lst_Append(gn->children, mem); + Lst_Append(mem->parents, gn); + gn->unmade += 1; + + /* + * Copy in the variables from the member node to this one. + */ + { + char *freeIt; + Var_Set(PREFIX, Var_Value(PREFIX, mem, &freeIt), gn); + bmake_free(freeIt); + Var_Set(TARGET, Var_Value(TARGET, mem, &freeIt), gn); + bmake_free(freeIt); + } + + 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 = Lst_First(gn->children); ln != NULL; ln = nln) { + nln = LstNode_Next(ln); + 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... + */ + SuffSuffGetSuffixArgs sd; /* Search string data */ + + /* + * Use first matching suffix... + */ + sd.len = eoarch - gn->name; + sd.ename = eoarch; + ln = Lst_Find(ms->parents, SuffSuffIsSuffix, &sd); + + if (ln != NULL) { + /* + * Got one -- apply it + */ + Suff *suff = LstNode_Datum(ln); + 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 (OP_NOP(gn->type)) { + 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; +} + +/* 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, Lst slst) +{ + char *eoname; /* End of name */ + char *sopref; /* Start of prefix */ + LstNode ln, nln; /* Next suffix node to check */ + Lst srcs; /* List of sources at which to look */ + Lst 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 */ + SuffSuffGetSuffixArgs sd; /* Search string data */ + + + sd.len = strlen(gn->name); + sd.ename = eoname = gn->name + sd.len; + + sopref = gn->name; + + /* + * Begin at the beginning... + */ + ln = Lst_First(sufflist); + srcs = Lst_Init(); + targs = Lst_Init(); + + /* + * 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)) { + + while (ln != NULL) { + /* + * Look for next possible suffix... + */ + ln = Lst_FindFrom(sufflist, ln, SuffSuffIsSuffix, &sd); + + if (ln != NULL) { + const char *eopref; + + /* + * Allocate a Src structure to which things can be transformed + */ + targ = bmake_malloc(sizeof(Src)); + targ->file = bmake_strdup(gn->name); + targ->suff = LstNode_Datum(ln); + targ->suff->refCount++; + targ->node = gn; + targ->parent = NULL; + targ->children = 0; +#ifdef DEBUG_SRC + targ->cp = Lst_Init(); +#endif + + eopref = eoname - targ->suff->nameLen; + targ->pref = bmake_strsedup(sopref, eopref); + + /* + * Add nodes from which the target can be made + */ + SuffAddLevel(srcs, targ); + + /* + * Record the target so we can nuke it + */ + Lst_Append(targs, targ); + + /* + * Search from this suffix's successor... + */ + ln = LstNode_Next(ln); + } + } + + /* + * Handle target of unknown suffix... + */ + if (Lst_IsEmpty(targs) && suffNull != NULL) { + SUFF_DEBUG1("\tNo known suffix on %s. Using .NULL suffix\n", + gn->name); + + targ = bmake_malloc(sizeof(Src)); + targ->file = bmake_strdup(gn->name); + targ->suff = suffNull; + targ->suff->refCount++; + targ->node = gn; + targ->parent = NULL; + targ->children = 0; + targ->pref = bmake_strdup(sopref); +#ifdef DEBUG_SRC + targ->cp = Lst_Init(); +#endif + + /* + * 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); + } + + /* + * 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 = LstNode_Datum(Lst_First(targs)); + } 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, gn->path ? gn->path : gn->name, 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. + */ + for (ln = Lst_First(gn->children); ln != NULL; ln = nln) { + nln = LstNode_Next(ln); + SuffExpandChildren(ln, gn); + } + + if (targ == NULL) { + SUFF_DEBUG1("\tNo valid suffix on %s\n", gn->name); + +sfnd_abort: + /* + * 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. + */ + if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) { + free(gn->path); + gn->path = Dir_FindFile(gn->name, + (targ == NULL ? dirSearchPath : + targ->suff->searchPath)); + if (gn->path != NULL) { + char *ptr; + 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. + */ + int savep = strlen(gn->path) - targ->suff->nameLen; + char savec; + + 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 { + /* + * 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); + } + } + } + + 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_FindNode(bottom->file, TARG_CREATE); + } + + 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_FindNode(targ->file, TARG_CREATE); + } + + 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, Lst 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, gn->path ? gn->path : gn->name, 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). + */ + LstNode ln; + Suff *s; + + ln = Lst_Find(sufflist, SuffSuffHasName, LIBSUFF); + if (gn->suffix) + gn->suffix->refCount--; + if (ln != NULL) { + gn->suffix = s = LstNode_Datum(ln); + 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(char *name) +{ + Suff *s; + LstNode ln; + + ln = Lst_Find(sufflist, SuffSuffHasName, name); + if (ln != NULL) { + s = LstNode_Datum(ln); + if (suffNull != NULL) { + suffNull->flags &= ~SUFF_NULL; + } + s->flags |= SUFF_NULL; + /* + * XXX: Here's where the transformation mangling would take place + */ + suffNull = s; + } else { + Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", + name); + } +} + +/* Initialize the suffixes module. */ +void +Suff_Init(void) +{ +#ifdef CLEANUP + suffClean = Lst_Init(); + sufflist = Lst_Init(); +#endif + srclist = Lst_Init(); + transforms = Lst_Init(); + + /* + * 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 int SuffPrintName(void *s, void *dummy MAKE_ATTR_UNUSED) +{ + + fprintf(debug_file, "%s ", ((Suff *)s)->name); + return 0; +} + +static int +SuffPrintSuff(void *sp, void *dummy MAKE_ATTR_UNUSED) +{ + Suff *s = (Suff *)sp; + + fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount); + + if (s->flags != 0) { + char flags_buf[SuffFlags_ToStringSize]; + + fprintf(debug_file, " (%s)", + Enum_FlagsToString(flags_buf, sizeof flags_buf, + s->flags, SuffFlags_ToStringSpecs)); + } + fputc('\n', debug_file); + fprintf(debug_file, "#\tTo: "); + Lst_ForEach(s->parents, SuffPrintName, NULL); + fputc('\n', debug_file); + fprintf(debug_file, "#\tFrom: "); + Lst_ForEach(s->children, SuffPrintName, NULL); + fputc('\n', debug_file); + fprintf(debug_file, "#\tSearch Path: "); + Dir_PrintPath(s->searchPath); + fputc('\n', debug_file); + return 0; +} + +static int +SuffPrintTrans(void *tp, void *dummy MAKE_ATTR_UNUSED) +{ + GNode *t = (GNode *)tp; + + fprintf(debug_file, "%-16s: ", t->name); + Targ_PrintType(t->type); + fputc('\n', debug_file); + Lst_ForEach(t->commands, Targ_PrintCmd, NULL); + fputc('\n', debug_file); + return 0; +} + +void +Suff_PrintAll(void) +{ + fprintf(debug_file, "#*** Suffixes:\n"); + Lst_ForEach(sufflist, SuffPrintSuff, NULL); + + fprintf(debug_file, "#*** Transformations:\n"); + Lst_ForEach(transforms, SuffPrintTrans, NULL); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/targ.c =================================================================== --- vendor/NetBSD/bmake/20200902/targ.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/targ.c (revision 365363) @@ -0,0 +1,598 @@ +/* $NetBSD: targ.c,v 1.81 2020/09/01 20:54:00 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: targ.c,v 1.81 2020/09/01 20:54:00 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: targ.c,v 1.81 2020/09/01 20:54:00 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * 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 Cleanup 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 for a given target, creating + * and storing it if it doesn't exist and the + * flags are right (TARG_CREATE) + * + * Targ_FindList Given a list of names, find nodes for all + * of them. If a name doesn't exist and the + * TARG_NOCREATE flag was given, an error message + * is printed. Else, if a name doesn't exist, + * its node is created. + * + * 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 + +#include "make.h" +#include "dir.h" + +static Lst allTargets; /* the list of all targets found so far */ +#ifdef CLEANUP +static Lst allGNs; /* List of all the GNodes */ +#endif +static Hash_Table targets; /* a hash table of same */ + +static int TargPrintOnlySrc(void *, void *); +static int TargPrintName(void *, void *); +#ifdef CLEANUP +static void TargFreeGN(void *); +#endif + +void +Targ_Init(void) +{ + allTargets = Lst_Init(); + Hash_InitTable(&targets, 191); +} + +void +Targ_End(void) +{ + Targ_Stats(); +#ifdef CLEANUP + Lst_Free(allTargets); + if (allGNs != NULL) + Lst_Destroy(allGNs, TargFreeGN); + Hash_DeleteTable(&targets); +#endif +} + +void +Targ_Stats(void) +{ + Hash_DebugStats(&targets, "targets"); +} + +/* Return the list of all targets. */ +Lst +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" + */ +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 = 0; + gn->mtime = 0; + gn->cmgn = NULL; + gn->implicitParents = Lst_Init(); + gn->cohorts = Lst_Init(); + gn->parents = Lst_Init(); + gn->children = Lst_Init(); + gn->order_pred = Lst_Init(); + gn->order_succ = Lst_Init(); + Hash_InitTable(&gn->context, 0); + gn->commands = Lst_Init(); + gn->suffix = NULL; + gn->fname = NULL; + gn->lineno = 0; + +#ifdef CLEANUP + if (allGNs == NULL) + allGNs = Lst_Init(); + Lst_Append(allGNs, gn); +#endif + + return gn; +} + +#ifdef CLEANUP +static void +TargFreeGN(void *gnp) +{ + GNode *gn = (GNode *)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); + Hash_DeleteTable(&gn->context); + Lst_Free(gn->commands); + + /* XXX: does gn->suffix need to be freed? It is reference-counted. */ + /* gn->fname points to name allocated when file was opened, don't free */ + + free(gn); +} +#endif + + +/* Find a node in the list using the given name for matching. + * If the node is created, it is added to the .ALLTARGETS list. + * + * Input: + * name the name to find + * flags flags governing events when target not found + * + * Results: + * The node in the list if it was. If it wasn't, return NULL if + * flags was TARG_NOCREATE or the newly created and initialized node + * if it was TARG_CREATE + */ +GNode * +Targ_FindNode(const char *name, int flags) +{ + GNode *gn; /* node in that element */ + Hash_Entry *he = NULL; /* New or used hash entry for node */ + Boolean isNew; /* Set TRUE if Hash_CreateEntry had to create */ + /* an entry for the node */ + + if (!(flags & (TARG_CREATE | TARG_NOHASH))) { + he = Hash_FindEntry(&targets, name); + if (he == NULL) + return NULL; + return (GNode *)Hash_GetValue(he); + } + + if (!(flags & TARG_NOHASH)) { + he = Hash_CreateEntry(&targets, name, &isNew); + if (!isNew) + return (GNode *)Hash_GetValue(he); + } + + gn = Targ_NewGN(name); + if (!(flags & TARG_NOHASH)) + Hash_SetValue(he, gn); + Var_Append(".ALLTARGETS", name, VAR_GLOBAL); + Lst_Append(allTargets, gn); + if (doing_depend) + gn->flags |= FROM_DEPEND; + return gn; +} + +/* Make a complete list of GNodes from the given list of names. + * If flags is TARG_CREATE, nodes will be created for all names in + * names which do not yet have graph nodes. If flags is TARG_NOCREATE, + * an error message will be printed for each name which can't be found. + * + * Input: + * name list of names to find + * flags flags used if no node is found for a given name + * + * Results: + * A complete list of graph nodes corresponding to all instances of all + * the names in names. + */ +Lst +Targ_FindList(Lst names, int flags) +{ + Lst nodes; /* result list */ + LstNode ln; /* name list element */ + GNode *gn; /* node in tLn */ + char *name; + + nodes = Lst_Init(); + + Lst_Open(names); + while ((ln = Lst_Next(names)) != NULL) { + name = LstNode_Datum(ln); + gn = Targ_FindNode(name, flags); + if (gn != NULL) { + /* + * Note: Lst_Append must come before the Lst_Concat so the nodes + * are added to the list in the order in which they were + * encountered in the makefile. + */ + Lst_Append(nodes, gn); + } else if (flags == TARG_NOCREATE) { + Error("\"%s\" -- target unknown.", name); + } + } + Lst_Close(names); + return nodes; +} + +/* Return true if should ignore errors when creating gn. */ +Boolean +Targ_Ignore(GNode *gn) +{ + return ignoreErrors || gn->type & OP_IGNORE; +} + +/* Return true if be silent when creating gn. */ +Boolean +Targ_Silent(GNode *gn) +{ + return 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 int +TargPrintName(void *gnp, void *pflags MAKE_ATTR_UNUSED) +{ + GNode *gn = (GNode *)gnp; + + fprintf(debug_file, "%s%s ", gn->name, gn->cohort_num); + + return 0; +} + + +int +Targ_PrintCmd(void *cmd, void *dummy MAKE_ATTR_UNUSED) +{ + fprintf(debug_file, "\t%s\n", (char *)cmd); + return 0; +} + +/* 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): fprintf(debug_file, "." #attr " "); break +#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG))fprintf(debug_file, "." #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))fprintf(debug_file, ".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"; + } +} + +/* Print the contents of a node. */ +int +Targ_PrintNode(void *gnp, void *passp) +{ + GNode *gn = (GNode *)gnp; + int pass = passp ? *(int *)passp : 0; + + fprintf(debug_file, "# %s%s", gn->name, gn->cohort_num); + GNode_FprintDetails(debug_file, ", ", gn, "\n"); + if (gn->flags == 0) + return 0; + + if (!OP_NOP(gn->type)) { + fprintf(debug_file, "#\n"); + if (gn == mainTarg) { + fprintf(debug_file, "# *** MAIN TARGET ***\n"); + } + if (pass >= 2) { + if (gn->unmade) { + fprintf(debug_file, "# %d unmade children\n", gn->unmade); + } else { + fprintf(debug_file, "# No unmade children\n"); + } + if (! (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC))) { + if (gn->mtime != 0) { + fprintf(debug_file, "# last modified %s: %s\n", + Targ_FmtTime(gn->mtime), + made_name(gn->made)); + } else if (gn->made != UNMADE) { + fprintf(debug_file, "# non-existent (maybe): %s\n", + made_name(gn->made)); + } else { + fprintf(debug_file, "# unmade\n"); + } + } + if (!Lst_IsEmpty(gn->implicitParents)) { + fprintf(debug_file, "# implicit parents: "); + Lst_ForEach(gn->implicitParents, TargPrintName, NULL); + fprintf(debug_file, "\n"); + } + } else { + if (gn->unmade) + fprintf(debug_file, "# %d unmade children\n", gn->unmade); + } + if (!Lst_IsEmpty(gn->parents)) { + fprintf(debug_file, "# parents: "); + Lst_ForEach(gn->parents, TargPrintName, NULL); + fprintf(debug_file, "\n"); + } + if (!Lst_IsEmpty(gn->order_pred)) { + fprintf(debug_file, "# order_pred: "); + Lst_ForEach(gn->order_pred, TargPrintName, NULL); + fprintf(debug_file, "\n"); + } + if (!Lst_IsEmpty(gn->order_succ)) { + fprintf(debug_file, "# order_succ: "); + Lst_ForEach(gn->order_succ, TargPrintName, NULL); + fprintf(debug_file, "\n"); + } + + fprintf(debug_file, "%-16s", gn->name); + switch (gn->type & OP_OPMASK) { + case OP_DEPENDS: + fprintf(debug_file, ": "); break; + case OP_FORCE: + fprintf(debug_file, "! "); break; + case OP_DOUBLEDEP: + fprintf(debug_file, ":: "); break; + } + Targ_PrintType(gn->type); + Lst_ForEach(gn->children, TargPrintName, NULL); + fprintf(debug_file, "\n"); + Lst_ForEach(gn->commands, Targ_PrintCmd, NULL); + fprintf(debug_file, "\n\n"); + if (gn->type & OP_DOUBLEDEP) { + Lst_ForEach(gn->cohorts, Targ_PrintNode, &pass); + } + } + return 0; +} + +/* Print only those targets that are just a source. + * The name of each file is printed, preceded by #\t. */ +static int +TargPrintOnlySrc(void *gnp, void *dummy MAKE_ATTR_UNUSED) +{ + GNode *gn = (GNode *)gnp; + if (!OP_NOP(gn->type)) + return 0; + + fprintf(debug_file, "#\t%s [%s] ", + gn->name, gn->path ? gn->path : gn->name); + Targ_PrintType(gn->type); + fprintf(debug_file, "\n"); + + return 0; +} + +/* Input: + * pass 1 => before processing + * 2 => after processing + * 3 => after processing, an error occurred + */ +void +Targ_PrintGraph(int pass) +{ + fprintf(debug_file, "#*** Input graph:\n"); + Lst_ForEach(allTargets, Targ_PrintNode, &pass); + fprintf(debug_file, "\n\n"); + fprintf(debug_file, "#\n# Files that are only sources:\n"); + Lst_ForEach(allTargets, TargPrintOnlySrc, NULL); + fprintf(debug_file, "#*** Global Variables:\n"); + Var_Dump(VAR_GLOBAL); + fprintf(debug_file, "#*** Command-line Variables:\n"); + Var_Dump(VAR_CMD); + fprintf(debug_file, "\n"); + Dir_PrintDirectories(); + fprintf(debug_file, "\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) +{ + LstNode pn, cn; + + for (pn = Lst_First(allTargets); pn != NULL; pn = LstNode_Next(pn)) { + GNode *pgn = LstNode_Datum(pn); + + if (!(pgn->type & OP_DOUBLEDEP)) + continue; + + for (cn = Lst_First(pgn->cohorts); cn != NULL; cn = LstNode_Next(cn)) { + GNode *cgn = LstNode_Datum(cn); + + cgn->type |= pgn->type & ~OP_OPMASK; + } + } +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/trace.c =================================================================== --- vendor/NetBSD/bmake/20200902/trace.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/trace.c (revision 365363) @@ -0,0 +1,116 @@ +/* $NetBSD: trace.c,v 1.15 2020/08/03 20:26:09 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. + */ + + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: trace.c,v 1.15 2020/08/03 20:26:09 rillig Exp $"; +#else +#include +#ifndef lint +__RCSID("$NetBSD: trace.c,v 1.15 2020/08/03 20:26:09 rillig Exp $"); +#endif /* not lint */ +#endif + +/*- + * 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 +#include + +#include "make.h" +#include "job.h" +#include "trace.h" + +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) { + char *dontFreeIt; + trpid = getpid(); + 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/20200902/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/20200902/unit-tests/Makefile =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/Makefile (revision 365363) @@ -0,0 +1,480 @@ +# $Id: Makefile,v 1.92 2020/09/02 18:39:29 sjg Exp $ +# +# $NetBSD: Makefile,v 1.130 2020/09/02 05:33:57 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 # broken on FreeBSD, enabled in t_make.sh +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-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+= cond1 +TESTS+= cond2 +TESTS+= counter +TESTS+= dep +TESTS+= dep-colon +TESTS+= dep-double-colon +TESTS+= dep-exclam +TESTS+= dep-none +TESTS+= dep-var +TESTS+= dep-wildcards +TESTS+= depsrc +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-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-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-literal +TESTS+= directive-for +TESTS+= directive-for-generating-endif +TESTS+= directive-if +TESTS+= directive-ifdef +TESTS+= directive-ifmake +TESTS+= directive-ifndef +TESTS+= directive-ifnmake +TESTS+= directive-info +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+= hash +TESTS+= impsrc +TESTS+= include-main +TESTS+= lint +TESTS+= make-exported +TESTS+= misc +TESTS+= moderrs +TESTS+= modmatch +TESTS+= modmisc +TESTS+= modts +TESTS+= modword +TESTS+= opt +TESTS+= opt-backwards +TESTS+= opt-chdir +TESTS+= opt-debug +TESTS+= opt-debug-g1 +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+= 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+= # suffixes # runs into an endless loop (try -dA) +TESTS+= sunshcmd +TESTS+= sysv +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+= 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-makeflags +TESTS+= varname-pwd +TESTS+= varname-vpath +TESTS+= varparse-dynamic +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 + +# 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.archive= -dA +FLAGS.counter= -dv +FLAGS.directive-ifmake= first second +FLAGS.doterror= # none +FLAGS.envfirst= -e +FLAGS.export= # none +FLAGS.lint= -dL -k +FLAGS.opt-debug-g1= -dg1 +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.vardebug= -k -dv FROM_CMDLINE= +FLAGS.varmod-match-escape= -dv +FLAGS.varname-dot-shell= -dpv +FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmline-plain' + +# Some tests need extra post-processing. +SED_CMDS.opt-debug-g1= -e 's,${.CURDIR},CURDIR,' +SED_CMDS.opt-debug-g1+= -e '/Global Variables:/,/Suffixes:/d' +SED_CMDS.sh-dots= -e 's,^.*\.\.\.:.*,,' +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-shell= -e 's, = /.*, = (details omitted),' +SED_CMDS.varname-dot-shell+= -e 's,"/[^"]*","(details omitted)",' +SED_CMDS.varname-dot-shell+= -e 's,\[/[^]]*\],[(details omitted)],' + +# Some tests need an additional round of postprocessing. +POSTPROC.counter= ${TOOL_SED} -n -e '/:RELEVANT = yes/,/:RELEVANT = no/p' +POSTPROC.deptgt-suffixes= \ + ${TOOL_SED} -n -e '/^\#\*\*\* Suffixes/,/^\#\*/p' +POSTPROC.vardebug= ${TOOL_SED} -n -e '/:RELEVANT = yes/,/:RELEVANT = no/p' +POSTPROC.varmod-match-escape= ${TOOL_SED} -n -e '/^Pattern/p' +POSTPROC.varname-dot-shell= \ + awk '/\.SHELL/ || /^ParseReadLine/' +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} + +OUTFILES= ${TESTS:=.out} + +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 + +# the tests are actually done with sub-makes. +.SUFFIXES: .mk .rawout .out +.mk.rawout: + @${_MKMSG_TEST:Uecho '# test '} ${.PREFIX} + @set -eu; \ + cd ${.OBJDIR}; \ + env -i PATH="$$PATH" ${ENV.${.TARGET:R}} \ + ${TEST_MAKE} \ + -r -C ${.CURDIR} -f ${.IMPSRC} \ + ${FLAGS.${.TARGET:R}:U-k} \ + > ${.TARGET}.tmp 2>&1 \ + && status=$$? || status=$$?; \ + echo $$status > ${.TARGET:R}.status + @mv ${.TARGET}.tmp ${.TARGET} + +# Post-process 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.${.TARGET:R}} \ + < ${.IMPSRC} > ${.TARGET}.tmp1 + @${POSTPROC.${.TARGET:R}: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} ${.PARSEDIR}/Makefile +.endif + +.-include Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/archive-suffix.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.exp (revision 365363) @@ -0,0 +1,2 @@ +`all' is up to date. +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/archive-suffix.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/archive.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/archive.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/archive.exp (revision 365363) @@ -0,0 +1,13 @@ +rm -f libprog.a +ar cru libprog.a archive.mk modmisc.mk varmisc.mk +ranlib libprog.a +ar t libprog.a +archive.mk +modmisc.mk +varmisc.mk +list-archive-wildcard: archive.mk +list-archive-wildcard: ternary.mk +depend-on-existing-member +`depend-on-nonexistent-member' is up to date. +rm -f libprog.a +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/archive.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/archive.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/archive.mk (revision 365363) @@ -0,0 +1,45 @@ +# $NetBSD: archive.mk,v 1.5 2020/08/23 17:51:24 rillig Exp $ +# +# Very basic demonstration of handling archives, based on the description +# in PSD.doc/tutorial.ms. + +ARCHIVE= libprog.${EXT.a} +FILES= archive.${EXT.mk} modmisc.${EXT.mk} varmisc.mk + +EXT.a= a +EXT.mk= mk + +MAKE_CMD= ${.MAKE} -f ${MAKEFILE} +RUN?= @set -eu; + +all: + ${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} +${ARCHIVE}: ${ARCHIVE}(${FILES}) + ar cru ${.TARGET} ${.OODATE} + ranlib ${.TARGET} + +list-archive: ${ARCHIVE} + 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) + ${RUN} printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@} + +depend-on-existing-member: ${ARCHIVE}(archive.mk) + ${RUN} echo $@ + +depend-on-nonexistent-member: ${ARCHIVE}(nonexistent.mk) + ${RUN} echo $@ + +remove-archive: + rm -f ${ARCHIVE} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cmd-interrupt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cmd-interrupt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cmd-interrupt.exp (revision 365363) @@ -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/20200902/unit-tests/cmd-interrupt.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/cmd-interrupt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cmd-interrupt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cmd-interrupt.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/cmdline.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cmdline.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cmdline.exp (revision 365363) @@ -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/20200902/unit-tests/cmdline.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cmdline.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cmdline.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/cond-cmp-numeric-eq.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-eq.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-eq.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-eq.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-eq.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-eq.mk (revision 365363) @@ -0,0 +1,53 @@ +# $NetBSD: cond-cmp-numeric-eq.mk,v 1.1 2020/08/23 13:50:17 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-cmp-numeric-ge.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ge.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ge.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ge.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ge.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ge.mk (revision 365363) @@ -0,0 +1,75 @@ +# $NetBSD: cond-cmp-numeric-ge.mk,v 1.1 2020/08/23 13:50:17 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/20200902/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/20200902/unit-tests/cond-cmp-numeric-gt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-gt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-gt.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-gt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-gt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-gt.mk (revision 365363) @@ -0,0 +1,73 @@ +# $NetBSD: cond-cmp-numeric-gt.mk,v 1.1 2020/08/23 13:50:17 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/20200902/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/20200902/unit-tests/cond-cmp-numeric-le.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-le.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-le.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-le.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-le.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-le.mk (revision 365363) @@ -0,0 +1,75 @@ +# $NetBSD: cond-cmp-numeric-le.mk,v 1.1 2020/08/23 13:50:17 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/20200902/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/20200902/unit-tests/cond-cmp-numeric-lt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-lt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-lt.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-lt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-lt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-lt.mk (revision 365363) @@ -0,0 +1,73 @@ +# $NetBSD: cond-cmp-numeric-lt.mk,v 1.1 2020/08/23 13:50:17 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/20200902/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/20200902/unit-tests/cond-cmp-numeric-ne.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ne.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ne.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ne.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ne.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric-ne.mk (revision 365363) @@ -0,0 +1,49 @@ +# $NetBSD: cond-cmp-numeric-ne.mk,v 1.1 2020/08/23 13:50:17 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/20200902/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/20200902/unit-tests/cond-cmp-numeric.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-numeric.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: cond-cmp-numeric.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for numeric comparisons in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-cmp-string.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-string.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-string.exp (revision 365363) @@ -0,0 +1,5 @@ +make: "cond-cmp-string.mk" line 18: Malformed conditional (str != str) +make: "cond-cmp-string.mk" line 37: Malformed conditional ("string" != "str""ing") +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-string.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-string.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-cmp-string.mk (revision 365363) @@ -0,0 +1,39 @@ +# $NetBSD: cond-cmp-string.mk,v 1.3 2020/08/20 18:43:19 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 Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-func-commands.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-commands.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-commands.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-func-commands.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-commands.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-commands.mk (revision 365363) @@ -0,0 +1,36 @@ +# $NetBSD: cond-func-commands.mk,v 1.3 2020/08/23 14:07:20 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/20200902/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/20200902/unit-tests/cond-func-defined.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-defined.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-defined.exp (revision 365363) @@ -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/20200902/unit-tests/cond-func-defined.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-defined.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-defined.mk (revision 365363) @@ -0,0 +1,33 @@ +# $NetBSD: cond-func-defined.mk,v 1.3 2020/08/20 17:23:43 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 after the opening parenthesis is ignored. +.if !defined( DEF) +.error +.endif + +# Horizontal whitespace 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/20200902/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/20200902/unit-tests/cond-func-empty.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-empty.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-empty.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-func-empty.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-empty.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-empty.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: cond-func-empty.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the empty() function in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-func-exists.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-exists.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-exists.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-func-exists.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-exists.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-exists.mk (revision 365363) @@ -0,0 +1,42 @@ +# $NetBSD: cond-func-exists.mk,v 1.4 2020/08/28 12:59:36 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/20200902/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/20200902/unit-tests/cond-func-make.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-make.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-func-make.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-make.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: cond-func-make.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the make() function in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-func-target.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-target.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-target.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-func-target.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func-target.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func-target.mk (revision 365363) @@ -0,0 +1,38 @@ +# $NetBSD: cond-func-target.mk,v 1.3 2020/08/23 14:07:20 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/20200902/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/20200902/unit-tests/cond-func.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func.exp (revision 365363) @@ -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/20200902/unit-tests/cond-func.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-func.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-func.mk (revision 365363) @@ -0,0 +1,63 @@ +# $NetBSD: cond-func.mk,v 1.1 2020/08/20 17:45:47 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 after the opening parenthesis is ignored. +.if !defined( DEF) +.error +.endif + +# Horizontal whitespace 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-late.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-late.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-late.exp (revision 365363) @@ -0,0 +1,4 @@ +make: Bad conditional expression ` != "no"' in != "no"?: +yes +no +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-late.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-late.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-late.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/cond-op-and.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-and.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-and.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-op-and.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-and.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-and.mk (revision 365363) @@ -0,0 +1,27 @@ +# $NetBSD: cond-op-and.mk,v 1.3 2020/08/28 14:48:37 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-op-not.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-not.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-not.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-op-not.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-not.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-not.mk (revision 365363) @@ -0,0 +1,22 @@ +# $NetBSD: cond-op-not.mk,v 1.3 2020/08/28 14:48:37 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/20200902/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/20200902/unit-tests/cond-op-or.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-or.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-or.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-op-or.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-or.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-or.mk (revision 365363) @@ -0,0 +1,27 @@ +# $NetBSD: cond-op-or.mk,v 1.3 2020/08/28 14:48:37 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-op-parentheses.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-parentheses.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-parentheses.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-op-parentheses.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op-parentheses.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op-parentheses.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/cond-op.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op.exp (revision 365363) @@ -0,0 +1,5 @@ +make: "cond-op.mk" line 45: Malformed conditional ("!word" == !word) +make: "cond-op.mk" line 57: Parsing continues until here. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-op.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-op.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-op.mk (revision 365363) @@ -0,0 +1,60 @@ +# $NetBSD: cond-op.mk,v 1.4 2020/08/28 14:07:51 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 CondGetString. +.if "!word" == !word +.error +.endif + +# Surprisingly, the ampersand and pipe are allowed in bare strings. +# That's another opportunity for writing confusing code. +# See CondGetString, which only has '!' in the list of stop characters. +.if "a&&b||c" != a&&b||c +.error +.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/20200902/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/20200902/unit-tests/cond-short.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-short.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-short.mk (revision 365363) @@ -0,0 +1,171 @@ +# $NetBSD: cond-short.mk,v 1.9 2020/08/19 22:47:09 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/20200902/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/20200902/unit-tests/cond-token-number.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-number.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-number.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-token-number.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-number.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-number.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: cond-token-number.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for number tokens in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-token-plain.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-plain.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-plain.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-token-plain.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-plain.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-plain.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: cond-token-plain.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for plain tokens (that is, string literals without quotes) +# in .if conditions. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-token-string.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-string.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-string.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond-token-string.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-string.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-string.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/cond-token-var.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-var.exp (revision 365363) @@ -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/20200902/unit-tests/cond-token-var.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-token-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-token-var.mk (revision 365363) @@ -0,0 +1,34 @@ +# $NetBSD: cond-token-var.mk,v 1.3 2020/08/20 19:43:42 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/20200902/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/20200902/unit-tests/counter.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/counter.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/counter.exp (revision 365363) @@ -0,0 +1,88 @@ +Global:RELEVANT = yes (load-time part) +Global:COUNTER = +Global:NEXT = ${COUNTER::=${COUNTER} a}${COUNTER:[#]} +Global:A = +Var_Parse: ${NEXT} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER::=${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER::...} to "" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES +Modifier part: " a" +Global:COUNTER = a +Result of ${COUNTER::=${COUNTER} a} is "" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER:[...} to " a" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Modifier part: "#" +Result of ${COUNTER:[#]} is "1" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Global:A = ${COUNTER::= a a}1 +Global:B = +Var_Parse: ${NEXT} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER::=${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER::...} to " a" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES +Modifier part: " a a" +Global:COUNTER = a a +Result of ${COUNTER::=${COUNTER} a} is "" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER:[...} to " a a" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Modifier part: "#" +Result of ${COUNTER:[#]} is "2" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Global:B = ${COUNTER::= a a a}2 +Global:C = +Var_Parse: ${NEXT} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER::=${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER::...} to " a a" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES +Modifier part: " a a a" +Global:COUNTER = a a a +Result of ${COUNTER::=${COUNTER} a} is "" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Var_Parse: ${COUNTER} a}${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${COUNTER:[#]} with VARE_WANTRES|VARE_ASSIGN +Applying ${COUNTER:[...} to " a a a" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Modifier part: "#" +Result of ${COUNTER:[#]} is "3" (eflags = VARE_WANTRES|VARE_ASSIGN, vflags = none) +Global:C = ${COUNTER::= a a a a}3 +Global:RELEVANT = no +Global:RELEVANT = yes (run-time part) +Result of ${RELEVANT::=yes (run-time part)} is "" (eflags = VARE_WANTRES, vflags = none) +Var_Parse: ${A:Q} B=${B:Q} C=${C:Q} COUNTER=${COUNTER:[#]:Q} with VARE_WANTRES +Var_Parse: ${COUNTER::= a a}1 with VARE_WANTRES +Applying ${COUNTER::...} to " a a a" (eflags = VARE_WANTRES, vflags = none) +Modifier part: " a a" +Global:COUNTER = a a +Result of ${COUNTER::= a a} is "" (eflags = VARE_WANTRES, vflags = none) +Applying ${A:Q} to "1" (eflags = VARE_WANTRES, vflags = none) +QuoteMeta: [1] +Result of ${A:Q} is "1" (eflags = VARE_WANTRES, vflags = none) +Var_Parse: ${B:Q} C=${C:Q} COUNTER=${COUNTER:[#]:Q} with VARE_WANTRES +Var_Parse: ${COUNTER::= a a a}2 with VARE_WANTRES +Applying ${COUNTER::...} to " a a" (eflags = VARE_WANTRES, vflags = none) +Modifier part: " a a a" +Global:COUNTER = a a a +Result of ${COUNTER::= a a a} is "" (eflags = VARE_WANTRES, vflags = none) +Applying ${B:Q} to "2" (eflags = VARE_WANTRES, vflags = none) +QuoteMeta: [2] +Result of ${B:Q} is "2" (eflags = VARE_WANTRES, vflags = none) +Var_Parse: ${C:Q} COUNTER=${COUNTER:[#]:Q} with VARE_WANTRES +Var_Parse: ${COUNTER::= a a a a}3 with VARE_WANTRES +Applying ${COUNTER::...} to " a a a" (eflags = VARE_WANTRES, vflags = none) +Modifier part: " a a a a" +Global:COUNTER = a a a a +Result of ${COUNTER::= a a a a} is "" (eflags = VARE_WANTRES, vflags = none) +Applying ${C:Q} to "3" (eflags = VARE_WANTRES, vflags = none) +QuoteMeta: [3] +Result of ${C:Q} is "3" (eflags = VARE_WANTRES, vflags = none) +Var_Parse: ${COUNTER:[#]:Q} with VARE_WANTRES +Applying ${COUNTER:[...} to " a a a a" (eflags = VARE_WANTRES, vflags = none) +Modifier part: "#" +Result of ${COUNTER:[#]} is "4" (eflags = VARE_WANTRES, vflags = none) +Applying ${COUNTER:Q} to "4" (eflags = VARE_WANTRES, vflags = none) +QuoteMeta: [4] +Result of ${COUNTER:Q} is "4" (eflags = VARE_WANTRES, vflags = none) +A=1 B=2 C=3 COUNTER=4 +Var_Parse: ${RELEVANT::=no} with VARE_WANTRES +Applying ${RELEVANT::...} to "yes (run-time part)" (eflags = VARE_WANTRES, vflags = none) +Modifier part: "no" +Global:RELEVANT = no +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/counter.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/counter.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/counter.mk (revision 365363) @@ -0,0 +1,31 @@ +# $NetBSD: counter.mk,v 1.1 2020/08/02 14:53:02 rillig Exp $ +# +# Demonstrates that it is not easily possible to let make count +# the number of times a variable is actually accessed. +# +# As of 2020-08-02, the counter ends up at having 4 words, even +# though the NEXT variable is only accessed 3 times. This is +# surprising. +# +# A hint to this surprising behavior is that the variables don't +# get fully expanded. For example, A does not simply contain the +# value "1" but an additional unexpanded ${COUNTER:...} before it. + +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/20200902/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/20200902/unit-tests/dep-colon.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-colon.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-colon.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-colon.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: dep-colon.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/20200902/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/20200902/unit-tests/dep-double-colon.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-double-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-double-colon.exp (revision 365363) @@ -0,0 +1,5 @@ +command 1a +command 1b +command 2a +command 2b +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-double-colon.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-double-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-double-colon.mk (revision 365363) @@ -0,0 +1,11 @@ +# $NetBSD: dep-double-colon.mk,v 1.3 2020/08/22 12:42:32 rillig Exp $ +# +# Tests for the :: operator in dependency declarations. + +all:: + @echo 'command 1a' + @echo 'command 1b' + +all:: + @echo 'command 2a' + @echo 'command 2b' Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/dep-exclam.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-exclam.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-exclam.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-exclam.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-exclam.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-exclam.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/dep-none.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-none.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-none.exp (revision 365363) @@ -0,0 +1,4 @@ +make: no target to make. + +make: stopped in unit-tests +exit status 2 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/dep-none.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-none.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-none.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-none.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/dep-var.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-var.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-var.exp (revision 365363) @@ -0,0 +1,2 @@ +def2 +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/dep-var.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-var.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-var.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-var.mk (revision 365363) @@ -0,0 +1,33 @@ +# $NetBSD: dep-var.mk,v 1.1 2020/08/22 16:51: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} + +# 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} + +UNDEF1= undef1 +DEF2= def2 + +undef1 def2: + @echo ${.TARGET} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/dep-wildcards.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-wildcards.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-wildcards.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dep-wildcards.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep-wildcards.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep-wildcards.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: dep-wildcards.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for wildcards such as *.c in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/dep.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dep.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dep.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dep.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-exec.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-exec.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-exec.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-exec.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-exec.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-exec.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-exec.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .EXEC in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-ignore.exp (revision 365363) @@ -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/20200902/unit-tests/depsrc-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-ignore.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-made.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-made.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-made.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-made.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-made.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-made.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-made.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .MADE in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-make.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-make.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-make.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-make.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-make.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .MAKE in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-meta.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-meta.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-meta.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-meta.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-meta.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-meta.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-nometa.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-nometa_cmp.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa_cmp.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa_cmp.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa_cmp.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa_cmp.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nometa_cmp.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-nopath.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nopath.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nopath.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nopath.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nopath.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-nopath.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-notmain.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-notmain.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-notmain.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-notmain.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-notmain.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-notmain.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-notmain.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .NOTMAIN in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-optional.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-optional.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-optional.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-optional.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-optional.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-optional.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-optional.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .OPTIONAL in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-phony.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-phony.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-phony.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-phony.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-phony.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-phony.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-phony.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .PHONY in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-precious.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-precious.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-precious.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-precious.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-precious.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-precious.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-recursive.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-recursive.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-recursive.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-recursive.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-recursive.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-recursive.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-recursive.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .RECURSIVE in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc-silent.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-silent.exp (revision 365363) @@ -0,0 +1,4 @@ +one +two +three +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-silent.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-silent.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-use.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-use.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-use.exp (revision 365363) @@ -0,0 +1,6 @@ +first 1 +first 2 +second 1 +second 2 +directly +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-use.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-use.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-use.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-usebefore-double-colon.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.exp (revision 365363) @@ -0,0 +1,2 @@ +double-colon early 1 +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore-double-colon.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-usebefore.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore.exp (revision 365363) @@ -0,0 +1,6 @@ +first 1 +first 2 +second 1 +second 2 +directly +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-usebefore.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/depsrc-wait.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-wait.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-wait.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc-wait.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc-wait.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc-wait.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: depsrc-wait.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special source .WAIT in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/depsrc.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/depsrc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/depsrc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/depsrc.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-begin.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-begin.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-begin.exp (revision 365363) @@ -0,0 +1,4 @@ +: parse time +: .BEGIN +: all +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-begin.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-begin.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-begin.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-default.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-default.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-default.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-default.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-default.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-default.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-delete_on_error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-delete_on_error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-delete_on_error.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-delete_on_error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-delete_on_error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-delete_on_error.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-delete_on_error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .DELETE_ON_ERROR in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/deptgt-end.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-end.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-end.exp (revision 365363) @@ -0,0 +1,4 @@ +: .BEGIN +: all +: .END +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-end.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-end.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-end.mk (revision 365363) @@ -0,0 +1,13 @@ +# $NetBSD: deptgt-end.mk,v 1.3 2020/08/29 17:34:21 rillig Exp $ +# +# Tests for the special target .END in dependency declarations, +# which is run after making the desired targets. + +.BEGIN: + : $@ + +.END: + : $@ + +all: + : $@ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/deptgt-error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-error.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-error.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-ignore.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-ignore.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-interrupt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-interrupt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-interrupt.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-interrupt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-interrupt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-interrupt.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-main.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-main.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-main.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-main.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-main.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-main.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-makeflags.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-makeflags.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-makeflags.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-makeflags.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-makeflags.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-makeflags.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-makeflags.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .MAKEFLAGS in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/deptgt-no_parallel.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-no_parallel.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-no_parallel.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-no_parallel.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-no_parallel.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-no_parallel.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-nopath.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-nopath.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-nopath.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-nopath.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-nopath.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-nopath.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-notparallel.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-notparallel.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-notparallel.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-notparallel.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-notparallel.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-notparallel.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-objdir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-objdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-objdir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-objdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-objdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-objdir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-order.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-order.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-order.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-order.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-order.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-order.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-path-suffix.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path-suffix.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path-suffix.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path-suffix.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path-suffix.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path-suffix.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-path.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-path.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-phony.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-phony.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-phony.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-phony.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-phony.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-phony.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-precious.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-precious.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-precious.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-precious.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-precious.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-precious.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-shell.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-shell.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-shell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-shell.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-silent.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-silent.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-silent.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-silent.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: deptgt-silent.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special target .SILENT in dependency declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/deptgt-stale.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-stale.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-stale.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-stale.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-stale.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-stale.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt-suffixes.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-suffixes.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-suffixes.exp (revision 365363) @@ -0,0 +1,7 @@ +#*** Suffixes: +# `.custom-null' [1] (SUFF_NULL) +# To: +# From: +# Search Path: . .. +#*** Transformations: +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt-suffixes.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt-suffixes.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt-suffixes.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/deptgt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/deptgt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/deptgt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/deptgt.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: deptgt.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for special targets like .BEGIN or .SUFFIXES in dependency +# declarations. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/dir-expand-path.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dir-expand-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dir-expand-path.exp (revision 365363) @@ -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/20200902/unit-tests/dir-expand-path.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dir-expand-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dir-expand-path.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/dir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dir.exp (revision 365363) @@ -0,0 +1,19 @@ +1 +2 +3 +4 +5 +13 +14 +15 +pre-patch +pre-configure +patch +configure +fetch +fetch-post +extract +extract-post +dup-1 +single-word +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/dir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dir.mk (revision 365363) @@ -0,0 +1,58 @@ +# $NetBSD: dir.mk,v 1.4 2020/07/31 20:16:21 rillig Exp $ +# +# Tests for dir.c. + +# Dependency lines may use braces for expansion. +all: {one,two,three} + +one: + @echo 1 +two: + @echo 2 +three: + @echo 3 + +# The braces may start in the middle of a word. +all: f{our,ive} + +four: + @echo 4 +five: + @echo 5 +six: + @echo 6 + +# But nested braces don't work. +all: {{thi,fou}r,fif}teen + +thirteen: + @echo 13 +fourteen: + @echo 14 +fifteen: + @echo 15 + +# There may be multiple brace groups side by side. +all: {pre-,}{patch,configure} + +pre-patch patch pre-configure configure: + @echo $@ + +# Empty pieces are allowed in the braces. +all: {fetch,extract}{,-post} + +fetch fetch-post extract extract-post: + @echo $@ + +# 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: + @echo $@ + +# Other than in Bash, the braces are also expanded if there is no comma. +all: {{{{{{{{{{single-word}}}}}}}}}} + +single-word: + @echo $@ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-elif.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elif.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elif.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-elif.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elif.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elif.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-elifdef.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifdef.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifdef.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-elifdef.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifdef.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifdef.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-elifmake.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifmake.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-elifmake.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifmake.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-elifndef.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifndef.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifndef.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-elifndef.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifndef.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifndef.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-elifnmake.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifnmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifnmake.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-elifnmake.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-elifnmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-elifnmake.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-else.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-else.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-else.exp (revision 365363) @@ -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/20200902/unit-tests/directive-else.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-else.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-else.mk (revision 365363) @@ -0,0 +1,32 @@ +# $NetBSD: directive-else.mk,v 1.3 2020/08/29 18:50:25 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/20200902/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/20200902/unit-tests/directive-endif.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-endif.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-endif.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-endif.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-endif.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-endif.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-error.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-error.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-export-env.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export-env.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-export-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export-env.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-export-literal.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export-literal.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export-literal.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-export-literal.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export-literal.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export-literal.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: directive-export-literal.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .export-literal directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-export.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-export.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-export.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-export.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: directive-export.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .export directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-for-generating-endif.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-for-generating-endif.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-for-generating-endif.exp (revision 365363) @@ -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/20200902/unit-tests/directive-for-generating-endif.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-for-generating-endif.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-for-generating-endif.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-for-generating-endif.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-for.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-for.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-for.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/directive-for.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-for.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-for.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-for.mk (revision 365363) @@ -0,0 +1,97 @@ +# $NetBSD: directive-for.mk,v 1.2 2020/09/02 22:58:59 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-if.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-if.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-if.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-if.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-if.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-if.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-ifdef.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifdef.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifdef.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-ifdef.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifdef.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifdef.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-ifmake.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifmake.exp (revision 365363) @@ -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/20200902/unit-tests/directive-ifmake.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifmake.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-ifndef.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifndef.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifndef.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-ifndef.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifndef.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifndef.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: directive-ifndef.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .ifndef directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-ifnmake.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifnmake.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifnmake.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-ifnmake.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-ifnmake.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-ifnmake.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: directive-ifnmake.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .ifnmake directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-info.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-info.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-info.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-info.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-info.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-info.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-undef.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-undef.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-undef.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-undef.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-undef.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-undef.mk (revision 365363) @@ -0,0 +1,17 @@ +# $NetBSD: directive-undef.mk,v 1.3 2020/08/23 19:30:13 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/20200902/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/20200902/unit-tests/directive-unexport-env.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport-env.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport-env.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive-unexport.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-unexport.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: directive-unexport.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the .unexport directive. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/directive-warning.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-warning.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-warning.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive-warning.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive-warning.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive-warning.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directive.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/directive.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directive.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directive.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/directives.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directives.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directives.exp (revision 365363) @@ -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/20200902/unit-tests/directives.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/directives.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/directives.mk (revision 365363) @@ -0,0 +1,163 @@ +# $NetBSD: directives.mk,v 1.5 2020/07/28 20:57:59 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/20200902/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/20200902/unit-tests/envfirst.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/envfirst.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/envfirst.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/envfirst.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/envfirst.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/envfirst.mk (revision 365363) @@ -0,0 +1,42 @@ +# $NetBSD: envfirst.mk,v 1.2 2020/07/27 18:57:42 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/20200902/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/20200902/unit-tests/export-all.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-all.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-all.mk (revision 365363) @@ -0,0 +1,24 @@ +# $Id: export-all.mk,v 1.1.1.3 2020/07/28 16:57:18 sjg 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/20200902/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/20200902/unit-tests/export-variants.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-variants.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-variants.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/export-variants.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/export-variants.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-variants.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-variants.mk (revision 365363) @@ -0,0 +1,40 @@ +# $NetBSD: export-variants.mk,v 1.2 2020/08/08 13:00:07 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, no variable should be exported. +.endif + +.if ${:!env | grep ^UT_ || true!} != "UT_VAR=value" +.warning At this point, some variables should be exported. +.endif + +.if ${env | grep ^UT_ || true:L:sh} != "UT_VAR=value" +.warning At this point, some variables should be exported. +.endif + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/export.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export.exp (revision 365363) @@ -0,0 +1,8 @@ +&=ampersand +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/20200902/unit-tests/export.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export.mk (revision 365363) @@ -0,0 +1,43 @@ +# $Id: export.mk,v 1.1.1.4 2020/08/08 22:34:25 sjg 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 ! +.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|PATH|PWD|SHLVL|_)=' + +all: + @env | ${FILTER_CMD} | sort Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/forloop.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/forloop.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/forloop.mk (revision 365363) @@ -0,0 +1,53 @@ +# $Id: forloop.mk,v 1.1.1.3 2020/09/02 18:35:14 sjg 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/20200902/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/20200902/unit-tests/impsrc.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/impsrc.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/impsrc.exp (revision 365363) @@ -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/20200902/unit-tests/impsrc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/impsrc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/impsrc.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/include-main.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/include-main.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/include-main.mk (revision 365363) @@ -0,0 +1,30 @@ +# $NetBSD: include-main.mk,v 1.2 2020/07/27 20:55:59 rillig Exp $ +# +# Demonstrates that the .INCLUDEDFROMFILE magic variable does 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 in reality it is the "filename in which the +# latest .include happened". See parse.c, function ParseSetIncludeFile. +# + +.if !defined(.INCLUDEDFROMFILE) +LOG+= main-before-ok +.else +. for f in ${.INCLUDEDFROMFILE} +LOG+= main-before-fail\(${f:Q}\) +. endfor +.endif + +.include "include-sub.mk" + +.if !defined(.INCLUDEDFROMFILE) +LOG+= main-after-ok +.else +. for f in ${.INCLUDEDFROMFILE} +LOG+= main-after-fail\(${f:Q}\) +. endfor +.endif + +all: + @printf '%s\n' ${LOG} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/lint.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/lint.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/lint.exp (revision 365363) @@ -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 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/lint.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/lint.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/lint.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/lint.mk (revision 365363) @@ -0,0 +1,17 @@ +# $NetBSD: lint.mk,v 1.2 2020/08/08 13:00:07 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}". + +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/20200902/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/20200902/unit-tests/make-exported.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/make-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/make-exported.exp (revision 365363) @@ -0,0 +1,3 @@ +-literal=make-exported-value +UT_VAR= +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/make-exported.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/make-exported.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/make-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/make-exported.mk (revision 365363) @@ -0,0 +1,16 @@ +# $NetBSD: make-exported.mk,v 1.1 2020/08/09 12:59:16 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 +-literal= make-exported-value +UT_VAR= ${UNEXPANDED} + +# The following behavior is probably not intended. +.MAKE.EXPORTED= -env # like .export-env +.MAKE.EXPORTED= -literal UT_VAR # like .export-literal PATH + +all: + @env | sort | grep -E '^UT_|make-exported-value' || true Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/moderrs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/moderrs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/moderrs.exp (revision 365363) @@ -0,0 +1,141 @@ +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S +VAR:S,V,v,=Thevariable +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification after complex modifier (expecting '}') for VAR +VAR:S,V,v,=Thevariable +Expect: Unfinished modifier for VAR (',' missing) +make: Unfinished modifier for VAR (',' missing) +VAR:S,V,v= +Expect: 2 errors about missing @ delimiter +make: Unfinished modifier for UNDEF ('@' missing) + +make: Unfinished modifier for UNDEF ('@' missing) + +1 2 3 +modloop-close: +make: Unclosed variable specification (expecting '}') for "UNDEF" (value "1}... 2}... 3}...") modifier @ +1}... 2}... 3}... +1}... 2}... 3}... +Expect: 2 errors about missing ] delimiter +make: Unfinished modifier for UNDEF (']' missing) + +make: Unfinished modifier for UNDEF (']' missing) + +13= +12345=ok +Expect: 2 errors about missing ! delimiter +make: Unfinished modifier for VARNAME ('!' missing) + +make: Unfinished modifier for ! ('!' missing) + +mod-subst-delimiter: +make: Missing delimiter for :S modifier + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier S +TheVariable +TheVariable +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) + +make: Unfinished modifier for VAR (',' missing) + +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier S +TheVariable +TheVariable +mod-regex-delimiter: +make: Missing delimiter for :C modifier + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unfinished modifier for VAR (',' missing) + +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier C +TheVariable +TheVariable +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) + +make: Unfinished modifier for VAR (',' missing) + +make: Unclosed variable specification (expecting '}') for "VAR" (value "TheVariable") modifier C +TheVariable +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/20200902/unit-tests/moderrs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/moderrs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/moderrs.mk (revision 365363) @@ -0,0 +1,176 @@ +# $Id: moderrs.mk,v 1.1.1.8 2020/08/26 16:40:43 sjg Exp $ +# +# various modifier error tests + +VAR=TheVariable +# incase 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: modunkn modunknV varterm vartermV modtermV modloop +all: modloop-close +all: modwords +all: modexclam +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 + +modunkn: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:Z=${VAR:Z}" + +modunknV: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:${MOD_UNKN}=${VAR:${MOD_UNKN}}" + +varterm: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:S,V,v,=${VAR:S,V,v, + +vartermV: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:${MOD_TERM},=${VAR:${MOD_S} + +modtermV: + @echo "Expect: Unfinished modifier for VAR (',' missing)" + -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" + +modloop: + @echo "Expect: 2 errors about missing @ delimiter" + @echo ${UNDEF:U1 2 3:@var} + @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. +modloop-close: + @echo $@: + @echo ${UNDEF:U1 2 3:@var@${var}}...@ + @echo ${UNDEF:U1 2 3:@var@${var}}...@} + +modwords: + @echo "Expect: 2 errors about missing ] delimiter" + @echo ${UNDEF:U1 2 3:[} + @echo ${UNDEF:U1 2 3:[#} + + # out of bounds => empty + @echo 13=${UNDEF:U1 2 3:[13]} + + # Word index out of bounds. + # + # On LP64I32, strtol returns LONG_MAX, + # which is then truncated to int (undefined behavior), + # typically resulting in -1. + # This -1 is interpreted as "the last word". + # + # On ILP32, strtol returns LONG_MAX, + # which is a large number. + # This results in a range from LONG_MAX - 1 to 3, + # which is empty. + @echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,} + +modexclam: + @echo "Expect: 2 errors about missing ! delimiter" + @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 ${!:L:!=exclam} + +mod-subst-delimiter: + @echo $@: + @echo ${VAR:S + @echo ${VAR:S, + @echo ${VAR:S,from + @echo ${VAR:S,from, + @echo ${VAR:S,from,to + @echo ${VAR:S,from,to, + @echo ${VAR:S,from,to,} + @echo 1: ${VAR:S + @echo 2: ${VAR:S, + @echo 3: ${VAR:S,from + @echo ${VAR:S,from, + @echo ${VAR:S,from,to + @echo ${VAR:S,from,to, + @echo ${VAR:S,from,to,} + +mod-regex-delimiter: + @echo $@: + @echo ${VAR:C + @echo ${VAR:C, + @echo ${VAR:C,from + @echo ${VAR:C,from, + @echo ${VAR:C,from,to + @echo ${VAR:C,from,to, + @echo ${VAR:C,from,to,} + @echo 1: ${VAR:C + @echo 2: ${VAR:C, + @echo 3: ${VAR:C,from + @echo ${VAR:C,from, + @echo ${VAR:C,from,to + @echo ${VAR:C,from,to, + @echo ${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 :C modifier would have to be chosen wisely. +mod-regex-undefined-subexpression: + @echo $@: + @echo ${FIB:C,1(.*),one\1,} # all ok + @echo ${FIB:C,1(.*)|2(.*),(\1)+(\2),:Q} # no match for subexpression + +mod-ts-parse: + @echo $@: + @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: + @echo $@: + @echo ${FIB:t + @echo ${FIB:txy} + @echo ${FIB:t} + @echo ${FIB:t:M*} + +mod-ifelse-parse: + @echo $@: + @echo ${FIB:? + @echo ${FIB:?then + @echo ${FIB:?then: + @echo ${FIB:?then:else + @echo ${FIB:?then:else} + +mod-remember-parse: + @echo $@: + @echo ${FIB:_} # ok + @echo ${FIB:__} # modifier name too long + +mod-sysv-parse: + @echo $@: + @echo ${FIB:3 + @echo ${FIB:3= + @echo ${FIB:3=x3 + @echo ${FIB:3=x3} # ok Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/modmatch.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modmatch.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modmatch.exp (revision 365363) @@ -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/20200902/unit-tests/modmatch.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modmatch.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modmatch.mk (revision 365363) @@ -0,0 +1,30 @@ +# $NetBSD: modmatch.mk,v 1.8 2020/08/16 20:03:53 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/20200902/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/20200902/unit-tests/modmisc.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modmisc.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modmisc.exp (revision 365363) @@ -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/20200902/unit-tests/modmisc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modmisc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modmisc.mk (revision 365363) @@ -0,0 +1,92 @@ +# $Id: modmisc.mk,v 1.1.1.15 2020/08/23 15:52:08 sjg 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/20200902/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/20200902/unit-tests/modts.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modts.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modts.exp (revision 365363) @@ -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/20200902/unit-tests/modts.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modts.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modts.mk (revision 365363) @@ -0,0 +1,47 @@ + +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/20200902/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/20200902/unit-tests/opt-backwards.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-backwards.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-backwards.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-backwards.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-backwards.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-backwards.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-chdir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-chdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-chdir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-chdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-chdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-chdir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-debug-g1.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.exp (revision 365363) @@ -0,0 +1,15 @@ +#*** Input graph: +# all, made UNMADE, type OP_DEPENDS, 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-target-no-sources, made UNMADE, type OP_DEPENDS, flags none + + +# +# Files that are only sources: +# unmade-sources [unmade-sources] +#*** Transformations: +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.mk (revision 365363) @@ -0,0 +1,19 @@ +# $NetBSD: opt-debug-g1.mk,v 1.1 2020/08/27 19:00:17 rillig Exp $ +# +# Tests for the -dg1 command line option, which prints the input +# graph before making anything. + +all: made-target made-target-no-sources + +made-target: made-source + +made-source: + +made-target-no-sources: + +unmade-target: unmade-sources + +unmade-target-no-sources: + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/opt-debug-g1.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/20200902/unit-tests/opt-debug.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-debug.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-debug.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-debug.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-debug.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-debug.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: opt-debug.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/20200902/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/20200902/unit-tests/opt-define.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-define.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-define.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-define.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-define.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-define.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-env.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-env.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-env.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-file.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-file.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-file.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-file.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-file.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-file.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-ignore.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-ignore.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-ignore.exp (revision 365363) @@ -0,0 +1,12 @@ +dependency 1 +dependency 2 +dependency 3 +other 1 +other 2 +main 1 +main 2 +*** Error code 1 (ignored) +*** Error code 7 (ignored) +*** Error code 1 (ignored) +*** Error code 1 (ignored) +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-ignore.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-ignore.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-ignore.mk (revision 365363) @@ -0,0 +1,30 @@ +# $NetBSD: opt-ignore.mk,v 1.3 2020/08/23 14:28:04 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? + +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/20200902/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/20200902/unit-tests/opt-include-dir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-include-dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-include-dir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-include-dir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-include-dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-include-dir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-jobs-internal.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs-internal.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs-internal.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs-internal.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs-internal.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs-internal.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-jobs.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-keep-going.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-keep-going.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-keep-going.exp (revision 365363) @@ -0,0 +1,6 @@ +dependency 1 +other 1 +*** Error code 1 (continuing) +*** Error code 1 (continuing) +`all' not remade because of errors. +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-keep-going.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-keep-going.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-keep-going.mk (revision 365363) @@ -0,0 +1,24 @@ +# $NetBSD: opt-keep-going.mk,v 1.3 2020/08/23 14:28:04 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. + +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/20200902/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/20200902/unit-tests/opt-m-include-dir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-m-include-dir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-m-include-dir.exp (revision 365363) @@ -0,0 +1,2 @@ +ok +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-m-include-dir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-m-include-dir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-m-include-dir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-no-action-at-all.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action-at-all.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action-at-all.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action-at-all.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action-at-all.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action-at-all.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-no-action.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action.exp (revision 365363) @@ -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/20200902/unit-tests/opt-no-action.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-no-action.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-query.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-query.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-query.exp (revision 365363) @@ -0,0 +1,2 @@ +command during parsing +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-query.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-query.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-query.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-raw.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-raw.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-raw.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-raw.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-raw.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-raw.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-silent.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-silent.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-silent.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-silent.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-silent.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-silent.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-touch.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-touch.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-touch.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-touch.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-touch.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-touch.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-tracefile.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-tracefile.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-tracefile.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-tracefile.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-tracefile.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-tracefile.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-var-expanded.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-var-expanded.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-var-expanded.exp (revision 365363) @@ -0,0 +1,3 @@ +other value $$ +value +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-var-expanded.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-var-expanded.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-var-expanded.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-var-literal.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-var-literal.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-var-literal.exp (revision 365363) @@ -0,0 +1,3 @@ +other ${VALUE} $$$$ +value +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-var-literal.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-var-literal.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-var-literal.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-warnings-as-errors.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-warnings-as-errors.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-warnings-as-errors.exp (revision 365363) @@ -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/20200902/unit-tests/opt-warnings-as-errors.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-warnings-as-errors.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-warnings-as-errors.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-where-am-i.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-where-am-i.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-where-am-i.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-where-am-i.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-where-am-i.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-where-am-i.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt-x-reduce-exported.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-x-reduce-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-x-reduce-exported.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt-x-reduce-exported.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt-x-reduce-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt-x-reduce-exported.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/opt.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/opt.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/opt.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/opt.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/phony-end.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/phony-end.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/phony-end.exp (revision 365363) @@ -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/20200902/unit-tests/posix1.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/posix1.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/posix1.mk (revision 365363) @@ -0,0 +1,186 @@ +# $NetBSD: posix1.mk,v 1.4 2020/08/10 18:19:58 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/20200902/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/20200902/unit-tests/recursive.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/recursive.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/recursive.exp (revision 365363) @@ -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/20200902/unit-tests/recursive.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/recursive.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/recursive.mk (revision 365363) @@ -0,0 +1,37 @@ +# $NetBSD: recursive.mk,v 1.2 2020/08/06 05:52:45 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/20200902/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/20200902/unit-tests/sh-dots.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.exp (revision 365363) @@ -0,0 +1,15 @@ +first first +hidden hidden +make: exec(...) failed (No such file or directory) +hidden delayed hidden +repeated repeated +commented commented +*** Error code 1 (ignored) +... # Run the below commands later + +commented delayed commented +first delayed first +repeated delayed repeated +repeated delayed twice repeated +*** Error code 127 (ignored) +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-dots.mk (revision 365363) @@ -0,0 +1,37 @@ +# $NetBSD: sh-dots.mk,v 1.1 2020/08/22 11:27:02 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. + +all: first hidden repeated commented + +# 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 "..." 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/20200902/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/20200902/unit-tests/sh-jobs-error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs-error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs-error.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs-error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs-error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs-error.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-jobs.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-leading-at.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-at.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-at.exp (revision 365363) @@ -0,0 +1,5 @@ +ok +space after @ +echo 'echoed' +echoed +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-at.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-at.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-at.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-leading-hyphen.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-hyphen.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-hyphen.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-hyphen.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-hyphen.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-hyphen.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-leading-plus.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-plus.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-plus.exp (revision 365363) @@ -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/20200902/unit-tests/sh-leading-plus.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-plus.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-leading-plus.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-meta-chars.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-meta-chars.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-meta-chars.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-meta-chars.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-meta-chars.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-meta-chars.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-multi-line.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-multi-line.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-multi-line.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-multi-line.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-multi-line.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-multi-line.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh-single-line.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-single-line.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-single-line.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh-single-line.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh-single-line.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh-single-line.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sh.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sh.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sh.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sh.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/sysv.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sysv.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sysv.exp (revision 365363) @@ -0,0 +1,15 @@ +FOOBAR = +FOOBAR = foobar fubar +fun +fun +fun +In the Sun +acme +aam.d +sam.c +a%.c +asam.c.c +asam.c +a.c.c + +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/sysv.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/sysv.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/sysv.mk (revision 365363) @@ -0,0 +1,43 @@ +# $Id: sysv.mk,v 1.9 2020/08/23 16:08:32 sjg Exp $ + +all: foo fun sam bla + +FOO ?= +FOOBAR = ${FOO:=bar} + +_this := ${.PARSEDIR}/${.PARSEFILE} + +B = /b +S = / +FUN = ${B}${S}fun +SUN = the Sun + +# we expect nothing when FOO is empty +foo: + @echo FOOBAR = ${FOOBAR} +.if empty(FOO) + @FOO="foo fu" ${.MAKE} -f ${_this} foo +.endif + +fun: + @echo ${FUN:T} + @echo ${FUN:${B}${S}fun=fun} + @echo ${FUN:${B}${S}%=%} + @echo ${In:L:%=% ${SUN}} + + +SAM=sam.c + +sam: + @echo ${SAM:s%.c=acme} + @echo ${SAM:s%.c=a%.d} + @echo ${SAM:s.c=a%.d} + @echo ${SAM:sam.c=a%.c} + @echo ${SAM:%=a%.c} + @echo ${SAM:%.c=a%.c} + @echo ${SAM:sam%=a%.c} + +BLA= + +bla: + @echo $(BLA:%=foo/%x) Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/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/20200902/unit-tests/unexport-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/unexport-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/unexport-env.mk (revision 365363) @@ -0,0 +1,15 @@ +# $Id: unexport-env.mk,v 1.1.1.2 2020/07/28 16:57:18 sjg 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/20200902/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/20200902/unit-tests/unexport.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/unexport.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/unexport.mk (revision 365363) @@ -0,0 +1,19 @@ +# $Id: unexport.mk,v 1.1.1.3 2020/08/08 22:34:25 sjg 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/20200902/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/20200902/unit-tests/use-inference.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/use-inference.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/use-inference.exp (revision 365363) @@ -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/20200902/unit-tests/use-inference.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/use-inference.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/use-inference.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/var-class-cmdline.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-cmdline.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-cmdline.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-class-cmdline.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-cmdline.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-cmdline.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/var-class-env.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-env.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-class-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-env.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/var-class-global.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-global.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-global.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-class-global.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-global.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-global.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/var-class-local-legacy.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-local-legacy.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-local-legacy.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-class-local-legacy.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-class-local-legacy.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-class-local-legacy.mk (revision 365363) @@ -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 ${&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/20200902/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/20200902/unit-tests/var-op-default.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-default.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-default.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-op-default.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-default.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-default.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: var-op-default.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the ?= variable assignment operator, which only assigns +# if the variable is still undefined. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/var-op-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/20200902/unit-tests/var-op-expand.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-expand.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-expand.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-op-expand.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-expand.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-expand.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: var-op-expand.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the := variable assignment operator, which expands its +# right-hand side. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/var-op-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/20200902/unit-tests/var-op-shell.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-shell.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-op-shell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op-shell.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: var-op-shell.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the != variable assignment operator, which runs its right-hand +# side through the shell. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/var-op-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/20200902/unit-tests/var-op.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/var-op.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/var-op.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/var-op.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: var-op.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the variable assignment operators. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/var-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/20200902/unit-tests/vardebug.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/vardebug.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/vardebug.exp (revision 365363) @@ -0,0 +1,80 @@ +Global:RELEVANT = yes +Global:VAR = added +Global:VAR = overwritten +Global:delete VAR +Global:delete VAR (not found) +Var_Parse: ${:U} with VARE_WANTRES +Applying ${:U} to "" (eflags = VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:U} is "" (eflags = VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Var_Set("${:U}", "empty name", ...) name expands to empty string - ignored +Var_Parse: ${:U} with VARE_WANTRES +Applying ${:U} to "" (eflags = VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:U} is "" (eflags = VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +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" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = 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" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Var_Parse: ${VAR:N[2]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:N...} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = 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" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Var_Parse: ${VAR:S,2,two,} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:S...} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = 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" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Var_Parse: ${VAR:Q} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:Q} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +QuoteMeta: [1\ 2\ 3] +Result of ${VAR:Q} is "1\ 2\ 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Var_Parse: ${VAR:tu:tl:Q} with VARE_UNDEFERR|VARE_WANTRES +Applying ${VAR:t...} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Result of ${VAR:tu} is "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Applying ${VAR:t...} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Result of ${VAR:tl} is "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Applying ${VAR:Q} to "1 2 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +QuoteMeta: [1\ 2\ 3] +Result of ${VAR:Q} is "1\ 2\ 3" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = none) +Var_Parse: ${:Uvalue:${:UM*e}:Mvalu[e]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:Uvalue} is "value" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Var_Parse: ${:UM*e}:Mvalu[e]} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:UM*e} is "M*e" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Indirect modifier "M*e" from "${:UM*e}" +Applying ${:M...} to "value" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Pattern[] for [value] is [*e] +ModifyWords: split "value" into 1 words +VarMatch [value] [*e] +Result of ${:M*e} is "value" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Applying ${:M...} to "value" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Pattern[] for [value] is [valu[e]] +ModifyWords: split "value" into 1 words +VarMatch [value] [valu[e]] +Result of ${:Mvalu[e]} is "value" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Var_Parse: ${:UVAR} with VARE_WANTRES +Applying ${:U...} to "" (eflags = VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:UVAR} is "VAR" (eflags = VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Global:delete VAR +Var_Parse: ${:Uvariable:unknown} with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK) +Result of ${:Uvariable} is "variable" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +Applying ${:u...} to "variable" (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +make: Unknown modifier 'u' +Result of ${:unknown} is error (eflags = VARE_UNDEFERR|VARE_WANTRES, vflags = VAR_JUNK|VAR_KEEP) +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:RELEVANT = no +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/vardebug.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/vardebug.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/vardebug.mk (revision 365363) @@ -0,0 +1,59 @@ +# $NetBSD: vardebug.mk,v 1.3 2020/08/08 14:28:46 rillig Exp $ +# +# Demonstrates the debugging output for var.c. + +RELEVANT= yes + +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]} # VarMatch +.endif +.if ${VAR:N[2]} # VarNoMatch (no debug output) +.endif + +.if ${VAR:S,2,two,} # VarGetPattern +.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 + +RELEVANT= no + +all: + @: Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varfind.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varfind.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varfind.exp (revision 365363) @@ -0,0 +1,15 @@ +VarFind-aliases.to: long explicit-dependency VarFind-aliases.from +VarFind-aliases.to: abbr explicit-dependency VarFind-aliases.from +VarFind-aliases.to: long +VarFind-aliases.to: abbr +VarFind-aliases.to: long VarFind-aliases.from +VarFind-aliases.to: abbr VarFind-aliases.from +VarFind-aliases.to: long +VarFind-aliases.to: abbr +VarFind-aliases.to: long explicit-dependency VarFind-aliases.from +VarFind-aliases.to: abbr explicit-dependency VarFind-aliases.from +VarFind-aliases.to: long VarFind-aliases +VarFind-aliases.to: abbr VarFind-aliases +VarFind-aliases.to: long VarFind-aliases.to +VarFind-aliases.to: abbr VarFind-aliases.to +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varfind.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varfind.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varfind.mk (revision 365363) @@ -0,0 +1,31 @@ +# $NetBSD: varfind.mk,v 1.1 2020/07/25 21:19:29 rillig Exp $ +# +# Demonstrates variable name aliases in VarFind. + +all: VarFind-aliases.to + +.SUFFIXES: .from .to + +VarFind-aliases.from: + @: do nothing + +VarFind-aliases.to: explicit-dependency + +explicit-dependency: + @: do nothing + +.from.to: + @echo $@: long ${.ALLSRC:Q} + @echo $@: abbr ${>: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/20200902/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/20200902/unit-tests/varmisc.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmisc.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmisc.exp (revision 365363) @@ -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/20200902/unit-tests/varmisc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmisc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmisc.mk (revision 365363) @@ -0,0 +1,227 @@ +# $Id: varmisc.mk,v 1.19 2020/08/31 16:28:10 sjg 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/20200902/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/20200902/unit-tests/varmod-assign.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-assign.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-assign.exp (revision 365363) @@ -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 +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/20200902/unit-tests/varmod-assign.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-assign.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-assign.mk (revision 365363) @@ -0,0 +1,81 @@ +# $NetBSD: varmod-assign.mk,v 1.6 2020/08/25 21:16:53 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 as a "bad modifier". + @echo ${::=value} + @echo $@: ${:Uvalue::=overwritten} + + # The :L modifier sets the variable's value to its name. + # Since the name is still "VAR", 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} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-defined.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-defined.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-defined.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-defined.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-defined.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-defined.mk (revision 365363) @@ -0,0 +1,28 @@ +# $NetBSD: varmod-defined.mk,v 1.3 2020/08/25 21:58: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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-edge.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-edge.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-edge.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-edge.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-edge.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-edge.mk (revision 365363) @@ -0,0 +1,173 @@ +# $NetBSD: varmod-edge.mk,v 1.12 2020/08/08 13:29:09 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/20200902/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/20200902/unit-tests/varmod-exclam-shell.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-exclam-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-exclam-shell.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-exclam-shell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-exclam-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-exclam-shell.mk (revision 365363) @@ -0,0 +1,28 @@ +# $NetBSD: varmod-exclam-shell.mk,v 1.2 2020/08/16 12:48:55 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/20200902/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/20200902/unit-tests/varmod-extension.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-extension.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-extension.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-extension.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-extension.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-extension.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-gmtime.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-gmtime.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-gmtime.exp (revision 365363) @@ -0,0 +1,9 @@ +mod-gmtime: +%Y +2020 +%Y +%Y +mod-gmtime-indirect: +make: Unknown modifier '1' + +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-gmtime.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-gmtime.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-gmtime.mk (revision 365363) @@ -0,0 +1,35 @@ +# $NetBSD: varmod-gmtime.mk,v 1.2 2020/08/16 12:48:55 rillig Exp $ +# +# Tests for the :gmtime variable modifier, which formats a timestamp +# using strftime(3). + +all: mod-gmtime +all: mod-gmtime-indirect + +mod-gmtime: + @echo $@: + @echo ${%Y:L:gmtim=1593536400} # modifier name too short + @echo ${%Y:L:gmtime=1593536400} # 2020-07-01T00:00:00Z + @echo ${%Y:L:gmtimer=1593536400} # modifier name too long + @echo ${%Y:L:gm=gm:M*} + +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}} + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-hash.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-hash.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-hash.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-hash.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-hash.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-hash.mk (revision 365363) @@ -0,0 +1,10 @@ +# $NetBSD: varmod-hash.mk,v 1.3 2020/08/23 15:13:21 rillig Exp $ +# +# Tests for the :hash variable modifier. + +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/20200902/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/20200902/unit-tests/varmod-head.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-head.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-head.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-head.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-head.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-head.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-ifelse.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-ifelse.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-ifelse.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-ifelse.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-ifelse.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-ifelse.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-ifelse.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the ${cond:?then:else} variable modifier, which evaluates either +# the then-expression or the else-expression, depending on the condition. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-l-name-to-value.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-l-name-to-value.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-l-name-to-value.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-l-name-to-value.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-l-name-to-value.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-l-name-to-value.mk (revision 365363) @@ -0,0 +1,31 @@ +# $NetBSD: varmod-l-name-to-value.mk,v 1.3 2020/08/25 22:25:05 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-localtime.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-localtime.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-localtime.exp (revision 365363) @@ -0,0 +1,4 @@ +%Y +2020 +%Y +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-localtime.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-localtime.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-localtime.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-localtime.mk,v 1.3 2020/08/23 15:13:21 rillig Exp $ +# +# Tests for the :localtime variable modifier, which returns the given time, +# formatted as a local timestamp. + +all: + @echo ${%Y:L:localtim=1593536400} # modifier name too short + @echo ${%Y:L:localtime=1593536400} # 2020-07-01T00:00:00Z + @echo ${%Y:L:localtimer=1593536400} # modifier name too long Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-loop.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-loop.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-loop.exp (revision 365363) @@ -0,0 +1,16 @@ +:+one+ +two+ +three+: +:x1y x2y x3y: +:x1y x2y x3y: +:mod-loop-varname: :x1y x2y x3y: :: +:x1y x2y x3y: +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/20200902/unit-tests/varmod-loop.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-loop.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-loop.mk (revision 365363) @@ -0,0 +1,63 @@ +# $NetBSD: varmod-loop.mk,v 1.2 2020/08/16 12:30:45 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 :@ 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}: Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-match-escape.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.exp (revision 365363) @@ -0,0 +1,3 @@ +Pattern[SPECIALS] for [\: : \\ * \*] is [\:] +Pattern[SPECIALS] for [\: : \\ * \*] is [:] +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-match-escape.mk (revision 365363) @@ -0,0 +1,20 @@ +# $NetBSD: varmod-match-escape.mk,v 1.1 2020/08/16 20:03:53 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. +SPECIALS= \: : \\ * \* +RELEVANT= yes +.if ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} +.warning unexpected +.endif +RELEVANT= no + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-match.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-match.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-match.exp (revision 365363) @@ -0,0 +1,5 @@ +match-char-class: + uppercase numbers: One Two Three Four + all the others: five six seven + starts with non-s, ends with [ex]: One Three five +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-match.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-match.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-match.mk (revision 365363) @@ -0,0 +1,22 @@ +# $NetBSD: varmod-match.mk,v 1.3 2020/08/16 20:03:53 rillig Exp $ +# +# Tests for the :M variable modifier, which filters words that match the +# given pattern. + +all: match-char-class +all: slow + + +NUMBERS= One Two Three Four five six seven + +match-char-class: + @echo '$@:' + @echo ' uppercase numbers: ${NUMBERS:M[A-Z]*}' + @echo ' all the others: ${NUMBERS:M[^A-Z]*}' + @echo ' starts with non-s, ends with [ex]: ${NUMBERS:M[^s]*[ex]}' + + +# Before 2020-06-13, this expression took quite a long time in Str_Match, +# calling itself 601080390 times for 16 asterisks. +slow: + @: ${:U****************:M****************b} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-no-match.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-no-match.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-no-match.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-no-match.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-no-match.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-no-match.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-order-reverse.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-reverse.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-reverse.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-reverse.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-reverse.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-reverse.mk (revision 365363) @@ -0,0 +1,13 @@ +# $NetBSD: varmod-order-reverse.mk,v 1.3 2020/08/16 20:13:10 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/20200902/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/20200902/unit-tests/varmod-order-shuffle.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-shuffle.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-shuffle.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-shuffle.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-shuffle.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order-shuffle.mk (revision 365363) @@ -0,0 +1,39 @@ +# $NetBSD: varmod-order-shuffle.mk,v 1.3 2020/08/16 20:43:01 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. + +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/20200902/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/20200902/unit-tests/varmod-order.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-order.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-order.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-order.mk (revision 365363) @@ -0,0 +1,19 @@ +# $NetBSD: varmod-order.mk,v 1.4 2020/08/16 20:43:01 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/20200902/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/20200902/unit-tests/varmod-path.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-path.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-path.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-path.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-quote-dollar.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote-dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote-dollar.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote-dollar.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote-dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote-dollar.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-quote.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-quote.mk (revision 365363) @@ -0,0 +1,9 @@ +# $NetBSD: varmod-quote.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the :Q variable modifier, which quotes the variable value +# to be used in a shell program. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-range.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-range.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-range.exp (revision 365363) @@ -0,0 +1,8 @@ +make: Unknown modifier 'r' + +1 2 3 +make: Unknown modifier 'r' + +make: Unknown modifier 'r' + +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-range.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-range.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-range.mk (revision 365363) @@ -0,0 +1,10 @@ +# $NetBSD: varmod-range.mk,v 1.3 2020/08/23 15:13:21 rillig Exp $ +# +# Tests for the :range variable modifier, which generates sequences +# of integers from the given range. + +all: + @echo ${a b c:L:rang} # modifier name too short + @echo ${a b c:L:range} # ok + @echo ${a b c:L:rango} # misspelled + @echo ${a b c:L:ranger} # modifier name too long Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-remember.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-remember.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-remember.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-remember.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-remember.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-remember.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-root.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-root.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-root.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-root.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-root.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-root.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-select-words.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-select-words.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-select-words.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-select-words.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-select-words.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-select-words.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-shell.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-shell.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-shell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-shell.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-subst-regex.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst-regex.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst-regex.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-subst-regex.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst-regex.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst-regex.mk (revision 365363) @@ -0,0 +1,87 @@ +# $NetBSD: varmod-subst-regex.mk,v 1.3 2020/08/28 17:15:04 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 result. +.if ${:U1 23 456:C,..,\0\0,} != "1 2323 45456" +.error +.endif + +# The modifier '1' applies the replacement at most once, across the whole +# variable 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. +.if ${:U12345 12345:C,.,\0\0,1} != "112345 12345" +.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/20200902/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/20200902/unit-tests/varmod-subst.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-subst.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-subst.mk (revision 365363) @@ -0,0 +1,153 @@ +# $NetBSD: varmod-subst.mk,v 1.3 2020/08/19 06:10:06 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/20200902/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/20200902/unit-tests/varmod-sysv.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-sysv.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-sysv.exp (revision 365363) @@ -0,0 +1,8 @@ +ax:Q b c d eb +bcd.e +& +anchor-dollar: value +anchor-dollar: valux +mismatch: file.cpp file.h +mismatch: renamed.c other.c +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-sysv.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-sysv.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-sysv.mk (revision 365363) @@ -0,0 +1,61 @@ +# $NetBSD: varmod-sysv.mk,v 1.3 2020/08/23 14:52:06 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. + +all: words ampersand anchor-dollar mismatch + +# The :Q looks like a modifier but isn't. +# It is part of the replacement string. +words: + @echo a${a b c d e:L:%a=x:Q}b + +# Before 2020-07-19, an ampersand could be used in the replacement part +# of a SysV substitution modifier. This was probably a copy-and-paste +# mistake since the SysV modifier code looked a lot like the code for the +# :S and :C modifiers. The ampersand is not mentioned in the manual page. +ampersand: + @echo ${:U${a.bcd.e:L:a.%=%}:Q} + @echo ${:U${a.bcd.e:L:a.%=&}:Q} + +# Before 2020-07-20, when a SysV modifier was parsed, a single dollar +# before the '=' was interpreted as an anchor, which doesn't make sense +# since the anchor was discarded immediately. +anchor-dollar: + @echo $@: ${:U${value:L:e$=x}:Q} + @echo $@: ${:U${value:L:e=x}:Q} + +# Words that don't match are copied unmodified. +# The % placeholder can be anywhere in the string. +mismatch: + @echo $@: ${:Ufile.c file.h:%.c=%.cpp} + @echo $@: ${:Ufile.c other.c:file.%=renamed.%} + +# Trying to cover all possible variants of the SysV modifier. +LIST= one two +EXPR.1= ${LIST:o=X} +EXP.1= one twX +EXPR.2= ${LIST:o=} +EXP.2= one tw +EXPR.3= ${LIST:o=%} +EXP.3= one tw% +EXPR.4= ${LIST:%o=X} +EXP.4= one X +EXPR.5= ${LIST:o%=X} +EXP.5= X two +EXPR.6= ${LIST:o%e=X} +EXP.6= X two +EXPR.7= ${LIST:o%%e=X} # Only the first '%' is the wildcard. +EXP.7= one two # None of the words contains a literal '%'. +EXPR.8= ${LIST:%=%%} +EXP.8= one% two% +EXPR.9= ${LIST:%nes=%xxx} # lhs is longer than the word "one" +EXP.9= one two + +.for i in ${:U:range=9} +.if ${EXPR.$i} != ${EXP.$i} +.warning test case $i expected "${EXP.$i}", got "${EXPR.$i} +.endif +.endfor Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-tail.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-tail.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-tail.exp (revision 365363) @@ -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/20200902/unit-tests/varmod-tail.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-tail.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-tail.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-to-abs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-abs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-abs.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-abs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-abs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-abs.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-to-lower.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-lower.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-lower.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-lower.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-lower.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-lower.mk (revision 365363) @@ -0,0 +1,19 @@ +# $NetBSD: varmod-to-lower.mk,v 1.3 2020/08/28 17:21:02 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/20200902/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/20200902/unit-tests/varmod-to-many-words.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-many-words.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-many-words.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-many-words.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-many-words.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-many-words.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-to-one-word.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-one-word.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-one-word.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-one-word.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-one-word.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-one-word.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod-to-separator.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-separator.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-separator.exp (revision 365363) @@ -0,0 +1,9 @@ +make: Bad modifier `:tx' for WORDS +make: "varmod-to-separator.mk" line 104: Malformed conditional (${WORDS:tx} != "anything") +make: "varmod-to-separator.mk" line 108: Parsing continues here. +make: Bad modifier `:t\X' for WORDS +make: "varmod-to-separator.mk" line 112: Malformed conditional (${WORDS:t\X} != "anything") +make: "varmod-to-separator.mk" line 115: Parsing continues here. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-separator.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-separator.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-separator.mk (revision 365363) @@ -0,0 +1,118 @@ +# $NetBSD: varmod-to-separator.mk,v 1.3 2020/08/31 19:58:21 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 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 + +# 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 +.info Parsing continues here. + +# 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 +.info Parsing continues here. + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-to-upper.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-upper.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-upper.exp (revision 365363) @@ -0,0 +1,2 @@ +mod-tu-space: A B +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-upper.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-upper.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-to-upper.mk (revision 365363) @@ -0,0 +1,21 @@ +# $NetBSD: varmod-to-upper.mk,v 1.4 2020/08/28 17:21:02 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/20200902/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/20200902/unit-tests/varmod-undefined.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-undefined.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-undefined.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-undefined.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-undefined.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-undefined.mk (revision 365363) @@ -0,0 +1,55 @@ +# $NetBSD: varmod-undefined.mk,v 1.3 2020/08/23 20:49:33 rillig Exp $ +# +# Tests for the :U variable modifier, which returns the given string +# if the variable is undefined. +# +# 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 +# . error ${word} +# . endif +# .endfor + +.if ${:Uone} != one +. error ${:Uone} +.endif + +# 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 + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varmod-unique.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-unique.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-unique.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod-unique.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod-unique.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod-unique.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varmod.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varmod.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varmod.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varmod.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varmod.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dollar.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dollar.exp (revision 365363) @@ -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/20200902/unit-tests/varname-dollar.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dollar.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-alltargets.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-alltargets.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-alltargets.exp (revision 365363) @@ -0,0 +1,4 @@ + +first second source +first second source all .END +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-alltargets.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-alltargets.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-alltargets.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-curdir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-curdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-curdir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-curdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-curdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-curdir.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-curdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .CURDIR variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-includedfromdir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromdir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromdir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-includedfromfile.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromfile.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromfile.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromfile.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includedfromfile.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-includes.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.exp (revision 365363) @@ -0,0 +1,2 @@ +.INCLUDES= -I. -I.. +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-includes.mk (revision 365363) @@ -0,0 +1,20 @@ +# $NetBSD: varname-dot-includes.mk,v 1.1 2020/08/28 03:51:06 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:Q}) +.error +.endif + +all: + @echo .INCLUDES=${.INCLUDES:Q} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-libs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.exp (revision 365363) @@ -0,0 +1,2 @@ +.LIBS= -L. -L.. +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-libs.mk (revision 365363) @@ -0,0 +1,20 @@ +# $NetBSD: varname-dot-libs.mk,v 1.1 2020/08/28 03:51:06 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:Q}) +.error +.endif + +all: + @echo .LIBS=${.LIBS:Q} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-make-dependfile.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-dependfile.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-dependfile.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-dependfile.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-dependfile.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-dependfile.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-expand_variables.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-expand_variables.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-expand_variables.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-expand_variables.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-expand_variables.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-expand_variables.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-exported.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-exported.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-exported.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-exported.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-exported.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-exported.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-jobs-prefix.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs-prefix.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs-prefix.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs-prefix.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs-prefix.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs-prefix.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-jobs.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-jobs.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-level.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-level.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-level.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-level.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-level.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-level.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-makefile_preference.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefile_preference.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefile_preference.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefile_preference.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefile_preference.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefile_preference.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-makefiles.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefiles.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefiles.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefiles.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefiles.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-makefiles.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-bailiwick.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-bailiwick.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-bailiwick.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-bailiwick.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-bailiwick.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-bailiwick.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-created.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-created.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-created.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-created.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-created.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-created.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-files.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-files.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-files.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-files.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-files.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-files.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-ignore_filter.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_filter.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_filter.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_filter.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_filter.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_filter.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-ignore_paths.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_paths.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_paths.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_paths.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_paths.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_paths.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-ignore_patterns.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-meta-prefix.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-prefix.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-prefix.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-prefix.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-prefix.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-meta-prefix.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-mode.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-mode.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-mode.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-mode.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-mode.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-mode.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-path_filemon.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-path_filemon.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-path_filemon.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-path_filemon.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-path_filemon.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-path_filemon.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-pid.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-pid.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-pid.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-pid.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-pid.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-pid.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-ppid.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-ppid.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-ppid.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-ppid.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-ppid.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-ppid.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-make-save_dollars.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-save_dollars.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-save_dollars.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-save_dollars.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-save_dollars.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-make-save_dollars.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-makeoverrides.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-makeoverrides.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-makeoverrides.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-makeoverrides.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-makeoverrides.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-makeoverrides.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-newline.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-newline.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-newline.exp (revision 365363) @@ -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/20200902/unit-tests/varname-dot-newline.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-newline.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-newline.mk (revision 365363) @@ -0,0 +1,23 @@ +# $NetBSD: varname-dot-newline.mk,v 1.3 2020/08/19 05:51:18 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/20200902/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/20200902/unit-tests/varname-dot-objdir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-objdir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-objdir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-objdir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-objdir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-objdir.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-dot-parsedir.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsedir.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsedir.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsedir.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsedir.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsedir.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-parsedir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .PARSEDIR variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-parsefile.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsefile.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsefile.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsefile.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsefile.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-parsefile.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-parsefile.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .PARSEFILE variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-path.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-path.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-path.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-path.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-path.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-path.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname-dot-path.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .PATH variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-shell.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.exp (revision 365363) @@ -0,0 +1,19 @@ +ParseReadLine (8): 'ORIG_SHELL:= ${.SHELL}' +Var_Parse: ${.SHELL} with VARE_WANTRES|VARE_ASSIGN +Global:delete .SHELL (not found) +Command:.SHELL = (details omitted) +ParseReadLine (10): '.SHELL= overwritten' +Global:.SHELL = overwritten +Var_Parse: ${.SHELL} != ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +ParseReadLine (18): '.undef .SHELL' +Global:delete .SHELL +ParseReadLine (19): '.SHELL= newly overwritten' +Global:.SHELL = newly overwritten +Var_Parse: ${.SHELL} != ${ORIG_SHELL} with VARE_UNDEFERR|VARE_WANTRES +ParseReadLine (24): 'all:' +ParseReadLine (25): ' @echo ${.SHELL:M*}' +Var_Parse: ${.SHELL:M*} with VARE_WANTRES +Applying ${.SHELL:M...} to "(details omitted)" (eflags = VARE_WANTRES, vflags = VAR_READONLY) +Pattern[.SHELL] for [(details omitted)] is [*] +Result of ${.SHELL:M*} is "(details omitted)" (eflags = VARE_WANTRES, vflags = VAR_READONLY) +exit status 0 Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.exp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-shell.mk (revision 365363) @@ -0,0 +1,25 @@ +# $NetBSD: varname-dot-shell.mk,v 1.2 2020/08/23 09:28:52 rillig Exp $ +# +# Tests for the special .SHELL variable, which contains the shell used for +# running the commands. +# +# This variable is read-only. + +ORIG_SHELL:= ${.SHELL} + +.SHELL= overwritten +.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 + +all: + @echo ${.SHELL:M*} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-dot-targets.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-targets.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-targets.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-targets.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-targets.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-dot-targets.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-empty.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-empty.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-empty.exp (revision 365363) @@ -0,0 +1,11 @@ +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 +out: fallback +out: 1 2 3 +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-empty.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-empty.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-empty.mk (revision 365363) @@ -0,0 +1,26 @@ +# $NetBSD: varname-empty.mk,v 1.5 2020/08/22 21:22:24 rillig Exp $ +# +# Tests for the special variable with the empty name. +# +# The variable "" is not supposed to be assigned any value. +# This is because it is heavily used in the .for loop expansion, +# as well as to generate arbitrary strings, as in ${:Ufallback}. + +# 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. +?= default += assigned # undefined behavior until 2020-08-22 ++= appended +:= subst +!= echo 'shell-output' + +# 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/20200902/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/20200902/unit-tests/varname-make.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-make.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-make.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-make.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-make.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-make.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-make_print_var_on_error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-make_print_var_on_error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-make_print_var_on_error.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-make_print_var_on_error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-make_print_var_on_error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-make_print_var_on_error.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname-make_print_var_on_error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for the special .MAKE.PRINT_VAR_ON_ERROR variable. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varname-makeflags.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-makeflags.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-makeflags.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-makeflags.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-makeflags.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-makeflags.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-pwd.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-pwd.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-pwd.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-pwd.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-pwd.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-pwd.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname-vpath.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-vpath.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-vpath.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname-vpath.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname-vpath.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname-vpath.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varname.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/varname.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varname.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varname.mk (revision 365363) @@ -0,0 +1,8 @@ +# $NetBSD: varname.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# +# Tests for special variables, such as .MAKE or .PARSEDIR. + +# TODO: Implementation + +all: + @:; Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varparse-dynamic.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varparse-dynamic.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varparse-dynamic.exp (revision 365363) @@ -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/20200902/unit-tests/varparse-dynamic.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varparse-dynamic.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varparse-dynamic.mk (revision 365363) @@ -0,0 +1,14 @@ +# $NetBSD: varparse-dynamic.mk,v 1.1 2020/07/26 22:15:36 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 + +all: + @: Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond-short.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond-short.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond-short.exp (revision 365363) @@ -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/20200902/unit-tests/Makefile.config.in =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/Makefile.config.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/Makefile.config.in (revision 365363) @@ -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/20200902/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/20200902/unit-tests/dollar.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dollar.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dollar.exp (revision 365363) @@ -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/20200902/unit-tests/dollar.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dollar.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dollar.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/escape.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/escape.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/escape.mk (revision 365363) @@ -0,0 +1,246 @@ +# $Id: escape.mk,v 1.1.1.3 2020/01/22 01:07:14 sjg 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/20200902/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/20200902/unit-tests/forloop.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/forloop.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/forloop.exp (revision 365363) @@ -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 vars +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +OK +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/include-main.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/include-main.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/include-main.exp (revision 365363) @@ -0,0 +1,6 @@ +main-before-ok +sub-before-ok +subsub-ok +sub-after-fail(include-sub.mk) +main-after-fail(include-sub.mk) +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/include-sub.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/include-sub.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/include-sub.mk (revision 365363) @@ -0,0 +1,17 @@ +# $NetBSD: include-sub.mk,v 1.1 2020/05/17 12:36:26 rillig Exp $ + +.if ${.INCLUDEDFROMFILE} == "include-main.mk" +LOG+= sub-before-ok +.else +LOG+= sub-before-fail +.endif + +.include "include-subsub.mk" + +.if ${.INCLUDEDFROMFILE} == "include-main.mk" +LOG+= sub-after-ok +.else +. for f in ${.INCLUDEDFROMFILE} +LOG+= sub-after-fail\(${f:Q}\) +. endfor +.endif Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/include-subsub.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/include-subsub.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/include-subsub.mk (revision 365363) @@ -0,0 +1,7 @@ +# $NetBSD: include-subsub.mk,v 1.1 2020/05/17 12:36:26 rillig Exp $ + +.if ${.INCLUDEDFROMFILE:T} == "include-sub.mk" +LOG+= subsub-ok +.else +LOG+= subsub-fail +.endif Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/varquote.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varquote.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varquote.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/varquote.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varquote.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varquote.exp (revision 365363) @@ -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/20200902/unit-tests/varcmd.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varcmd.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varcmd.exp (revision 365363) @@ -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/20200902/unit-tests/varcmd.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varcmd.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varcmd.mk (revision 365363) @@ -0,0 +1,60 @@ +# $Id: varcmd.mk,v 1.1.1.3 2017/12/08 03:37:54 sjg 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/20200902/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/20200902/unit-tests/dotwait.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dotwait.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dotwait.exp (revision 365363) @@ -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/20200902/unit-tests/dotwait.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/dotwait.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/dotwait.mk (revision 365363) @@ -0,0 +1,61 @@ +# $NetBSD: dotwait.mk,v 1.2 2017/10/08 20:44:19 sjg 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/20200902/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/20200902/unit-tests/export-env.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-env.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-env.exp (revision 365363) @@ -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/20200902/unit-tests/export-env.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-env.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-env.mk (revision 365363) @@ -0,0 +1,27 @@ +# $Id: export-env.mk,v 1.1.1.2 2016/02/18 20:35:24 sjg Exp $ + +# our normal .export, subsequent changes affect the environment +UT_TEST=this +.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/20200902/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/20200902/unit-tests/cond2.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond2.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond2.mk (revision 365363) @@ -0,0 +1,29 @@ +# $Id: cond2.mk,v 1.1.1.2 2015/12/02 00:34:27 sjg Exp $ + +TEST_UNAME_S= NetBSD + +# this should be ok +X:= ${${TEST_UNAME_S} == "NetBSD":?Ok:fail} +.if $X == "Ok" +Y= good +.endif +# expect: Bad conditional expression ` == "empty"' in == "empty"?oops:ok +X:= ${${TEST_NOT_SET} == "empty":?oops:ok} +# expect: Malformed conditional ({TEST_TYPO} == "Ok") +.if {TEST_TYPO} == "Ok" +Y= oops +.endif +.if empty(TEST_NOT_SET) +Y!= echo TEST_NOT_SET is empty or not defined >&2; echo +.endif +# expect: Malformed conditional (${TEST_NOT_SET} == "empty") +.if ${TEST_NOT_SET} == "empty" +Y= oops +.endif + +.if defined(.NDEF) && ${.NDEF} > 0 +Z= yes +.endif + +all: + @echo $@ Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/cond2.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/doterror.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/doterror.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/doterror.exp (revision 365363) @@ -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/20200902/unit-tests/cond2.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond2.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond2.exp (revision 365363) @@ -0,0 +1,7 @@ +make: Bad conditional expression ` == "empty"' in == "empty"?oops:ok +make: "cond2.mk" line 13: Malformed conditional ({TEST_TYPO} == "Ok") +TEST_NOT_SET is empty or not defined +make: "cond2.mk" line 20: Malformed conditional (${TEST_NOT_SET} == "empty") +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/comment.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/comment.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/comment.exp (revision 365363) @@ -0,0 +1,5 @@ +comment testing start +this is foo +This is how a comment looks: # comment +comment testing done +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/comment.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/comment.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/comment.mk (revision 365363) @@ -0,0 +1,31 @@ +# This is a comment +.if ${MACHINE_ARCH} == something +FOO=bar +.endif + +#\ + Multiline comment + +BAR=# defined +FOOBAR= # defined + +# This is an escaped comment \ +that keeps going until the end of this line + +# Another escaped comment \ +that \ +goes \ +on + +# This is NOT an escaped comment due to the double backslashes \\ +all: hi foo bar + @echo comment testing done + +hi: + @echo comment testing start + +foo: + @echo this is $@ + +bar: + @echo This is how a comment looks: '# comment' Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/unit-tests/cond1.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond1.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond1.exp (revision 365363) @@ -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 should be either == or != +make: Bad conditional expression `"0" > 0' in "0" > 0?OK:No + +OK +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/cond1.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/cond1.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/cond1.mk (revision 365363) @@ -0,0 +1,109 @@ +# $Id: cond1.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/doterror.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/doterror.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/doterror.mk (revision 365363) @@ -0,0 +1,20 @@ +# $Id: doterror.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/error.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/error.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/error.exp (revision 365363) @@ -0,0 +1,4 @@ +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 +exit status 1 Index: vendor/NetBSD/bmake/20200902/unit-tests/error.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/error.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/error.mk (revision 365363) @@ -0,0 +1,10 @@ +# $Id: error.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/escape.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/escape.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/escape.exp (revision 365363) @@ -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/20200902/unit-tests/export-all.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/export-all.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/export-all.exp (revision 365363) @@ -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/20200902/unit-tests/forsubst.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/forsubst.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/forsubst.exp (revision 365363) @@ -0,0 +1,2 @@ +.for with :S;... OK +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/forsubst.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/forsubst.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/forsubst.mk (revision 365363) @@ -0,0 +1,10 @@ +# $Id: forsubst.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/hash.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/hash.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/hash.exp (revision 365363) @@ -0,0 +1,9 @@ +b2af338b +3360ac65 +7747f046 +9ca87054 +880fe816 +208fcbd3 +d5d376eb +de41416c +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/hash.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/hash.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/hash.mk (revision 365363) @@ -0,0 +1,18 @@ +STR1= +STR2= a +STR3= ab +STR4= abc +STR5= abcd +STR6= abcde +STR7= abcdef +STR8= abcdefghijklmnopqrstuvwxyz + +all: + @echo ${STR1:hash} + @echo ${STR2:hash} + @echo ${STR3:hash} + @echo ${STR4:hash} + @echo ${STR5:hash} + @echo ${STR6:hash} + @echo ${STR7:hash} + @echo ${STR8:hash} Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/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/20200902/unit-tests/misc.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/misc.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/misc.exp (revision 365363) @@ -0,0 +1 @@ +exit status 0 Index: vendor/NetBSD/bmake/20200902/unit-tests/misc.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/misc.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/misc.mk (revision 365363) @@ -0,0 +1,16 @@ +# $Id: misc.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg Exp $ + +.if !exists(${.CURDIR}/) +.warning ${.CURDIR}/ doesn't exist ? +.endif + +.if !exists(${.CURDIR}/.) +.warning ${.CURDIR}/. doesn't exist ? +.endif + +.if !exists(${.CURDIR}/..) +.warning ${.CURDIR}/.. doesn't exist ? +.endif + +all: + @: all is well Property changes on: vendor/NetBSD/bmake/20200902/unit-tests/misc.mk ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/unit-tests/modword.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modword.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modword.exp (revision 365363) @@ -0,0 +1,122 @@ +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" +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: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/20200902/unit-tests/modword.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/modword.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/modword.mk (revision 365363) @@ -0,0 +1,151 @@ +# $Id: modword.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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-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]}"' + +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-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/20200902/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/20200902/unit-tests/order.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/order.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/order.exp (revision 365363) @@ -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/20200902/unit-tests/order.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/order.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/order.mk (revision 365363) @@ -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/20200902/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/20200902/unit-tests/phony-end.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/phony-end.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/phony-end.mk (revision 365363) @@ -0,0 +1,9 @@ +# $Id: phony-end.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/posix.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/posix.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/posix.exp (revision 365363) @@ -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/20200902/unit-tests/posix.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/posix.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/posix.mk (revision 365363) @@ -0,0 +1,24 @@ +# $Id: posix.mk,v 1.1.1.1 2014/08/30 18:57:18 sjg 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/20200902/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/20200902/unit-tests/posix1.exp =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/posix1.exp (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/posix1.exp (revision 365363) @@ -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" + ${ /dev/null" returned non-zero status +make: "varshell.mk" line 8: warning: "false" returned non-zero status +make: "varshell.mk" line 9: 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/20200902/unit-tests/varshell.mk =================================================================== --- vendor/NetBSD/bmake/20200902/unit-tests/varshell.mk (nonexistent) +++ vendor/NetBSD/bmake/20200902/unit-tests/varshell.mk (revision 365363) @@ -0,0 +1,19 @@ +# $Id: varshell.mk,v 1.4 2015/04/20 03:16:39 sjg 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/20200902/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/20200902/util.c =================================================================== --- vendor/NetBSD/bmake/20200902/util.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/util.c (revision 365363) @@ -0,0 +1,596 @@ +/* $NetBSD: util.c,v 1.58 2020/08/01 14:47:49 rillig Exp $ */ + +/* + * Missing stuff from OS's + * + * $Id: util.c,v 1.36 2020/08/01 23:08:14 sjg Exp $ + */ +#if defined(__MINT__) || defined(__linux__) +#include +#endif + +#include "make.h" + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: util.c,v 1.58 2020/08/01 14:47:49 rillig Exp $"; +#else +#ifndef lint +__RCSID("$NetBSD: util.c,v 1.58 2020/08/01 14:47:49 rillig Exp $"); +#endif +#endif + +#include +#include +#include + +#if !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 */ +void (* +bmake_signal(int s, void (*a)(int)))(int) +{ + 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; + } +} +#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/20200902/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/20200902/var.c =================================================================== --- vendor/NetBSD/bmake/20200902/var.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/var.c (revision 365363) @@ -0,0 +1,3771 @@ +/* $NetBSD: var.c,v 1.484 2020/09/02 06:25:48 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. + */ + +#ifndef MAKE_NATIVE +static char rcsid[] = "$NetBSD: var.c,v 1.484 2020/09/02 06:25:48 rillig Exp $"; +#else +#include +#ifndef lint +#if 0 +static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; +#else +__RCSID("$NetBSD: var.c,v 1.484 2020/09/02 06:25:48 rillig Exp $"); +#endif +#endif /* not lint */ +#endif + +/*- + * var.c -- + * Variable-handling functions + * + * Interface: + * Var_Set Set the value of a variable in the given + * context. The variable is created if it doesn't + * yet exist. + * + * Var_Append Append more characters to an existing variable + * in the given context. The variable needn't + * exist already -- it will be created if it doesn't. + * 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 in a + * context or NULL if the variable is undefined. + * + * Var_Subst Substitute either a single variable or all + * variables in a string, using the given context. + * + * Var_Parse Parse a variable expansion from a string and + * return the result and the number of characters + * consumed. + * + * Var_Delete Delete a variable in a context. + * + * Var_Init Initialize this module. + * + * Debugging: + * 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 + +#include "make.h" + +#ifdef HAVE_INTTYPES_H +#include +#elif defined(HAVE_STDINT_H) +#include +#endif + +#include "enum.h" +#include "dir.h" +#include "job.h" +#include "metachar.h" + +#define VAR_DEBUG_IF(cond, fmt, ...) \ + if (!(DEBUG(VAR) && (cond))) \ + (void) 0; \ + else \ + fprintf(debug_file, fmt, __VA_ARGS__) + +#define VAR_DEBUG(fmt, ...) VAR_DEBUG_IF(TRUE, fmt, __VA_ARGS__) + +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; + +/* + * This is a harmless return value for Var_Parse that can be used by Var_Subst + * to determine if there was an error in parsing -- easier than returning + * a flag, as things outside this module don't give a hoot. + */ +char var_Error[] = ""; + +/* + * Similar to var_Error, but returned when the 'VARE_UNDEFERR' flag for + * Var_Parse is not set. + * + * Why not just use a constant? Well, GCC likes to condense identical string + * instances... + */ +static char varNoError[] = ""; + +/* + * Traditionally we consume $$ during := like any other expansion. + * Other make's do not. + * This knob allows controlling the behavior. + * FALSE to consume $$ during := assignment. + * TRUE to preserve $$ during := assignment. + */ +#define 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 Makefile are located in + * the global context. + * 3) the command-line context. All variables set on the command line + * are placed in this context. They are UNALTERABLE once placed here. + * 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 checkEnvFirst). + */ +GNode *VAR_INTERNAL; /* variables from make itself */ +GNode *VAR_GLOBAL; /* variables from the makefile */ +GNode *VAR_CMD; /* variables defined on the command-line */ + +typedef enum { + FIND_CMD = 0x01, /* look in VAR_CMD when searching */ + FIND_GLOBAL = 0x02, /* look in VAR_GLOBAL as well */ + FIND_ENV = 0x04 /* look in the environment also */ +} VarFindFlags; + +typedef enum { + /* 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 a junk variable that should be destroyed when done with + * it. Used by Var_Parse for undefined, modified variables. */ + VAR_JUNK = 0x04, + /* Variable is VAR_JUNK, but we found a use for it in some modifier and + * the value is therefore valid. */ + VAR_KEEP = 0x08, + /* 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 command line. */ + VAR_FROM_CMD = 0x40, + VAR_READONLY = 0x80 +} VarFlags; + +ENUM_FLAGS_RTTI_8(VarFlags, + VAR_IN_USE, VAR_FROM_ENV, VAR_JUNK, VAR_KEEP, + VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY); + +typedef struct Var { + char *name; /* the variable's name; it is allocated for + * environment variables and aliased to the + * Hash_Entry name for all other variables, + * and thus must not be modified */ + Buffer val; /* its value */ + VarFlags flags; /* miscellaneous status flags */ +} Var; + +/* + * Exporting vars is expensive so skip it if we can + */ +typedef enum { + VAR_EXPORTED_NONE, + VAR_EXPORTED_YES, + VAR_EXPORTED_ALL +} VarExportedMode; + +static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE; + +typedef enum { + /* + * 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 { + VARP_SUB_GLOBAL = 0x01, /* Apply substitution globally */ + VARP_SUB_ONE = 0x02, /* Apply substitution to one word */ + VARP_ANCHOR_START = 0x04, /* Match at start of word */ + VARP_ANCHOR_END = 0x08 /* Match at end of word */ +} VarPatternFlags; + +#define BROPEN '{' +#define BRCLOSE '}' +#define PROPEN '(' +#define PRCLOSE ')' + +/*- + *----------------------------------------------------------------------- + * VarFind -- + * Find the given variable in the given context and any other contexts + * indicated. + * + * Input: + * name name to find + * ctxt context in which to find it + * flags FIND_GLOBAL look in VAR_GLOBAL as well + * FIND_CMD look in VAR_CMD as well + * FIND_ENV look in the environment as well + * + * Results: + * A pointer to the structure describing the desired variable or + * NULL if the variable does not exist. + *----------------------------------------------------------------------- + */ +static Var * +VarFind(const char *name, GNode *ctxt, VarFindFlags flags) +{ + Hash_Entry *var; + + /* + * 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. + */ + if (*name == '.' && isupper((unsigned char)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; + } + } + +#ifdef notyet + /* for compatibility with gmake */ + if (name[0] == '^' && name[1] == '\0') + name = ALLSRC; +#endif + + /* + * First look for the variable in the given context. If it's not there, + * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, + * depending on the FIND_* flags in 'flags' + */ + var = Hash_FindEntry(&ctxt->context, name); + + if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) + var = Hash_FindEntry(&VAR_CMD->context, name); + + if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) && + ctxt != VAR_GLOBAL) + { + var = Hash_FindEntry(&VAR_GLOBAL->context, name); + if (var == NULL && ctxt != VAR_INTERNAL) { + /* VAR_INTERNAL is subordinate to VAR_GLOBAL */ + var = Hash_FindEntry(&VAR_INTERNAL->context, name); + } + } + + if (var == NULL && (flags & FIND_ENV)) { + char *env; + + if ((env = getenv(name)) != NULL) { + Var *v = bmake_malloc(sizeof(Var)); + size_t len; + v->name = bmake_strdup(name); + + len = strlen(env); + Buf_Init(&v->val, len + 1); + Buf_AddBytes(&v->val, env, len); + + v->flags = VAR_FROM_ENV; + return v; + } + + if (checkEnvFirst && (flags & FIND_GLOBAL) && ctxt != VAR_GLOBAL) { + var = Hash_FindEntry(&VAR_GLOBAL->context, name); + if (var == NULL && ctxt != VAR_INTERNAL) + var = Hash_FindEntry(&VAR_INTERNAL->context, name); + if (var == NULL) + return NULL; + else + return (Var *)Hash_GetValue(var); + } + + return NULL; + } + + if (var == NULL) + return NULL; + else + return (Var *)Hash_GetValue(var); +} + +/*- + *----------------------------------------------------------------------- + * VarFreeEnv -- + * If the variable is an environment variable, free it + * + * Input: + * v the variable + * destroy true if the value buffer should be destroyed. + * + * Results: + * TRUE if it is an environment variable, FALSE otherwise. + *----------------------------------------------------------------------- + */ +static Boolean +VarFreeEnv(Var *v, Boolean destroy) +{ + if (!(v->flags & VAR_FROM_ENV)) + return FALSE; + free(v->name); + Buf_Destroy(&v->val, destroy); + 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) +{ + Var *v = bmake_malloc(sizeof(Var)); + size_t len = strlen(val); + Hash_Entry *he; + + Buf_Init(&v->val, len + 1); + Buf_AddBytes(&v->val, val, len); + + v->flags = 0; + if (flags & VAR_SET_READONLY) + v->flags |= VAR_READONLY; + + he = Hash_CreateEntry(&ctxt->context, name, NULL); + Hash_SetValue(he, v); + v->name = he->name; + VAR_DEBUG_IF(!(ctxt->flags & INTERNAL), + "%s:%s = %s\n", ctxt->name, name, val); +} + +/* Remove a variable from a context, freeing the Var structure as well. */ +void +Var_Delete(const char *name, GNode *ctxt) +{ + char *name_freeIt = NULL; + Hash_Entry *he; + + if (strchr(name, '$') != NULL) + name = name_freeIt = Var_Subst(name, VAR_GLOBAL, VARE_WANTRES); + he = Hash_FindEntry(&ctxt->context, name); + VAR_DEBUG("%s:delete %s%s\n", + ctxt->name, name, he != NULL ? "" : " (not found)"); + free(name_freeIt); + + if (he != NULL) { + Var *v = (Var *)Hash_GetValue(he); + if (v->flags & VAR_EXPORTED) + unsetenv(v->name); + if (strcmp(v->name, MAKE_EXPORTED) == 0) + var_exportedVars = VAR_EXPORTED_NONE; + if (v->name != he->name) + free(v->name); + Hash_DeleteEntry(&ctxt->context, he); + Buf_Destroy(&v->val, TRUE); + free(v); + } +} + + +/* + * 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 (name[0] == '.') + return FALSE; /* skip internals */ + 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; + } + } + + 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 this as something we need to re-export. + * No point actually exporting it now though, + * the child 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; + } + + expr = str_concat3("${", name, "}"); + val = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); + 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; +} + +static void +Var_ExportVars_callback(void *entry, void *unused MAKE_ATTR_UNUSED) +{ + Var *var = entry; + Var_Export1(var->name, 0); +} + +/* + * This gets called from our children. + */ +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) { + /* Ouch! This is crazy... */ + Hash_ForEach(&VAR_GLOBAL->context, Var_ExportVars_callback, NULL); + return; + } + + val = Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES); + 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; + } + + flags = 0; + if (strncmp(str, "-env", 4) == 0) { + str += 4; + } else if (strncmp(str, "-literal", 8) == 0) { + str += 8; + flags |= VAR_EXPORT_LITERAL; + } else { + flags |= VAR_EXPORT_PARENT; + } + + val = Var_Subst(str, VAR_GLOBAL, VARE_WANTRES); + 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_ALL) + var_exportedVars = VAR_EXPORTED_YES; + 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 { + for (; isspace((unsigned char)*str); str++) + continue; + if (str[0] != '\0') + varnames = str; + } + + if (varnames == NULL) { + /* Using .MAKE.EXPORTED */ + varnames = varnames_freeIt = Var_Subst("${" MAKE_EXPORTED ":O:u}", + VAR_GLOBAL, VARE_WANTRES); + } + + { + 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_DEBUG("Not unexporting \"%s\" (not found)\n", varname); + continue; + } + + VAR_DEBUG("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) { + char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}"); + char *cp = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); + 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); + + /* + * 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... + */ + if (strchr(name, '$') != NULL) + name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); + + if (name[0] == '\0') { + VAR_DEBUG("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_CMD, 0); + if (v != NULL) { + if (v->flags & VAR_FROM_CMD) { + VAR_DEBUG("%s:%s = %s ignored!\n", ctxt->name, name, val); + goto out; + } + VarFreeEnv(v, TRUE); + } + } + + v = VarFind(name, ctxt, 0); + if (v == NULL) { + if (ctxt == VAR_CMD && !(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. + */ + Var_Delete(name, VAR_GLOBAL); + } + VarAdd(name, val, ctxt, flags); + } else { + if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) { + VAR_DEBUG("%s:%s = %s ignored (read-only)\n", + ctxt->name, name, val); + goto out; + } + Buf_Empty(&v->val); + if (val) + Buf_AddStr(&v->val, val); + + VAR_DEBUG("%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_CMD && !(flags & VAR_NO_EXPORT) && name[0] != '.') { + if (v == NULL) { + /* we just added it */ + v = VarFind(name, ctxt, 0); + } + if (v != NULL) + 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 (!varNoExportEnv) + setenv(name, val ? val : "", 1); + + Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL); + } + if (name[0] == '.' && strcmp(name, 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 variable to set + * 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_CMD, only + * VAR_CMD->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_CMD 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 variable to modify + * 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; + name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); + if (name[0] == '\0') { + VAR_DEBUG("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 ? (FIND_CMD | FIND_ENV) : 0); + + if (v == NULL) { + Var_Set(name, val, ctxt); + } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) { + Buf_AddByte(&v->val, ' '); + Buf_AddStr(&v->val, val); + + VAR_DEBUG("%s:%s = %s\n", ctxt->name, name, + Buf_GetAll(&v->val, NULL)); + + if (v->flags & VAR_FROM_ENV) { + Hash_Entry *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 = Hash_CreateEntry(&ctxt->context, name, NULL); + Hash_SetValue(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 + * 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) + name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); + + v = VarFind(name, ctxt, FIND_CMD | FIND_GLOBAL | FIND_ENV); + 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 + * 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 *freeIt + * as soon as the returned value is no longer needed. + *----------------------------------------------------------------------- + */ +const char * +Var_Value(const char *name, GNode *ctxt, char **freeIt) +{ + Var *v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); + char *p; + + *freeIt = NULL; + if (v == NULL) + return NULL; + + p = Buf_GetAll(&v->val, NULL); + if (VarFreeEnv(v, FALSE)) + *freeIt = p; + return p; +} + + +/* SepBuf is a string being built from "words", interleaved with separators. */ +typedef struct { + 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 an expression and + * typically adds a modification of this word to the buffer. It may also do + * nothing or add several words. */ +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_DEBUG("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 +/*- + *----------------------------------------------------------------------- + * Str_SYSVMatch -- + * Check word against pattern for a match (% is wild), + * + * Input: + * word Word to examine + * pattern Pattern to examine against + * + * Results: + * Returns the start of the match, or NULL. + * *match_len returns the length of the match, if any. + * *hasPercent returns whether the pattern contains a percent. + *----------------------------------------------------------------------- + */ +static const char * +Str_SYSVMatch(const char *word, const char *pattern, size_t *match_len, + Boolean *hasPercent) +{ + const char *p = pattern; + const char *w = word; + const char *percent; + size_t w_len; + size_t p_len; + const char *w_tail; + + *hasPercent = FALSE; + if (*p == '\0') { /* ${VAR:=suffix} */ + *match_len = strlen(w); /* Null pattern is the whole string */ + return w; + } + + percent = strchr(p, '%'); + if (percent != NULL) { /* ${VAR:...%...=...} */ + *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 */ + *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; + + *match_len = (size_t)(w_tail - w); + return w; +} + +typedef struct { + GNode *ctx; + const char *lhs; + const char *rhs; +} ModifyWord_SYSVSubstArgs; + +/* Callback for ModifyWords to implement the :%.from=%.to modifier. */ +static void +ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data) +{ + const ModifyWord_SYSVSubstArgs *args = data; + char *rhs_expanded; + const char *rhs; + const char *percent; + + size_t match_len; + Boolean lhsPercent; + const char *match = Str_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. */ + + rhs_expanded = Var_Subst(args->rhs, args->ctx, VARE_WANTRES); + + 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 + + +typedef struct { + const char *lhs; + size_t lhsLen; + const char *rhs; + size_t rhsLen; + VarPatternFlags pflags; + Boolean matched; +} ModifyWord_SubstArgs; + +/* 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); + 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) { + if (wordLen != args->lhsLen) + goto nosub; + + /* :S,^whole$,replacement, */ + SepBuf_AddBytes(buf, args->rhs, args->rhsLen); + args->matched = TRUE; + } else { + /* :S,^prefix,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; + } + + /* unanchored case, may match more than once */ + while ((match = Str_FindSubstring(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); +} + +typedef struct { + regex_t re; + size_t nsub; + char *replace; + VarPatternFlags pflags; + Boolean matched; +} ModifyWord_SubstRegexArgs; + +/* 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) +{ + 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 != '\\' || !isdigit((unsigned char)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 && m[n].rm_eo == -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"); + /* fall through */ + case REG_NOMATCH: + nosub: + SepBuf_AddStr(buf, wp); + break; + } +} +#endif + + +typedef struct { + GNode *ctx; + char *tvar; /* name of temporary variable */ + char *str; /* string to expand */ + VarEvalFlags eflags; +} ModifyWord_LoopArgs; + +/* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */ +static void +ModifyWord_Loop(const char *word, SepBuf *buf, void *data) +{ + const ModifyWord_LoopArgs *args; + char *s; + + if (word[0] == '\0') + return; + + args = data; + Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT); + s = Var_Subst(args->str, args->ctx, args->eflags); + + VAR_DEBUG("ModifyWord_Loop: in \"%s\", replace \"%s\" with \"%s\" " + "to \"%s\"\n", + word, args->tvar, args->str, s); + + if (s[0] == '\n' || (buf->buf.count > 0 && + buf->buf.buffer[buf->buf.count - 1] == '\n')) + buf->needSep = FALSE; + SepBuf_AddStr(buf, s); + free(s); +} + + +/*- + * Implements the :[first..last] modifier. + * This is a special case of ModifyWords since we want to be able + * to scan the list backwards if first > last. + */ +static char * +VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first, + int last) +{ + Words words; + int 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.). + */ + if (first < 0) + first += (int)words.len + 1; + if (last < 0) + last += (int)words.len + 1; + + /* + * We avoid scanning more of the list than we need to. + */ + if (first > last) { + start = MIN((int)words.len, first) - 1; + end = MAX(0, last - 1); + step = -1; + } else { + start = MAX(0, first - 1); + end = MIN((int)words.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(GNode *ctx, char sep, Boolean oneBigWord, const char *str, + ModifyWordsCallback modifyWord, void *modifyWord_args) +{ + 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_DEBUG("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 (result.buf.count > 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); +} + + +/*- + * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ + * or the "var" or "replacement" 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 char * +ParseModifierPart( + const char **pp, /* The parsing position, updated upon return */ + int delim, /* Parsing stops at this delimiter */ + VarEvalFlags eflags, /* Flags for evaluating nested variables; + * if VARE_WANTRES is not set, the text is + * only parsed */ + GNode *ctxt, /* For looking up nested variables */ + 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 $. */ + 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; + char *rstr; + + Buf_Init(&buf, 0); + + /* + * Skim through until the matching delimiter is found; + * pick up variable substitutions on the way. Also allow + * backslashes to quote the delimiter, $, and \, but don't + * touch other backslashes. + */ + p = *pp; + while (*p != '\0' && *p != delim) { + const char *varstart; + + Boolean is_escaped = p[0] == '\\' && ( + p[1] == delim || p[1] == '\\' || p[1] == '$' || + (p[1] == '&' && subst != NULL)); + if (is_escaped) { + 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 *cp2; + int len; + void *freeIt; + VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN; + + cp2 = Var_Parse(p, ctxt, nested_eflags, &len, &freeIt); + Buf_AddStr(&buf, cp2); + free(freeIt); + p += len; + 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] == PROPEN || p[1] == BROPEN) { + /* + * Find the end of this variable reference + * and suck it in without further ado. + * It will be interpreted later. + */ + int have = p[1]; + int want = have == PROPEN ? PRCLOSE : BRCLOSE; + int depth = 1; + + for (p += 2; *p != '\0' && depth > 0; p++) { + if (p[-1] != '\\') { + if (*p == have) + depth++; + if (*p == want) + depth--; + } + } + Buf_AddBytesBetween(&buf, varstart, p); + } else { + Buf_AddByte(&buf, *varstart); + p++; + } + } + + if (*p != delim) { + *pp = p; + return NULL; + } + + *pp = ++p; + if (out_length != NULL) + *out_length = Buf_Size(&buf); + + rstr = Buf_Destroy(&buf, FALSE); + VAR_DEBUG("Modifier part: \"%s\"\n", rstr); + return rstr; +} + +/* 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) +{ + char *res; + 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 (isspace((unsigned char)*str) || ismeta((unsigned char)*str)) + Buf_AddByte(&buf, '\\'); + Buf_AddByte(&buf, *str); + if (quoteDollar && *str == '$') + Buf_AddStr(&buf, "\\$"); + } + + res = Buf_Destroy(&buf, FALSE); + VAR_DEBUG("QuoteMeta: [%s]\n", res); + return res; +} + +/* 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), set st->missing_delim and 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 variables into useful + * variables (VAR_JUNK, VAR_KEEP). + * + * Some modifiers need to free some memory. + */ + +typedef struct { + 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 missing_delim; /* For error reporting */ + + 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. */ +} ApplyModifiersState; + +typedef enum { + 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, with "Unfinished modifier" + * if st->missing_delim is set. */ +} ApplyModifierResult; + +/* 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] == '='); +} + +/* :@var@...${var}...@ */ +static ApplyModifierResult +ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) +{ + ModifyWord_LoopArgs args; + char delim; + char prev_sep; + VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES; + + args.ctx = st->ctxt; + + (*pp)++; /* Skip the first '@' */ + delim = '@'; + args.tvar = ParseModifierPart(pp, delim, eflags, + st->ctxt, NULL, NULL, NULL); + if (args.tvar == NULL) { + st->missing_delim = delim; + 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; + } + + args.str = ParseModifierPart(pp, delim, eflags, + st->ctxt, NULL, NULL, NULL); + if (args.str == NULL) { + st->missing_delim = delim; + 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->ctxt, st->sep, st->oneBigWord, st->val, + ModifyWord_Loop, &args); + 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->v->flags & VAR_JUNK)) + 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 *cp2; + int len; + void *freeIt; + + cp2 = Var_Parse(p, st->ctxt, eflags, &len, &freeIt); + Buf_AddStr(&buf, cp2); + free(freeIt); + p += len; + continue; + } + + /* Ordinary text */ + Buf_AddByte(&buf, *p); + p++; + } + *pp = p; + + if (st->v->flags & VAR_JUNK) + st->v->flags |= VAR_KEEP; + if (eflags & VARE_WANTRES) { + st->newVal = Buf_Destroy(&buf, FALSE); + } else { + st->newVal = st->val; + Buf_Destroy(&buf, TRUE); + } + return AMR_OK; +} + +/* :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] == '=') { + char *ep; + utc = (time_t)strtoul(mod + 7, &ep, 10); + *pp = ep; + } else { + utc = 0; + *pp = mod + 6; + } + st->newVal = VarStrftime(st->val, TRUE, utc); + return AMR_OK; +} + +/* :localtime */ +static Boolean +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] == '=') { + char *ep; + utc = (time_t)strtoul(mod + 10, &ep, 10); + *pp = ep; + } 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; + + if (st->v->flags & VAR_JUNK) + st->v->flags |= VAR_KEEP; + + gn = Targ_FindNode(st->v->name, TARG_NOCREATE); + if (gn == NULL || gn->type & OP_NOPATH) { + path = NULL; + } else if (gn->path) { + path = bmake_strdup(gn->path); + } else { + Lst 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_Exclam(const char **pp, ApplyModifiersState *st) +{ + char delim; + char *cmd; + const char *errfmt; + + (*pp)++; + delim = '!'; + cmd = ParseModifierPart(pp, delim, st->eflags, st->ctxt, + NULL, NULL, NULL); + if (cmd == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + + errfmt = NULL; + if (st->eflags & VARE_WANTRES) + st->newVal = Cmd_Exec(cmd, &errfmt); + else + st->newVal = varNoError; + free(cmd); + + if (errfmt != NULL) + Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ + + if (st->v->flags & VAR_JUNK) + st->v->flags |= VAR_KEEP; + 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] == '=') { + char *ep; + n = (size_t)strtoul(mod + 6, &ep, 10); + *pp = ep; + } 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; + pattern = Var_Subst(pattern, st->ctxt, st->eflags); + free(old_pattern); + } + + VAR_DEBUG("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->ctxt, st->sep, st->oneBigWord, st->val, + callback, pattern); + free(pattern); + return AMR_OK; +} + +/* :S,from,to, */ +static ApplyModifierResult +ApplyModifier_Subst(const char **pp, ApplyModifiersState *st) +{ + ModifyWord_SubstArgs args; + char *lhs, *rhs; + Boolean oneBigWord; + + 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)++; + } + + lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, + &args.lhsLen, &args.pflags, NULL); + if (lhs == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + args.lhs = lhs; + + rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, + &args.rhsLen, NULL, &args); + if (rhs == NULL) { + st->missing_delim = delim; + 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->ctxt, st->sep, oneBigWord, st->val, + ModifyWord_Subst, &args); + + free(lhs); + free(rhs); + return AMR_OK; +} + +#ifndef NO_REGEX + +/* :C,from,to, */ +static ApplyModifierResult +ApplyModifier_Regex(const char **pp, ApplyModifiersState *st) +{ + char *re; + ModifyWord_SubstRegexArgs args; + Boolean oneBigWord; + int error; + + char delim = (*pp)[1]; + if (delim == '\0') { + Error("Missing delimiter for :C modifier"); + (*pp)++; + return AMR_CLEANUP; + } + + *pp += 2; + + re = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); + if (re == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + + args.replace = ParseModifierPart(pp, delim, st->eflags, st->ctxt, + NULL, NULL, NULL); + if (args.replace == NULL) { + free(re); + st->missing_delim = delim; + 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->ctxt, st->sep, oneBigWord, st->val, + ModifyWord_SubstRegex, &args); + regfree(&args.re); + free(args.replace); + return AMR_OK; +} +#endif + +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) +{ + /* XXX: pp points to the 's', for historic reasons only. + * Changing this will influence the error messages. */ + const char *sep = *pp + 1; + + /* ":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] != '\\') + 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 *numStart = sep + 1; + int base = 8; /* assume octal */ + char *end; + + if (sep[1] == 'x') { + base = 16; + numStart++; + } else if (!isdigit((unsigned char)sep[1])) + return AMR_BAD; /* ":ts". */ + + st->sep = (char)strtoul(numStart, &end, base); + if (*end != ':' && *end != st->endc) + return AMR_BAD; + *pp = end; + } + +ok: + st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, + ModifyWord_Copy, NULL); + 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'); + + *pp = mod + 1; /* make sure it is set */ + if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') + return AMR_BAD; /* Found ":t" or ":t:". */ + + if (mod[1] == 's') + return ApplyModifier_ToSep(pp, st); + + if (mod[2] != st->endc && mod[2] != ':') + return AMR_BAD; /* Found ":t". */ + + /* Check for two-character options: ":tu", ":tl" */ + if (mod[1] == 'A') { /* absolute path */ + st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, + ModifyWord_Realpath, NULL); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'u') { + 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] = (char)toupper((unsigned char)st->val[i]); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'l') { + 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] = (char)tolower((unsigned char)st->val[i]); + *pp = mod + 2; + return AMR_OK; + } + + if (mod[1] == 'W' || mod[1] == 'w') { + st->oneBigWord = mod[1] == 'W'; + st->newVal = st->val; + *pp = mod + 2; + return AMR_OK; + } + + /* Found ":t:" or ":t". */ + return AMR_BAD; +} + +/* :[#], :[1], etc. */ +static ApplyModifierResult +ApplyModifier_Words(const char **pp, ApplyModifiersState *st) +{ + char delim; + char *estr; + char *ep; + int first, last; + + (*pp)++; /* skip the '[' */ + delim = ']'; /* look for closing ']' */ + estr = ParseModifierPart(pp, delim, st->eflags, st->ctxt, + NULL, NULL, NULL); + if (estr == NULL) { + st->missing_delim = delim; + 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]. + */ + first = (int)strtol(estr, &ep, 0); + if (ep == estr) /* Found junk instead of a number */ + goto bad_modifier; + + if (ep[0] == '\0') { /* Found only one integer in :[N] */ + last = first; + } else if (ep[0] == '.' && ep[1] == '.' && ep[2] != '\0') { + /* Expecting another integer after ".." */ + ep += 2; + last = (int)strtol(ep, &ep, 0); + if (ep[0] != '\0') /* Found junk after ".." */ + goto bad_modifier; + } else + goto bad_modifier; /* Found junk instead of ".." */ + + /* + * Now seldata is 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 seldata. */ + 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 delim; + char *then_expr, *else_expr; + + 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_EvalExpression(NULL, st->v->name, &value, 0, FALSE); + if (cond_rc != COND_INVALID && value) + then_eflags |= VARE_WANTRES; + if (cond_rc != COND_INVALID && !value) + else_eflags |= VARE_WANTRES; + } + + (*pp)++; /* skip past the '?' */ + delim = ':'; + then_expr = ParseModifierPart(pp, delim, then_eflags, st->ctxt, + NULL, NULL, NULL); + if (then_expr == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + + delim = st->endc; /* BRCLOSE or PRCLOSE */ + else_expr = ParseModifierPart(pp, delim, else_eflags, st->ctxt, + NULL, NULL, NULL); + if (else_expr == NULL) { + st->missing_delim = delim; + 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); + } + if (st->v->flags & VAR_JUNK) + st->v->flags |= VAR_KEEP; + 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 *sv_name; + char delim; + char *val; + + const char *mod = *pp; + const char *op = mod + 1; + if (!(op[0] == '=' || + (op[1] == '=' && + (op[0] == '!' || op[0] == '+' || op[0] == '?')))) + return AMR_UNKNOWN; /* "::" */ + + + if (st->v->name[0] == 0) { + *pp = mod + 1; + return AMR_BAD; + } + + v_ctxt = st->ctxt; /* context where v belongs */ + sv_name = NULL; + if (st->v->flags & VAR_JUNK) { + /* + * We need to bmake_strdup() it in case ParseModifierPart() recurses. + */ + sv_name = st->v->name; + st->v->name = bmake_strdup(st->v->name); + } else if (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 == PROPEN ? PRCLOSE : BRCLOSE; + val = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); + if (st->v->flags & VAR_JUNK) { + /* restore original name */ + free(st->v->name); + st->v->name = sv_name; + } + if (val == NULL) { + st->missing_delim = delim; + 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->v->flags & VAR_JUNK)) + break; + /* FALLTHROUGH */ + default: + Var_Set(st->v->name, val, v_ctxt); + break; + } + } + free(val); + st->newVal = varNoError; /* XXX: varNoError is kind of an error, + * the intention here is to just return + * an empty string. */ + 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. */ +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->ctxt, st->sep, st->oneBigWord, + st->val, modifyWord, NULL); + (*pp)++; + return AMR_OK; +} + +#ifdef SYSVVARSUB +/* :from=to */ +static ApplyModifierResult +ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) +{ + char delim; + char *lhs, *rhs; + + 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 nest = 1; + const char *next = mod; + while (*next != '\0' && nest > 0) { + if (*next == '=') { + eqFound = TRUE; + /* continue looking for st->endc */ + } else if (*next == st->endc) + nest--; + else if (*next == st->startc) + nest++; + if (nest > 0) + next++; + } + if (*next != st->endc || !eqFound) + return AMR_UNKNOWN; + + delim = '='; + *pp = mod; + lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); + if (lhs == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + + delim = st->endc; + rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); + if (rhs == NULL) { + st->missing_delim = delim; + return AMR_CLEANUP; + } + + /* + * SYSV modifications happen through the whole + * string. Note the pattern is anchored at the end. + */ + (*pp)--; + if (lhs[0] == '\0' && *st->val == '\0') { + st->newVal = st->val; /* special case */ + } else { + ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs}; + st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, + ModifyWord_SYSVSubst, &args); + } + free(lhs); + free(rhs); + return AMR_OK; +} +#endif + +/* 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 *val, /* the current value of the variable */ + char const startc, /* '(' or '{', or '\0' for indirect modifiers */ + char const endc, /* ')' or '}', or '\0' for indirect modifiers */ + Var * const v, /* the variable may have its flags changed */ + GNode * const ctxt, /* for looking up and modifying variables */ + VarEvalFlags const eflags, + void ** const freePtr /* free this after using the return value */ +) { + ApplyModifiersState st = { + startc, endc, v, ctxt, eflags, val, + var_Error, /* .newVal */ + '\0', /* .missing_delim */ + ' ', /* .sep */ + FALSE /* .oneBigWord */ + }; + 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 == '$') { + /* + * We may have some complex modifiers in a variable. + */ + int rlen; + void *freeIt; + const char *rval = Var_Parse(p, st.ctxt, st.eflags, &rlen, &freeIt); + + /* + * If we have not parsed up to st.endc or ':', + * we are not interested. + */ + int c; + if (rval[0] != '\0' && + (c = p[rlen]) != '\0' && c != ':' && c != st.endc) { + free(freeIt); + goto apply_mods; + } + + VAR_DEBUG("Indirect modifier \"%s\" from \"%.*s\"\n", + rval, rlen, p); + + p += rlen; + + if (rval[0] != '\0') { + const char *rval_pp = rval; + st.val = ApplyModifiers(&rval_pp, st.val, '\0', '\0', v, + ctxt, eflags, freePtr); + if (st.val == var_Error + || (st.val == varNoError && !(st.eflags & VARE_UNDEFERR)) + || *rval_pp != '\0') { + free(freeIt); + goto out; /* error already reported */ + } + } + free(freeIt); + if (*p == ':') + p++; + else if (*p == '\0' && endc != '\0') { + Error("Unclosed variable specification after complex " + "modifier (expecting '%c') for %s", st.endc, st.v->name); + goto out; + } + continue; + } + apply_mods: + st.newVal = var_Error; /* default value, in case of errors */ + res = AMR_BAD; /* just a safe fallback */ + mod = p; + + if (DEBUG(VAR)) { + char eflags_str[VarEvalFlags_ToStringSize]; + char vflags_str[VarFlags_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. */ + VAR_DEBUG("Applying ${%s:%c%s} to \"%s\" " + "(eflags = %s, vflags = %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)); + } + + switch (*mod) { + case ':': + res = ApplyModifier_Assign(&p, &st); + break; + case '@': + res = ApplyModifier_Loop(&p, &st); + break; + case '_': + res = ApplyModifier_Remember(&p, &st); + break; + case 'D': + case 'U': + res = ApplyModifier_Defined(&p, &st); + break; + case 'L': + if (st.v->flags & VAR_JUNK) + st.v->flags |= VAR_KEEP; + st.newVal = bmake_strdup(st.v->name); + p++; + res = AMR_OK; + break; + case 'P': + res = ApplyModifier_Path(&p, &st); + break; + case '!': + res = ApplyModifier_Exclam(&p, &st); + break; + case '[': + res = ApplyModifier_Words(&p, &st); + break; + case 'g': + res = ApplyModifier_Gmtime(&p, &st); + break; + case 'h': + res = ApplyModifier_Hash(&p, &st); + break; + case 'l': + res = ApplyModifier_Localtime(&p, &st); + break; + case 't': + res = ApplyModifier_To(&p, &st); + break; + case 'N': + case 'M': + res = ApplyModifier_Match(&p, &st); + break; + case 'S': + res = ApplyModifier_Subst(&p, &st); + break; + case '?': + res = ApplyModifier_IfElse(&p, &st); + break; +#ifndef NO_REGEX + case 'C': + res = ApplyModifier_Regex(&p, &st); + break; +#endif + case 'q': + case 'Q': + if (p[1] == st.endc || p[1] == ':') { + st.newVal = VarQuote(st.val, *mod == 'q'); + p++; + res = AMR_OK; + } else + res = AMR_UNKNOWN; + break; + case 'T': + res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Tail); + break; + case 'H': + res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Head); + break; + case 'E': + res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Suffix); + break; + case 'R': + res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Root); + break; + case 'r': + res = ApplyModifier_Range(&p, &st); + break; + case 'O': + res = ApplyModifier_Order(&p, &st); + break; + case 'u': + if (p[1] == st.endc || p[1] == ':') { + st.newVal = VarUniq(st.val); + p++; + res = AMR_OK; + } else + res = AMR_UNKNOWN; + break; +#ifdef SUNSHCMD + case 's': + 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 = varNoError; + p += 2; + res = AMR_OK; + } else + res = AMR_UNKNOWN; + break; +#endif + default: + res = AMR_UNKNOWN; + } + +#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)) { + char eflags_str[VarEvalFlags_ToStringSize]; + char vflags_str[VarFlags_ToStringSize]; + const char *quot = st.newVal == var_Error ? "" : "\""; + const char *newVal = st.newVal == var_Error ? "error" : st.newVal; + + VAR_DEBUG("Result of ${%s:%.*s} is %s%s%s " + "(eflags = %s, vflags = %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)); + } + + if (st.newVal != st.val) { + if (*freePtr) { + free(st.val); + *freePtr = NULL; + } + st.val = st.newVal; + if (st.val != var_Error && st.val != varNoError) { + *freePtr = 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++; + } + mod = p; + } +out: + *pp = p; + assert(st.val != NULL); /* Use var_Error or varNoError instead. */ + return st.val; + +bad_modifier: + Error("Bad modifier `:%.*s' for %s", + (int)strcspn(mod, ":)}"), mod, st.v->name); + +cleanup: + *pp = p; + if (st.missing_delim != '\0') + Error("Unfinished modifier for %s ('%c' missing)", + st.v->name, st.missing_delim); + free(*freePtr); + *freePtr = NULL; + return var_Error; +} + +static Boolean +VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) +{ + if ((namelen == 1 || + (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && + (ctxt == VAR_CMD || 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[0]) { + case '@': + case '%': + case '*': + case '!': + return TRUE; + } + return FALSE; + } + + if ((namelen == 7 || namelen == 8) && varname[0] == '.' && + isupper((unsigned char)varname[1]) && + (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) + { + return strcmp(varname, ".TARGET") == 0 || + strcmp(varname, ".ARCHIVE") == 0 || + strcmp(varname, ".PREFIX") == 0 || + strcmp(varname, ".MEMBER") == 0; + } + + return FALSE; +} + +/*- + *----------------------------------------------------------------------- + * Var_Parse -- + * Given the start of a variable invocation (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. + * + * Input: + * str The string to parse + * ctxt The context for the variable + * flags VARE_UNDEFERR if undefineds are an error + * VARE_WANTRES if we actually want the result + * VARE_ASSIGN if we are in a := assignment + * lengthPtr OUT: The length of the specification + * freePtr OUT: Non-NULL if caller should free *freePtr + * + * Results: + * Returns the value of the variable expression, never NULL. + * var_Error if there was a parse error and VARE_UNDEFERR was set. + * varNoError if there was a parse error and VARE_UNDEFERR was not set. + * + * Parsing should continue at str + *lengthPtr. + * + * After using the returned value, *freePtr 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] */ +const char * +Var_Parse(const char * const str, GNode *ctxt, VarEvalFlags eflags, + int *lengthPtr, void **freePtr) +{ + const char *tstr; /* Pointer into str */ + 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 invocation, unaltered */ + const char *extramodifiers; + Var *v; + char *nstr; + char eflags_str[VarEvalFlags_ToStringSize]; + + VAR_DEBUG("%s: %s with %s\n", __func__, str, + Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags, + VarEvalFlags_ToStringSpecs)); + + *freePtr = NULL; + extramodifiers = NULL; /* extra modifiers to apply first */ + dynamic = FALSE; + +#ifdef USE_DOUBLE_BOOLEAN + /* Appease GCC 5.5.0, which thinks that the variable might not be + * initialized. */ + endc = '\0'; +#endif + + startc = str[1]; + if (startc != PROPEN && startc != BROPEN) { + char name[2]; + + /* + * 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. + */ + + /* Error out some really stupid names */ + if (startc == '\0' || strchr(")}:$", startc)) { + *lengthPtr = 1; + return var_Error; + } + + name[0] = startc; + name[1] = '\0'; + v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); + if (v == NULL) { + *lengthPtr = 2; + + if (ctxt == VAR_CMD || 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 (str[1]) { + case '@': + return "$(.TARGET)"; + case '%': + return "$(.MEMBER)"; + case '*': + return "$(.PREFIX)"; + case '!': + return "$(.ARCHIVE)"; + } + } + return (eflags & VARE_UNDEFERR) ? var_Error : varNoError; + } else { + haveModifier = FALSE; + tstr = str + 1; + } + } else { + Buffer namebuf; /* Holds the variable name */ + int depth; + size_t namelen; + char *varname; + + endc = startc == PROPEN ? PRCLOSE : BRCLOSE; + + Buf_Init(&namebuf, 0); + + /* + * Skip to the end character or a colon, whichever comes first. + */ + depth = 1; + for (tstr = str + 2; *tstr != '\0'; tstr++) { + /* Track depth so we can spot parse errors. */ + if (*tstr == startc) + depth++; + if (*tstr == endc) { + if (--depth == 0) + break; + } + if (*tstr == ':' && depth == 1) + break; + /* A variable inside a variable, expand. */ + if (*tstr == '$') { + int rlen; + void *freeIt; + const char *rval = Var_Parse(tstr, ctxt, eflags, &rlen, + &freeIt); + Buf_AddStr(&namebuf, rval); + free(freeIt); + tstr += rlen - 1; + } else + Buf_AddByte(&namebuf, *tstr); + } + if (*tstr == ':') { + haveModifier = TRUE; + } else if (*tstr == endc) { + haveModifier = FALSE; + } else { + Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", + Buf_GetAll(&namebuf, NULL)); + /* + * If we never did find the end character, return NULL + * right now, setting the length to be the distance to + * the end of the string, since that's what make does. + */ + *lengthPtr = (int)(size_t)(tstr - str); + Buf_Destroy(&namebuf, TRUE); + return var_Error; + } + + varname = Buf_GetAll(&namebuf, &namelen); + + /* + * At this point, varname points into newly allocated memory from + * namebuf, containing only the name of the variable. + * + * start and tstr point into the const string that was pointed + * to by the original value of the str parameter. start points + * to the '$' at the beginning of the string, while tstr points + * to the char just after the end of the variable name -- this + * will be '\0', ':', PRCLOSE, or BRCLOSE. + */ + + v = VarFind(varname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); + /* + * 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_CMD && 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') { + extramodifiers = "H:"; + } else { /* F */ + extramodifiers = "T:"; + } + } + } + + if (v == NULL) { + dynamic = VarIsDynamic(ctxt, varname, namelen); + + if (!haveModifier) { + /* + * No modifiers -- have specification length so we can return + * now. + */ + *lengthPtr = (int)(size_t)(tstr - str) + 1; + if (dynamic) { + char *pstr = bmake_strldup(str, (size_t)*lengthPtr); + *freePtr = pstr; + Buf_Destroy(&namebuf, TRUE); + return pstr; + } else { + Buf_Destroy(&namebuf, TRUE); + return (eflags & VARE_UNDEFERR) ? var_Error : varNoError; + } + } else { + /* + * Still need to get to the end of the variable specification, + * so kludge up a Var structure for the modifications + */ + v = bmake_malloc(sizeof(Var)); + v->name = varname; + Buf_Init(&v->val, 1); + v->flags = VAR_JUNK; + Buf_Destroy(&namebuf, FALSE); + } + } else + Buf_Destroy(&namebuf, TRUE); + } + + if (v->flags & VAR_IN_USE) { + Fatal("Variable %s is recursive.", v->name); + /*NOTREACHED*/ + } else { + v->flags |= VAR_IN_USE; + } + + /* + * 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) != 0) { + nstr = Var_Subst(nstr, ctxt, eflags); + *freePtr = nstr; + } + + v->flags &= ~(unsigned)VAR_IN_USE; + + if (haveModifier || extramodifiers != NULL) { + void *extraFree; + + extraFree = NULL; + if (extramodifiers != NULL) { + const char *em = extramodifiers; + nstr = ApplyModifiers(&em, nstr, '(', ')', + v, ctxt, eflags, &extraFree); + } + + if (haveModifier) { + /* Skip initial colon. */ + tstr++; + + nstr = ApplyModifiers(&tstr, nstr, startc, endc, + v, ctxt, eflags, freePtr); + free(extraFree); + } else { + *freePtr = extraFree; + } + } + + /* Skip past endc if possible. */ + *lengthPtr = (int)(size_t)(tstr + (*tstr ? 1 : 0) - str); + + if (v->flags & VAR_FROM_ENV) { + Boolean destroy = nstr != Buf_GetAll(&v->val, NULL); + if (!destroy) { + /* + * Returning the value unmodified, so tell the caller to free + * the thing. + */ + *freePtr = nstr; + } + (void)VarFreeEnv(v, destroy); + } else if (v->flags & VAR_JUNK) { + /* + * Perform any freeing needed and set *freePtr to NULL so the caller + * doesn't try to free a static pointer. + * If VAR_KEEP is also set then we want to keep str(?) as is. + */ + if (!(v->flags & VAR_KEEP)) { + if (*freePtr != NULL) { + free(*freePtr); + *freePtr = NULL; + } + if (dynamic) { + nstr = bmake_strldup(str, (size_t)*lengthPtr); + *freePtr = nstr; + } else { + nstr = (eflags & VARE_UNDEFERR) ? var_Error : varNoError; + } + } + if (nstr != Buf_GetAll(&v->val, NULL)) + Buf_Destroy(&v->val, TRUE); + free(v->name); + free(v); + } + return nstr; +} + +/* 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. + */ +char * +Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags) +{ + Buffer buf; /* Buffer for forming things */ + Boolean trailingBslash; + + /* 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; + trailingBslash = FALSE; /* variable ends in \ */ + + while (*str) { + if (*str == '\n' && trailingBslash) + Buf_AddByte(&buf, ' '); + + if (*str == '$' && str[1] == '$') { + /* + * A dollar sign may be escaped with another dollar sign. + * In such a case, we skip over the escape character and store the + * dollar sign into the buffer directly. + */ + if (save_dollars && (eflags & VARE_ASSIGN)) + Buf_AddByte(&buf, '$'); + Buf_AddByte(&buf, '$'); + str += 2; + } else if (*str != '$') { + /* + * Skip as many characters as possible -- either to the end of + * the string or to the next dollar sign (variable invocation). + */ + const char *cp; + + for (cp = str++; *str != '$' && *str != '\0'; str++) + continue; + Buf_AddBytesBetween(&buf, cp, str); + } else { + int length; + void *freeIt; + const char *val = Var_Parse(str, ctxt, eflags, &length, &freeIt); + + if (val == var_Error || val == varNoError) { + /* + * 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) { + str += length; + } 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\"", + length, str); + } + str += length; + errorReported = TRUE; + } else { + Buf_AddByte(&buf, *str); + str += 1; + } + } else { + size_t val_len; + + str += length; + + val_len = strlen(val); + Buf_AddBytes(&buf, val, val_len); + trailingBslash = val_len > 0 && val[val_len - 1] == '\\'; + } + free(freeIt); + freeIt = NULL; + } + } + + return Buf_DestroyCompact(&buf); +} + +/* Initialize the module. */ +void +Var_Init(void) +{ + VAR_INTERNAL = Targ_NewGN("Internal"); + VAR_GLOBAL = Targ_NewGN("Global"); + VAR_CMD = Targ_NewGN("Command"); +} + + +void +Var_End(void) +{ + Var_Stats(); +} + +void +Var_Stats(void) +{ + Hash_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL"); +} + + +/****************** PRINT DEBUGGING INFO *****************/ +static void +VarPrintVar(void *vp, void *data MAKE_ATTR_UNUSED) +{ + Var *v = (Var *)vp; + fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL)); +} + +/* Print all variables in a context, unordered. */ +void +Var_Dump(GNode *ctxt) +{ + Hash_ForEach(&ctxt->context, VarPrintVar, NULL); +} Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/configure =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/x-shellscript Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/configure.in =================================================================== --- vendor/NetBSD/bmake/20200902/configure.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/configure.in (revision 365363) @@ -0,0 +1,433 @@ +dnl +dnl RCSid: +dnl $Id: configure.in,v 1.66 2020/07/10 16:34:38 sjg Exp $ +dnl +dnl Process this file with autoconf to produce a configure script +dnl +AC_PREREQ(2.50) +AC_INIT([bmake], [20200710], [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 dissable 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 dissable 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_INCLUDES_DEFAULT +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 + +#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/20200902/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/20200902/filemon/filemon.h =================================================================== --- vendor/NetBSD/bmake/20200902/filemon/filemon.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/filemon/filemon.h (revision 365363) @@ -0,0 +1,53 @@ +/* $NetBSD: filemon.h,v 1.2 2020/01/22 22:10:36 sjg 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 FILEMON_H_ +#define 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 /* FILEMON_H_ */ Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/filemon/filemon_ktrace.c =================================================================== --- vendor/NetBSD/bmake/20200902/filemon/filemon_ktrace.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/filemon/filemon_ktrace.c (revision 365363) @@ -0,0 +1,878 @@ +/* $NetBSD: filemon_ktrace.c,v 1.2 2020/01/19 20:22:57 riastradh 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 = 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 = 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 = args[0]; + flags = 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/20200902/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/20200902/meta.h =================================================================== --- vendor/NetBSD/bmake/20200902/meta.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/meta.h (revision 365363) @@ -0,0 +1,59 @@ +/* $NetBSD: meta.h,v 1.7 2020/07/03 08:13:23 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; + +extern Boolean useMeta; + +struct Job; /* not defined yet */ +void meta_init(void); +void meta_finish(void); +void meta_mode_init(const char *); +void meta_job_start(struct Job *, GNode *); +void meta_job_child(struct Job *); +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); Property changes on: vendor/NetBSD/bmake/20200902/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/20200902/dirname.c =================================================================== --- vendor/NetBSD/bmake/20200902/dirname.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/dirname.c (revision 365363) @@ -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/20200902/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/20200902/Makefile.config.in =================================================================== --- vendor/NetBSD/bmake/20200902/Makefile.config.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/Makefile.config.in (revision 365363) @@ -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/20200902/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/20200902/boot-strap =================================================================== --- vendor/NetBSD/bmake/20200902/boot-strap (nonexistent) +++ vendor/NetBSD/bmake/20200902/boot-strap (revision 365363) @@ -0,0 +1,475 @@ +: +# 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.51 2020/02/19 16:46:23 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` + echo You can install by running: + echo + echo $0 $cmd_args op=install + echo + echo "Use --install-prefix=/something to install somewhere other than $prefix" + echo "Use --install-destdir=/somewhere to set DESTDIR during install" + echo "Use --install-host-target to use INSTALL_BIN=$HOST_TARGET/bin" + echo "Use -DWITH_PROG_VERSION to install as bmake-$MAKE_VERSION" + echo "Use -DWITHOUT_PROG_LINK to suppress bmake -> bmake-$MAKE_VERSION symlink" + echo "Use -DWITHOUT_INSTALL_MK to skip installing files to $prefix/share/mk" + fi +} + +op_$op +exit 0 Property changes on: vendor/NetBSD/bmake/20200902/boot-strap ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/config.h.in =================================================================== --- vendor/NetBSD/bmake/20200902/config.h.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/config.h.in (revision 365363) @@ -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/20200902/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/20200902/make-bootstrap.sh.in =================================================================== --- vendor/NetBSD/bmake/20200902/make-bootstrap.sh.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/make-bootstrap.sh.in (revision 365363) @@ -0,0 +1,101 @@ +#!/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 for.o getopt hash.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" + +LST_OBJECTS="lstAppend.o lstDupl.o lstInit.o lstOpen.o \ +lstAtEnd.o lstEnQueue.o lstInsert.o lstAtFront.o lstIsAtEnd.o \ +lstClose.o lstFind.o lstIsEmpty.o lstRemove.o lstConcat.o \ +lstFindFrom.o lstLast.o lstReplace.o lstFirst.o lstDatum.o \ +lstForEach.o lstMember.o lstSucc.o lstDeQueue.o lstForEachFrom.o \ +lstDestroy.o lstNext.o lstPrev.o" + +LIB_OBJECTS="@LIBOBJS@" + +do_compile main.o ${MDEFS} + +for o in ${BASE_OBJECTS} ${LST_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/20200902/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/20200902/aclocal.m4 =================================================================== --- vendor/NetBSD/bmake/20200902/aclocal.m4 (nonexistent) +++ vendor/NetBSD/bmake/20200902/aclocal.m4 (revision 365363) @@ -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/20200902/stresep.c =================================================================== --- vendor/NetBSD/bmake/20200902/stresep.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/stresep.c (revision 365363) @@ -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/20200902/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/20200902/machine.sh =================================================================== --- vendor/NetBSD/bmake/20200902/machine.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/machine.sh (revision 365363) @@ -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/20200902/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/20200902/PSD.doc/tutorial.ms =================================================================== --- vendor/NetBSD/bmake/20200902/PSD.doc/tutorial.ms (nonexistent) +++ vendor/NetBSD/bmake/20200902/PSD.doc/tutorial.ms (revision 365363) @@ -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/20200902/PSD.doc/Makefile =================================================================== --- vendor/NetBSD/bmake/20200902/PSD.doc/Makefile (nonexistent) +++ vendor/NetBSD/bmake/20200902/PSD.doc/Makefile (revision 365363) @@ -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/20200902/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/20200902/README =================================================================== --- vendor/NetBSD/bmake/20200902/README (nonexistent) +++ vendor/NetBSD/bmake/20200902/README (revision 365363) @@ -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/20200902/getopt.c =================================================================== --- vendor/NetBSD/bmake/20200902/getopt.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/getopt.c (revision 365363) @@ -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/20200902/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/20200902/makefile.in =================================================================== --- vendor/NetBSD/bmake/20200902/makefile.in (nonexistent) +++ vendor/NetBSD/bmake/20200902/makefile.in (revision 365363) @@ -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/20200902/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/20200902/realpath.c =================================================================== --- vendor/NetBSD/bmake/20200902/realpath.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/realpath.c (revision 365363) @@ -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/20200902/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/20200902/find_lib.sh =================================================================== --- vendor/NetBSD/bmake/20200902/find_lib.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/find_lib.sh (revision 365363) @@ -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/20200902/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/20200902/install-sh =================================================================== --- vendor/NetBSD/bmake/20200902/install-sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/install-sh (revision 365363) @@ -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/20200902/install-sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: vendor/NetBSD/bmake/20200902/mkdeps.sh =================================================================== --- vendor/NetBSD/bmake/20200902/mkdeps.sh (nonexistent) +++ vendor/NetBSD/bmake/20200902/mkdeps.sh (revision 365363) @@ -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/20200902/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/20200902/pathnames.h =================================================================== --- vendor/NetBSD/bmake/20200902/pathnames.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/pathnames.h (revision 365363) @@ -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/20200902/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/20200902/ranlib.h =================================================================== --- vendor/NetBSD/bmake/20200902/ranlib.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/ranlib.h (revision 365363) @@ -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/20200902/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/20200902/setenv.c =================================================================== --- vendor/NetBSD/bmake/20200902/setenv.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/setenv.c (revision 365363) @@ -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/20200902/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/20200902/sigcompat.c =================================================================== --- vendor/NetBSD/bmake/20200902/sigcompat.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/sigcompat.c (revision 365363) @@ -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/20200902/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/20200902/strlcpy.c =================================================================== --- vendor/NetBSD/bmake/20200902/strlcpy.c (nonexistent) +++ vendor/NetBSD/bmake/20200902/strlcpy.c (revision 365363) @@ -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/20200902/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/20200902/trace.h =================================================================== --- vendor/NetBSD/bmake/20200902/trace.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/trace.h (revision 365363) @@ -0,0 +1,49 @@ +/* $NetBSD: trace.h,v 1.3 2008/04/28 20:24:14 martin 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 { + 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/20200902/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/20200902/wait.h =================================================================== --- vendor/NetBSD/bmake/20200902/wait.h (nonexistent) +++ vendor/NetBSD/bmake/20200902/wait.h (revision 365363) @@ -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/20200902/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