Update to bmake-20200902

Lots of code refactoring, simplification and cleanup.
Lots of new unit-tests providing much higher code coverage.
All courtesy of rillig at netbsd.

Other significant changes:

o new read-only variable .SHELL which provides the path of the shell
  used to run scripts (as defined by  the .SHELL target).

o variable parsing detects more errors.

o new debug option -dl: LINT mode, does the equivalent of := for all
  variable assignments so that file and line number are reported for
  variable parse errors.
This commit is contained in:
Simon J. Gerraty 2020-09-05 19:29:42 +00:00
commit 2c3632d14f
660 changed files with 15351 additions and 11022 deletions

View File

@ -1,3 +1,243 @@
2020-09-02 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200802
Merge with NetBSD make, pick up
o more unit tests
2020-08-01 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* VERSION (_MAKE_VERSION): 20200728
Merge with NetBSD make, pick up
o var.c: more optimizations
2020-07-26 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* bsd.after-import.mk: make sure we update unit-tests/Makefile
2020-07-10 Simon J Gerraty <sjg@beast.crufty.net>
* configure.in: use AC_INCLUDES_DEFAULT rather than AC_HEADER_STDC

View File

@ -23,6 +23,8 @@ configure.in
dir.c
dir.h
dirname.c
enum.c
enum.h
filemon/filemon.h
filemon/filemon_dev.c
filemon/filemon_ktrace.c
@ -34,36 +36,8 @@ hash.h
install-sh
job.c
job.h
lst.c
lst.h
lst.lib/Makefile
lst.lib/lstAppend.c
lst.lib/lstAtEnd.c
lst.lib/lstAtFront.c
lst.lib/lstClose.c
lst.lib/lstConcat.c
lst.lib/lstDatum.c
lst.lib/lstDeQueue.c
lst.lib/lstDestroy.c
lst.lib/lstDupl.c
lst.lib/lstEnQueue.c
lst.lib/lstFind.c
lst.lib/lstFindFrom.c
lst.lib/lstFirst.c
lst.lib/lstForEach.c
lst.lib/lstForEachFrom.c
lst.lib/lstInit.c
lst.lib/lstInsert.c
lst.lib/lstInt.h
lst.lib/lstIsAtEnd.c
lst.lib/lstIsEmpty.c
lst.lib/lstLast.c
lst.lib/lstMember.c
lst.lib/lstNext.c
lst.lib/lstOpen.c
lst.lib/lstPrev.c
lst.lib/lstRemove.c
lst.lib/lstReplace.c
lst.lib/lstSucc.c
machine.sh
main.c
make-bootstrap.sh.in
@ -88,7 +62,6 @@ ranlib.h
realpath.c
setenv.c
sigcompat.c
sprite.h
str.c
stresep.c
strlcpy.c
@ -100,22 +73,234 @@ 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/cond-late.mk
unit-tests/cond-late.exp
unit-tests/cond-short.mk
unit-tests/cond-short.exp
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
@ -124,6 +309,8 @@ 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
@ -138,6 +325,10 @@ 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
@ -146,12 +337,62 @@ unit-tests/modmatch.exp
unit-tests/modmatch.mk
unit-tests/modmisc.exp
unit-tests/modmisc.mk
unit-tests/modorder.exp
unit-tests/modorder.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
@ -162,6 +403,28 @@ 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
@ -174,12 +437,204 @@ 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

View File

@ -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 <rillig@NetBSD.org>
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 <Todd.Miller@courtesan.com>
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 <YEAR> <COPYRIGHT HOLDER>
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.

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.107 2020/06/07 21:18:46 sjg Exp $
# $Id: Makefile,v 1.112 2020/08/28 16:26:17 sjg Exp $
PROG= bmake
@ -8,9 +8,11 @@ SRCS= \
compat.c \
cond.c \
dir.c \
enum.c \
for.c \
hash.c \
job.c \
lst.c \
main.c \
make.c \
make_malloc.c \
@ -25,36 +27,6 @@ SRCS= \
util.c \
var.c
# from lst.lib/
SRCS+= \
lstAppend.c \
lstAtEnd.c \
lstAtFront.c \
lstClose.c \
lstConcat.c \
lstDatum.c \
lstDeQueue.c \
lstDestroy.c \
lstDupl.c \
lstEnQueue.c \
lstFind.c \
lstFindFrom.c \
lstFirst.c \
lstForEach.c \
lstForEachFrom.c \
lstInit.c \
lstInsert.c \
lstIsAtEnd.c \
lstIsEmpty.c \
lstLast.c \
lstMember.c \
lstNext.c \
lstOpen.c \
lstPrev.c \
lstRemove.c \
lstReplace.c \
lstSucc.c
.-include "VERSION"
.-include "Makefile.inc"
@ -97,7 +69,6 @@ COPTS.filemon_dev.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
.endif # USE_FILEMON
.PATH: ${srcdir}
.PATH: ${srcdir}/lst.lib
.if make(obj) || make(clean)
SUBDIR+= unit-tests
@ -109,7 +80,7 @@ SUBDIR+= unit-tests
# list of OS's which are derrived from BSD4.4
BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly MirBSD Bitrig
# we are...
OS!= uname -s
OS := ${.MAKE.OS:U${uname -s:L:sh}}
# are we 4.4BSD ?
isBSD44:=${BSD44_LIST:M${OS}}
@ -237,5 +208,8 @@ install-mk:
# end-delete2
# A simple unit-test driver to help catch regressions
TEST_MAKE ?= ${.OBJDIR}/${PROG:T}
accept test:
cd ${.CURDIR}/unit-tests && MAKEFLAGS= ${.MAKE} -r -m / TEST_MAKE=${TEST_MAKE:U${.OBJDIR}/${PROG:T}} ${.TARGET}
cd ${.CURDIR}/unit-tests && \
MAKEFLAGS= ${TEST_MAKE} -r -m / ${.TARGET} ${TESTS:DTESTS=${TESTS:Q}}

View File

@ -1,2 +1,2 @@
# keep this compatible with sh and make
_MAKE_VERSION=20200710
_MAKE_VERSION=20200902

View File

@ -1,4 +1,4 @@
/* $NetBSD: arch.c,v 1.73 2020/07/03 08:02:55 rillig Exp $ */
/* $NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: arch.c,v 1.73 2020/07/03 08:02:55 rillig Exp $";
static char rcsid[] = "$NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#else
__RCSID("$NetBSD: arch.c,v 1.73 2020/07/03 08:02:55 rillig Exp $");
__RCSID("$NetBSD: arch.c,v 1.107 2020/08/30 11:15:05 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -94,7 +94,7 @@ __RCSID("$NetBSD: arch.c,v 1.73 2020/07/03 08:02:55 rillig Exp $");
* 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.
* FAILURE is returned if the specification is
* FALSE is returned if the specification is
* invalid for some reason.
*
* Arch_Touch Alter the modification time of the archive
@ -184,12 +184,9 @@ typedef struct Arch {
size_t fnamesize; /* Size of the string table */
} Arch;
static int ArchFindArchive(const void *, const void *);
#ifdef CLEANUP
static void ArchFree(void *);
#endif
static struct ar_hdr *ArchStatMember(char *, char *, Boolean);
static FILE *ArchFindMember(char *, char *, struct ar_hdr *, const char *);
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 *);
@ -225,19 +222,6 @@ static int ArchSVR4Entry(Arch *, char *, size_t, FILE *);
#define AR_MAX_NAME_LEN (sizeof(arh.AR_NAME)-1)
#ifdef CLEANUP
/*-
*-----------------------------------------------------------------------
* ArchFree --
* Free memory used by an archive
*
* Results:
* None.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
static void
ArchFree(void *ap)
{
@ -272,23 +256,18 @@ ArchFree(void *ap)
* ctxt Context in which to expand variables
*
* Results:
* SUCCESS if it was a valid specification. The linePtr is updated
* 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.
*
* Side Effects:
* Some nodes may be created. The given list is extended.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
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 *nameBuf; /* temporary place for node name */
char saveChar; /* Ending delimiter of member-name */
Boolean subLibName; /* TRUE if libName should have/had
* variable substitution performed on it */
@ -304,26 +283,25 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
* so we can safely advance beyond it...
*/
int length;
void *freeIt;
char *result;
void *result_freeIt;
const char *result;
Boolean isError;
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
&length, &freeIt);
free(freeIt);
result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES,
&length, &result_freeIt);
isError = result == var_Error;
free(result_freeIt);
if (isError)
return FALSE;
if (result == var_Error) {
return FAILURE;
} else {
subLibName = TRUE;
}
cp += length-1;
subLibName = TRUE;
cp += length - 1;
}
}
*cp++ = '\0';
if (subLibName) {
libName = Var_Subst(NULL, libName, ctxt, VARF_UNDEFERR|VARF_WANTRES);
libName = Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES);
}
@ -347,18 +325,18 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
*/
int length;
void *freeIt;
char *result;
const char *result;
Boolean isError;
result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES,
result = Var_Parse(cp, ctxt, VARE_UNDEFERR|VARE_WANTRES,
&length, &freeIt);
isError = result == var_Error;
free(freeIt);
if (result == var_Error) {
return FAILURE;
} else {
doSubst = TRUE;
}
if (isError)
return FALSE;
doSubst = TRUE;
cp += length;
} else {
cp++;
@ -372,7 +350,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
*/
if (*cp == '\0') {
printf("No closing parenthesis in archive specification\n");
return FAILURE;
return FALSE;
}
/*
@ -401,20 +379,15 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
char *buf;
char *sacrifice;
char *oldMemName = memName;
size_t sz;
memName = Var_Subst(NULL, memName, ctxt,
VARF_UNDEFERR|VARF_WANTRES);
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.
*/
sz = strlen(memName)+strlen(libName)+3;
buf = sacrifice = bmake_malloc(sz);
snprintf(buf, sz, "%s(%s)", libName, memName);
buf = sacrifice = str_concat4(libName, "(", memName, ")");
if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) {
/*
@ -426,42 +399,43 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
if (gn == NULL) {
free(buf);
return FAILURE;
return FALSE;
} else {
gn->type |= OP_ARCHV;
(void)Lst_AtEnd(nodeLst, gn);
Lst_Append(nodeLst, gn);
}
} else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) {
} else if (!Arch_ParseArchive(&sacrifice, nodeLst, ctxt)) {
/*
* Error in nested call -- free buffer and return FAILURE
* Error in nested call -- free buffer and return FALSE
* ourselves.
*/
free(buf);
return FAILURE;
return FALSE;
}
/*
* Free buffer and continue with our work.
*/
free(buf);
} else if (Dir_HasWildcards(memName)) {
Lst members = Lst_Init(FALSE);
char *member;
size_t sz = MAXPATHLEN, nsz;
nameBuf = bmake_malloc(sz);
Lst members = Lst_Init();
Buffer nameBuf;
Buf_Init(&nameBuf, 0);
Dir_Expand(memName, dirSearchPath, members);
while (!Lst_IsEmpty(members)) {
member = (char *)Lst_DeQueue(members);
nsz = strlen(libName) + strlen(member) + 3;
if (sz > nsz)
nameBuf = bmake_realloc(nameBuf, sz = nsz * 2);
char *member = Lst_Dequeue(members);
snprintf(nameBuf, sz, "%s(%s)", libName, member);
Buf_Empty(&nameBuf);
Buf_AddStr(&nameBuf, libName);
Buf_AddStr(&nameBuf, "(");
Buf_AddStr(&nameBuf, member);
Buf_AddStr(&nameBuf, ")");
free(member);
gn = Targ_FindNode(nameBuf, TARG_CREATE);
gn = Targ_FindNode(Buf_GetAll(&nameBuf, NULL), TARG_CREATE);
if (gn == NULL) {
free(nameBuf);
return FAILURE;
Buf_Destroy(&nameBuf, TRUE);
return FALSE;
} else {
/*
* We've found the node, but have to make sure the rest of
@ -471,19 +445,24 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
* end of the provided list.
*/
gn->type |= OP_ARCHV;
(void)Lst_AtEnd(nodeLst, gn);
Lst_Append(nodeLst, gn);
}
}
Lst_Destroy(members, NULL);
free(nameBuf);
Lst_Free(members);
Buf_Destroy(&nameBuf, TRUE);
} else {
size_t sz = strlen(libName) + strlen(memName) + 3;
nameBuf = bmake_malloc(sz);
snprintf(nameBuf, sz, "%s(%s)", libName, memName);
gn = Targ_FindNode(nameBuf, TARG_CREATE);
free(nameBuf);
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 FAILURE;
return FALSE;
} else {
/*
* We've found the node, but have to make sure the rest of the
@ -493,7 +472,7 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
* provided list.
*/
gn->type |= OP_ARCHV;
(void)Lst_AtEnd(nodeLst, gn);
Lst_Append(nodeLst, gn);
}
}
if (doSubst) {
@ -520,31 +499,15 @@ Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt)
} while (*cp != '\0' && isspace ((unsigned char)*cp));
*linePtr = cp;
return SUCCESS;
return TRUE;
}
/*-
*-----------------------------------------------------------------------
* ArchFindArchive --
* See if the given archive is the one we are looking for. Called
* From ArchStatMember and ArchFindMember via Lst_Find.
*
* Input:
* ar Current list element
* archName Name we want
*
* Results:
* 0 if it is, non-zero if it isn't.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
static int
ArchFindArchive(const void *ar, const void *archName)
/* 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(archName, ((const Arch *)ar)->name);
return strcmp(((const Arch *)ar)->name, desiredName) == 0;
}
/*-
@ -565,24 +528,20 @@ ArchFindArchive(const void *ar, const void *archName)
* 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...
*
* Side Effects:
*
*-----------------------------------------------------------------------
*/
static struct ar_hdr *
ArchStatMember(char *archive, char *member, Boolean hash)
ArchStatMember(const char *archive, const char *member, Boolean hash)
{
FILE * arch; /* Stream to archive */
int size; /* Size of archive member */
char *cp; /* Useful character pointer */
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. */
/* Current member name while hashing. */
/*
* Because of space constraints and similar things, files are archived
@ -590,14 +549,14 @@ ArchStatMember(char *archive, char *member, Boolean hash)
* to point 'member' to the final component, if there is one, to make
* the comparisons easier...
*/
cp = strrchr(member, '/');
if (cp != NULL) {
member = cp + 1;
const char *base = strrchr(member, '/');
if (base != NULL) {
member = base + 1;
}
ln = Lst_Find(archives, archive, ArchFindArchive);
ln = Lst_Find(archives, ArchFindArchive, archive);
if (ln != NULL) {
ar = (Arch *)Lst_Datum(ln);
ar = LstNode_Datum(ln);
he = Hash_FindEntry(&ar->members, member);
@ -610,8 +569,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
if (len > AR_MAX_NAME_LEN) {
len = AR_MAX_NAME_LEN;
strncpy(copy, member, AR_MAX_NAME_LEN);
copy[AR_MAX_NAME_LEN] = '\0';
snprintf(copy, sizeof copy, "%s", member);
}
if ((he = Hash_FindEntry(&ar->members, copy)) != NULL)
return (struct ar_hdr *)Hash_GetValue(he);
@ -653,7 +611,7 @@ ArchStatMember(char *archive, char *member, Boolean hash)
* can handle...
*/
if ((fread(magic, SARMAG, 1, arch) != 1) ||
(strncmp(magic, ARMAG, SARMAG) != 0)) {
(strncmp(magic, ARMAG, SARMAG) != 0)) {
fclose(arch);
return NULL;
}
@ -673,6 +631,8 @@ ArchStatMember(char *archive, char *member, Boolean hash)
*/
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
@ -680,13 +640,14 @@ ArchStatMember(char *archive, char *member, Boolean hash)
* 'size' field of the header and round it up during the seek.
*/
arh.AR_SIZE[sizeof(arh.AR_SIZE)-1] = '\0';
size = (int)strtol(arh.AR_SIZE, NULL, 10);
size = (size_t)strtol(arh.ar_size, NULL, 10);
memcpy(memName, arh.AR_NAME, sizeof(arh.AR_NAME));
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {
continue;
nameend = memName + AR_MAX_NAME_LEN;
while (*nameend == ' ') {
nameend--;
}
cp[1] = '\0';
nameend[1] = '\0';
#ifdef SVR4ARCHIVES
/*
@ -706,8 +667,8 @@ ArchStatMember(char *archive, char *member, Boolean hash)
}
}
else {
if (cp[0] == '/')
cp[0] = '\0';
if (nameend[0] == '/')
nameend[0] = '\0';
}
#endif
@ -719,11 +680,11 @@ ArchStatMember(char *archive, char *member, Boolean hash)
if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
isdigit((unsigned char)memName[sizeof(AR_EFMT1) - 1])) {
unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
if (elen > MAXPATHLEN)
if ((unsigned int)elen > MAXPATHLEN)
goto badarch;
if (fread(memName, elen, 1, arch) != 1)
if (fread(memName, (size_t)elen, 1, arch) != 1)
goto badarch;
memName[elen] = '\0';
if (fseek(arch, -elen, SEEK_CUR) != 0)
@ -738,13 +699,13 @@ ArchStatMember(char *archive, char *member, Boolean hash)
Hash_SetValue(he, bmake_malloc(sizeof(struct ar_hdr)));
memcpy(Hash_GetValue(he), &arh, sizeof(struct ar_hdr));
}
if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0)
if (fseek(arch, ((long)size + 1) & ~1, SEEK_CUR) != 0)
goto badarch;
}
fclose(arch);
(void)Lst_AtEnd(archives, ar);
Lst_Append(archives, ar);
/*
* Now that the archive has been read and cached, we can look into
@ -774,17 +735,14 @@ ArchStatMember(char *archive, char *member, Boolean hash)
* If it is "//", then load the table of filenames
* If it is "/<offset>", 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
*
* Side Effects:
* If a table is read, the file pointer is moved to the next archive
* member
*
*-----------------------------------------------------------------------
*/
static int
@ -834,7 +792,7 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
}
if (DEBUG(ARCH)) {
fprintf(debug_file, "Found svr4 archive name table with %lu entries\n",
(unsigned long)entry);
(unsigned long)entry);
}
return 0;
}
@ -861,8 +819,7 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
fprintf(debug_file, "Replaced %s with %s\n", name, &ar->fnametab[entry]);
}
(void)strncpy(name, &ar->fnametab[entry], MAXPATHLEN);
name[MAXPATHLEN] = '\0';
snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]);
return 1;
}
#endif
@ -874,6 +831,7 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
* 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
@ -886,21 +844,17 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
* 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.
*
* Side Effects:
* The passed struct ar_hdr structure is filled in.
*
*-----------------------------------------------------------------------
*/
static FILE *
ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
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 *cp; /* Useful character pointer */
char magic[SARMAG];
size_t len, tlen;
const char * base;
arch = fopen(archive, mode);
if (arch == NULL) {
@ -912,7 +866,7 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
* can handle...
*/
if ((fread(magic, SARMAG, 1, arch) != 1) ||
(strncmp(magic, ARMAG, SARMAG) != 0)) {
(strncmp(magic, ARMAG, SARMAG) != 0)) {
fclose(arch);
return NULL;
}
@ -923,9 +877,9 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
* to point 'member' to the final component, if there is one, to make
* the comparisons easier...
*/
cp = strrchr(member, '/');
if (cp != NULL) {
member = cp + 1;
base = strrchr(member, '/');
if (base != NULL) {
member = base + 1;
}
len = tlen = strlen(member);
if (len > sizeof(arhPtr->AR_NAME)) {
@ -958,7 +912,7 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
* the file at the actual member, rather than its header, but
* not here...
*/
if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) != 0) {
if (fseek(arch, -(long)sizeof(struct ar_hdr), SEEK_CUR) != 0) {
fclose(arch);
return NULL;
}
@ -974,14 +928,14 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
sizeof(AR_EFMT1) - 1) == 0 &&
isdigit((unsigned char)arhPtr->AR_NAME[sizeof(AR_EFMT1) - 1])) {
unsigned int elen = atoi(&arhPtr->AR_NAME[sizeof(AR_EFMT1)-1]);
int elen = atoi(&arhPtr->AR_NAME[sizeof(AR_EFMT1)-1]);
char ename[MAXPATHLEN + 1];
if (elen > MAXPATHLEN) {
if ((unsigned int)elen > MAXPATHLEN) {
fclose(arch);
return NULL;
}
if (fread(ename, elen, 1, arch) != 1) {
if (fread(ename, (size_t)elen, 1, arch) != 1) {
fclose(arch);
return NULL;
}
@ -991,7 +945,7 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
}
if (strncmp(ename, member, len) == 0) {
/* Found as extended name */
if (fseek(arch, -sizeof(struct ar_hdr) - elen,
if (fseek(arch, -(long)sizeof(struct ar_hdr) - elen,
SEEK_CUR) != 0) {
fclose(arch);
return NULL;
@ -1035,18 +989,15 @@ ArchFindMember(char *archive, char *member, struct ar_hdr *arhPtr,
*-----------------------------------------------------------------------
* 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.
*
* Side Effects:
* The modification time of the entire archive is also changed.
* For a library, this could necessitate the re-ranlib'ing of the
* whole thing.
*
*-----------------------------------------------------------------------
*/
void
@ -1060,8 +1011,8 @@ Arch_Touch(GNode *gn)
Var_Value(MEMBER, gn, &p2),
&arh, "r+");
free(p1);
free(p2);
bmake_free(p1);
bmake_free(p2);
snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now);
@ -1071,37 +1022,24 @@ Arch_Touch(GNode *gn)
}
}
/*-
*-----------------------------------------------------------------------
* Arch_TouchLib --
* Given a node which represents a library, touch the thing, making
* sure that the table of contents also is touched.
/* 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
*
* Results:
* None.
*
* Side Effects:
* Both the modification time of the library and of the RANLIBMAG
* member are set to 'now'.
*
*-----------------------------------------------------------------------
*/
void
#if !defined(RANLIBMAG)
Arch_TouchLib(GNode *gn MAKE_ATTR_UNUSED)
#else
Arch_TouchLib(GNode *gn)
#endif
{
#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, UNCONST(RANLIBMAG), &arh, "r+");
arch = ArchFindMember(gn->path, RANLIBMAG, &arh, "r+");
snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long) now);
if (arch != NULL) {
@ -1111,25 +1049,16 @@ Arch_TouchLib(GNode *gn)
times.actime = times.modtime = now;
utime(gn->path, &times);
}
#else
(void)gn;
#endif
}
/*-
*-----------------------------------------------------------------------
* Arch_MTime --
* Return the modification time of a member of an archive.
/* 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
*
* Results:
* The modification time(seconds).
*
* Side Effects:
* The mtime field of the given node is filled in with the value
* returned by the function.
*
*-----------------------------------------------------------------------
*/
time_t
Arch_MTime(GNode *gn)
@ -1142,8 +1071,8 @@ Arch_MTime(GNode *gn)
Var_Value(MEMBER, gn, &p2),
TRUE);
free(p1);
free(p2);
bmake_free(p1);
bmake_free(p2);
if (arhPtr != NULL) {
modTime = (time_t)strtol(arhPtr->AR_DATE, NULL, 10);
@ -1155,34 +1084,17 @@ Arch_MTime(GNode *gn)
return modTime;
}
/*-
*-----------------------------------------------------------------------
* Arch_MemMTime --
* Given a non-existent archive member's node, get its modification
* time from its archived form, if it exists.
*
* Results:
* The modification time.
*
* Side Effects:
* The mtime field is filled in.
*
*-----------------------------------------------------------------------
*/
/* 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;
char *nameStart,
*nameEnd;
if (Lst_Open(gn->parents) != SUCCESS) {
gn->mtime = 0;
return 0;
}
Lst_Open(gn->parents);
while ((ln = Lst_Next(gn->parents)) != NULL) {
pgn = (GNode *)Lst_Datum(ln);
pgn = LstNode_Datum(ln);
if (pgn->type & OP_ARCHV) {
/*
@ -1192,12 +1104,13 @@ Arch_MemMTime(GNode *gn)
* child. We keep searching its parents in case some other
* parent requires this child to exist...
*/
nameStart = strchr(pgn->name, '(') + 1;
nameEnd = strchr(nameStart, ')');
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, nameEnd - nameStart) == 0) {
gn->mtime = Arch_MTime(pgn);
strncmp(nameStart, gn->name, nameLen) == 0) {
gn->mtime = Arch_MTime(pgn);
}
} else if (pgn->flags & REMAKE) {
/*
@ -1214,29 +1127,20 @@ Arch_MemMTime(GNode *gn)
return gn->mtime;
}
/*-
*-----------------------------------------------------------------------
* Arch_FindLib --
* Search for a library along the given search path.
/* 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
*
* Results:
* None.
*
* Side Effects:
* 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 .LIBRARIES 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.
*
*-----------------------------------------------------------------------
*/
void
Arch_FindLib(GNode *gn, Lst path)
@ -1258,44 +1162,38 @@ Arch_FindLib(GNode *gn, Lst path)
#endif /* LIBRARIES */
}
/*-
*-----------------------------------------------------------------------
* Arch_LibOODate --
* Decide if a node with the OP_LIB attribute is out-of-date. Called
* from Make_OODate to make its life easier.
/* 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.
* 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.
*
* Side Effects:
* The library will be hashed if it hasn't been already.
*
*-----------------------------------------------------------------------
*/
Boolean
Arch_LibOODate(GNode *gn)
@ -1315,7 +1213,7 @@ Arch_LibOODate(GNode *gn)
struct ar_hdr *arhPtr; /* Header for __.SYMDEF */
int modTimeTOC; /* The table-of-contents's mod time */
arhPtr = ArchStatMember(gn->path, UNCONST(RANLIBMAG), FALSE);
arhPtr = ArchStatMember(gn->path, RANLIBMAG, FALSE);
if (arhPtr != NULL) {
modTimeTOC = (int)strtol(arhPtr->AR_DATE, NULL, 10);
@ -1340,40 +1238,14 @@ Arch_LibOODate(GNode *gn)
return oodate;
}
/*-
*-----------------------------------------------------------------------
* Arch_Init --
* Initialize things for this module.
*
* Results:
* None.
*
* Side Effects:
* The 'archives' list is initialized.
*
*-----------------------------------------------------------------------
*/
/* Initialize things for this module. */
void
Arch_Init(void)
{
archives = Lst_Init(FALSE);
archives = Lst_Init();
}
/*-
*-----------------------------------------------------------------------
* Arch_End --
* Cleanup things for this module.
*
* Results:
* None.
*
* Side Effects:
* The 'archives' list is freed
*
*-----------------------------------------------------------------------
*/
/* Clean up things for this module. */
void
Arch_End(void)
{
@ -1382,35 +1254,22 @@ Arch_End(void)
#endif
}
/*-
*-----------------------------------------------------------------------
* Arch_IsLib --
* Check if the node is a library
*
* Results:
* True or False.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
int
Boolean
Arch_IsLib(GNode *gn)
{
static const char armag[] = "!<arch>\n";
char buf[sizeof(armag)-1];
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)) {
if (read(fd, buf, sizeof buf) != sizeof buf) {
(void)close(fd);
return FALSE;
}
(void)close(fd);
return memcmp(buf, armag, sizeof(buf)) == 0;
return memcmp(buf, armag, sizeof buf) == 0;
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.282 2020/06/06 20:28:42 wiz Exp $
.\" $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.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd June 5, 2020
.Dd August 28, 2020
.Dt BMAKE 1
.Os
.Sh NAME
@ -166,8 +166,15 @@ 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 @
@ -311,7 +318,8 @@ 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).
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
@ -412,37 +420,44 @@ or more sources.
This creates a relationship where the targets
.Dq depend
on the sources
and are usually created from them.
The exact relationship between the target and the source is determined
by the operator that separates them.
The three operators are as follows:
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 \&:
A target is considered out-of-date if its modification time is less than
those of any of its sources.
Sources for a target accumulate over dependency lines when this operator
is used.
The target is removed if
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.
is interrupted, the target is removed.
.It Ic \&!
Targets are always re-created, but not until all sources have been
examined and re-created as necessary.
Sources for a target accumulate over dependency lines when this operator
is used.
The target is removed if
.Nm
is interrupted.
The same, but the target is always re-created whether or not it is out
of date.
.It Ic \&::
If no sources are specified, the target is always re-created.
Otherwise, a target is considered out-of-date if any of its sources has
been modified more recently than the target.
Sources for a target do not accumulate over dependency lines when this
operator is used.
The target will not be removed if
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 \&? ,
@ -608,7 +623,7 @@ 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, parenthesis, or whitespace are really best avoided!
braces, parentheses, or whitespace are really best avoided!
.Pp
If the result of expanding a variable contains a dollar sign
.Pq Ql \&$
@ -1126,6 +1141,9 @@ is set to the value of
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
@ -1171,7 +1189,7 @@ 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
Select only those words that match
Selects only those words that match
.Ar pattern .
The standard shell wildcard characters
.Pf ( Ql * ,
@ -1195,11 +1213,11 @@ This is identical to
but selects all words which do not match
.Ar pattern .
.It Cm \&:O
Order every word in variable alphabetically.
Orders every word in variable alphabetically.
.It Cm \&:Or
Order every word in variable in reverse alphabetical order.
Orders every word in variable in reverse alphabetical order.
.It Cm \&:Ox
Randomize words in variable.
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 \&:=
@ -1249,7 +1267,7 @@ If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Compute a 32-bit hash of the value and encode it as hex digits.
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 ,
@ -1259,7 +1277,7 @@ If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:tA
Attempt to convert variable to an absolute path using
Attempts to convert variable to an absolute path using
.Xr realpath 3 ,
if that fails, the value is unchanged.
.It Cm \&:tl
@ -1271,7 +1289,7 @@ This modifier sets the separator to the character
If
.Ar c
is omitted, then no separator is used.
The common escapes (including octal numeric codes), work as expected.
The common escapes (including octal numeric codes) work as expected.
.It Cm \&:tu
Converts variable to upper-case letters.
.It Cm \&:tW
@ -1287,21 +1305,21 @@ See also
.Sm off
.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW
.Sm on
Modify the first occurrence of
Modifies the first occurrence of
.Ar old_string
in the variable's value, replacing it with
in each word of the variable's value, replacing it with
.Ar new_string .
If a
.Ql g
is appended to the last slash of the pattern, all occurrences
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 slash of the pattern, only the first word
is appended to the last delimiter of the pattern, only the first occurrence
is affected.
If a
.Ql W
is appended to the last slash of the pattern,
is appended to the last delimiter of the pattern,
then the value is treated as a single word
(possibly containing embedded white space).
If
@ -1370,13 +1388,6 @@ 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).
Note that
.Ql 1
and
.Ql g
are orthogonal; the former specifies whether multiple words are
potentially affected, the latter whether multiple substitutions can
potentially occur within each affected word.
.Pp
As for the
.Cm \&:S
@ -1387,9 +1398,9 @@ and
are subjected to variable expansion before being parsed as
regular expressions.
.It Cm \&:T
Replaces each word in the variable with its last component.
Replaces each word in the variable with its last path component.
.It Cm \&:u
Remove adjacent duplicate words (like
Removes adjacent duplicate words (like
.Xr uniq 1 ) .
.Sm off
.It Cm \&:\&? Ar true_string Cm \&: Ar false_string
@ -1405,7 +1416,7 @@ 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 is any words match "42" you need to use something like:
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
@ -1449,7 +1460,7 @@ in either the
or
.Ar old_string ,
only the first instance is treated specially (as the pattern character);
all subsequent instances are treated as regular characters
all subsequent instances are treated as regular characters.
.Pp
Variable expansion occurs in the normal fashion inside both
.Ar old_string
@ -1466,11 +1477,10 @@ This is the loop expansion mechanism from the OSF Development
Environment (ODE) make.
Unlike
.Cm \&.for
loops expansion occurs at the time of
reference.
Assign
loops, expansion occurs at the time of reference.
Assigns
.Ar temp
to each word in the variable and evaluate
to each word in the variable and evaluates
.Ar string .
The ODE convention is that
.Ar temp
@ -1481,7 +1491,7 @@ For example.
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
.It Cm \&:_[=var]
Save the current variable value in
Saves the current variable value in
.Ql $_
or the named
.Va var
@ -1502,7 +1512,7 @@ is used to save the result of the
modifier which is later referenced using the index values from
.Ql :range .
.It Cm \&:U Ns Ar newval
If the variable is undefined
If the variable is undefined,
.Ar newval
is the value.
If the variable is defined, the existing value is returned.
@ -1512,7 +1522,7 @@ It is handy for setting per-target CFLAGS for instance:
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
If the variable is defined,
.Ar newval
is the value.
.It Cm \&:L
@ -1641,7 +1651,7 @@ 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
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
@ -1687,7 +1697,7 @@ The possible conditionals are as follows:
The message is printed along with the name of the makefile and line number,
then
.Nm
will exit.
will exit immediately.
.It Ic .export Ar variable ...
Export the specified global variable.
If no variable list is provided, all globals are exported
@ -1876,7 +1886,7 @@ 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
variable is being compared against 0, or an empty string in the case
of a string comparison.
.Pp
When
@ -1917,7 +1927,7 @@ 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-rules
.It Aq make-lines
.It Ic \&.endfor
.El
.Pp
@ -1929,7 +1939,7 @@ On each iteration of the loop, one word is taken and assigned to each
in order, and these
.Ic variables
are substituted into the
.Ic make-rules
.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

View File

@ -89,9 +89,15 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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.
@ -188,7 +194,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
-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).
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
@ -260,25 +266,31 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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 usually created from them. The exact relationship
between the target and the source is determined by the operator that sep-
arates them. The three operators are as follows:
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:
: A target is considered out-of-date if its modification time is less
than those of any of its sources. Sources for a target accumulate
over dependency lines when this operator is used. The target is
removed if bmake is interrupted.
: 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.
! Targets are always re-created, but not until all sources have been
examined and re-created as necessary. Sources for a target accumu-
late over dependency lines when this operator is used. The target
is removed if bmake is interrupted.
! The same, but the target is always re-created whether or not it is
out of date.
:: If no sources are specified, the target is always re-created. Oth-
erwise, a target is considered out-of-date if any of its sources
has been modified more recently than the target. Sources for a
target do not accumulate over dependency lines when this operator
is used. The target will not be removed if bmake is interrupted.
:: 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
@ -374,7 +386,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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, parenthesis, or whitespace are really best
taining dollar, braces, parentheses, or whitespace are really best
avoided!
If the result of expanding a variable contains a dollar sign (`$') the
@ -729,6 +741,9 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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.
@ -765,7 +780,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
ponent.
:Mpattern
Select only those words that match pattern. The standard shell
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
@ -779,11 +794,11 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
This is identical to `:M', but selects all words which do not match
pattern.
:O Order every word in variable alphabetically.
:O Orders every word in variable alphabetically.
:Or Order every word in variable in reverse alphabetical order.
:Or Orders every word in variable in reverse alphabetical order.
:Ox Randomize words in variable. The results will be different each
: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,
@ -821,13 +836,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
utc value is not provided or is 0, the current time is used.
:hash
Compute a 32-bit hash of the value and encode it as hex digits.
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 Attempt to convert variable to an absolute path using realpath(3),
: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.
@ -836,7 +851,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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.
octal numeric codes) work as expected.
:tu Converts variable to upper-case letters.
@ -847,20 +862,20 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
white space. See also `:[@]'.
:S/old_string/new_string/[1gW]
Modify the first occurrence of old_string in the variable's value,
replacing it with new_string. If a `g' is appended to the last
slash of the pattern, all occurrences in each word are replaced. If
a `1' is appended to the last slash of the pattern, only the first
word is affected. If a `W' is appended to the last slash of the
pattern, then the value is treated as a single word (possibly con-
taining 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
(`\').
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
@ -878,16 +893,13 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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).
Note that `1' and `g' are orthogonal; the former specifies whether
multiple words are potentially affected, the latter whether multiple
substitutions can potentially occur within each affected word.
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 component.
:T Replaces each word in the variable with its last path component.
:u Remove adjacent duplicate words (like uniq(1)).
: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-
@ -898,7 +910,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
variable expansions. A common error is trying to use expressions
like
${NUMBERS:M42:?match:no}
which actually tests defined(NUMBERS), to determine is any words
which actually tests defined(NUMBERS), to determine if any words
match "42" you need to use something like:
${"${NUMBERS:M42}" != "":?match:no}.
@ -916,7 +928,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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
characters.
Variable expansion occurs in the normal fashion inside both
old_string and new_string with the single exception that a backslash
@ -925,17 +937,17 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
:@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. Assign temp to each word in the variable and evaluate
string. The ODE convention is that temp should start and end with a
period. For example.
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]
Save the current variable value in `$_' or the named var for later
Saves the current variable value in `$_' or the named var for later
reference. Example usage:
M_cmpv.units = 1 1000 1000000
@ -948,7 +960,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
later referenced using the index values from `:range'.
:Unewval
If the variable is undefined newval is the value. If the variable
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:
@ -957,7 +969,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
${VAR:D:Unewval}
:Dnewval
If the variable is defined newval is the value.
If the variable is defined, newval is the value.
:L The name of the variable is the value.
@ -1033,7 +1045,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
# Returns the number of words in the value.
INCLUDE STATEMENTS, CONDITIONALS AND FOR LOOPS
Makefile inclusion, conditional structures and for loops reminiscent of
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-
@ -1057,7 +1069,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
.error message
The message is printed along with the name of the makefile and
line number, then bmake will exit.
line number, then bmake will exit immediately.
.export variable ...
Export the specified global variable. If no variable list is
@ -1191,7 +1203,7 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
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
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
@ -1210,12 +1222,12 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
The syntax of a for loop is:
.for variable [variable ...] in expression
<make-rules>
<make-lines>
.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-rules inside
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.
@ -1556,4 +1568,4 @@ BMAKE(1) FreeBSD General Commands Manual BMAKE(1)
There is no way of escaping a space character in a filename.
FreeBSD 11.3 June 5, 2020 FreeBSD 11.3
FreeBSD 11.3 August 28, 2020 FreeBSD 11.3

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,4 +1,4 @@
# $Id: bsd.after-import.mk,v 1.15 2018/12/30 17:14:24 sjg Exp $
# $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.
@ -9,7 +9,7 @@
# The goal is to allow the benefits of autoconf without
# the overhead of running configure.
all: _makefile
all: _makefile _utmakefile
all: after-import
# we rely on bmake
@ -37,7 +37,9 @@ SRCTOP := ${srctop}
.endif
# This lets us match what boot-strap does
.if !defined(HOST_OS)
.if defined(.MAKE.OS)
HOST_OS:= ${.MAKE.OS}
.elif !defined(HOST_OS)
HOST_OS!= uname
.endif
@ -107,5 +109,18 @@ _makefile: bootstrap ${MAKEFILE}
@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 <bsd.obj.mk>

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.c,v 1.26 2020/07/03 08:02:55 rillig Exp $ */
/* $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.
@ -70,173 +70,123 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: buf.c,v 1.26 2020/07/03 08:02:55 rillig Exp $";
static char rcsid[] = "$NetBSD: buf.c,v 1.37 2020/08/23 08:21:50 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: buf.c,v 1.26 2020/07/03 08:02:55 rillig Exp $");
__RCSID("$NetBSD: buf.c,v 1.37 2020/08/23 08:21:50 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* buf.c --
* Functions for automatically-expanded buffers.
*/
/* Functions for automatically-expanded null-terminated buffers. */
#include "make.h"
#include "buf.h"
#include <limits.h>
#include "make.h"
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define BUF_DEF_SIZE 256 /* Default buffer size */
/*-
*-----------------------------------------------------------------------
* Buf_Expand_1 --
* Extend buffer for single byte add.
*
*-----------------------------------------------------------------------
*/
/* Extend the buffer for adding a single byte. */
void
Buf_Expand_1(Buffer *bp)
{
bp->size += max(bp->size, 16);
bp->size += MAX(bp->size, 16);
bp->buffer = bmake_realloc(bp->buffer, bp->size);
}
/*-
*-----------------------------------------------------------------------
* Buf_AddBytes --
* Add a number of bytes to the buffer.
*
* Results:
* None.
*
* Side Effects:
* Guess what?
*
*-----------------------------------------------------------------------
*/
/* Add the given bytes to the buffer. */
void
Buf_AddBytes(Buffer *bp, int numBytes, const Byte *bytesPtr)
Buf_AddBytes(Buffer *bp, const char *bytesPtr, size_t numBytes)
{
int count = bp->count;
Byte *ptr;
size_t count = bp->count;
char *ptr;
if (__predict_false(count + numBytes >= bp->size)) {
bp->size += max(bp->size, numBytes + 16);
bp->size += MAX(bp->size, numBytes + 16);
bp->buffer = bmake_realloc(bp->buffer, bp->size);
}
ptr = bp->buffer + count;
bp->count = count + numBytes;
ptr[numBytes] = 0;
memcpy(ptr, bytesPtr, numBytes);
ptr[numBytes] = '\0';
}
/*-
*-----------------------------------------------------------------------
* Buf_GetAll --
* Get all the available data at once.
*
* Results:
* A pointer to the data and the number of bytes available.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
Byte *
Buf_GetAll(Buffer *bp, int *numBytesPtr)
/* 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;
}
/*-
*-----------------------------------------------------------------------
* Buf_Empty --
* Throw away bytes in a buffer.
*
* Results:
* None.
*
* Side Effects:
* The bytes are discarded.
*
*-----------------------------------------------------------------------
*/
/* Mark the buffer as empty, so it can be filled with data again. */
void
Buf_Empty(Buffer *bp)
{
bp->count = 0;
*bp->buffer = 0;
bp->buffer[0] = '\0';
}
/*-
*-----------------------------------------------------------------------
* Buf_Init --
* Initialize a buffer. If no initial size is given, a reasonable
* default is used.
*
* Input:
* size Initial size for the buffer
*
* Results:
* A buffer to be given to other functions in this library.
*
* Side Effects:
* The buffer is created, the space allocated and pointers
* initialized.
*
*-----------------------------------------------------------------------
*/
/* Initialize a buffer.
* If the given initial size is 0, a reasonable default is used. */
void
Buf_Init(Buffer *bp, int size)
Buf_Init(Buffer *bp, size_t size)
{
if (size <= 0) {
size = BUF_DEF_SIZE;
size = 256;
}
bp->size = size;
bp->count = 0;
bp->buffer = bmake_malloc(size);
*bp->buffer = 0;
bp->buffer[0] = '\0';
}
/*-
*-----------------------------------------------------------------------
* Buf_Destroy --
* Nuke a buffer and all its resources.
*
* Input:
* buf Buffer to destroy
* freeData TRUE if the data should be destroyed
*
* Results:
* Data buffer, NULL if freed
*
* Side Effects:
* The buffer is freed.
*
*-----------------------------------------------------------------------
*/
Byte *
/* 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)
{
Byte *data;
data = buf->buffer;
char *data = buf->buffer;
if (freeData) {
free(data);
data = NULL;
@ -249,42 +199,24 @@ Buf_Destroy(Buffer *buf, Boolean freeData)
return data;
}
/*-
*-----------------------------------------------------------------------
* Buf_DestroyCompact --
* Nuke a buffer and return its data.
*
* Input:
* buf Buffer to destroy
*
* Results:
* Data buffer
*
* Side Effects:
* If the buffer size is much greater than its content,
* a new buffer will be allocated and the old one freed.
*
*-----------------------------------------------------------------------
*/
#ifndef BUF_COMPACT_LIMIT
# define BUF_COMPACT_LIMIT 128 /* worthwhile saving */
# define BUF_COMPACT_LIMIT 128 /* worthwhile saving */
#endif
Byte *
/* 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
Byte *data;
if (buf->size - buf->count >= BUF_COMPACT_LIMIT) {
/* We trust realloc to be smart */
data = bmake_realloc(buf->buffer, buf->count + 1);
if (data) {
data[buf->count] = 0;
Buf_Destroy(buf, FALSE);
return data;
}
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);

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.19 2017/05/31 22:02:06 maya Exp $ */
/* $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.
@ -72,48 +72,54 @@
* from: @(#)buf.h 8.1 (Berkeley) 6/6/93
*/
/*-
* buf.h --
* Header for users of the buf library.
*/
/* Automatically growing null-terminated buffers of characters. */
#ifndef MAKE_BUF_H
#define MAKE_BUF_H
typedef char Byte;
#include <stddef.h>
/* An automatically growing null-terminated buffer of characters. */
typedef struct Buffer {
int size; /* Current size of the buffer */
int count; /* Number of bytes in buffer */
Byte *buffer; /* The buffer itself (zero terminated) */
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. */
/* If we aren't on NetBSD, __predict_false() might not be defined. */
#ifndef __predict_false
#define __predict_false(x) (x)
#endif
/* Buf_AddByte adds a single byte to a buffer. */
#define Buf_AddByte(bp, byte) do { \
int _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; \
} while (0)
#define BUF_ERROR 256
#define Buf_Size(bp) ((bp)->count)
void Buf_Expand_1(Buffer *);
void Buf_AddBytes(Buffer *, int, const Byte *);
Byte *Buf_GetAll(Buffer *, int *);
/* 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 *, int);
Byte *Buf_Destroy(Buffer *, Boolean);
Byte *Buf_DestroyCompact(Buffer *);
void Buf_Init(Buffer *, size_t);
char *Buf_Destroy(Buffer *, Boolean);
char *Buf_DestroyCompact(Buffer *);
#endif /* MAKE_BUF_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: compat.c,v 1.113 2020/07/03 08:13:23 rillig Exp $ */
/* $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.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: compat.c,v 1.113 2020/07/03 08:13:23 rillig Exp $";
static char rcsid[] = "$NetBSD: compat.c,v 1.139 2020/08/30 20:08:47 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: compat.c,v 1.113 2020/07/03 08:13:23 rillig Exp $");
__RCSID("$NetBSD: compat.c,v 1.139 2020/08/30 20:08:47 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -129,34 +129,24 @@ static void
CompatDeleteTarget(GNode *gn)
{
if ((gn != NULL) && !Targ_Precious (gn)) {
char *p1;
char *file = Var_Value(TARGET, gn, &p1);
char *p1;
const char *file = Var_Value(TARGET, gn, &p1);
if (!noExecute && eunlink(file) != -1) {
Error("*** %s removed", file);
}
free(p1);
bmake_free(p1);
}
}
/*-
*-----------------------------------------------------------------------
* CompatInterrupt --
* Interrupt the creation of the current target and remove it if
* it ain't precious.
/* Interrupt the creation of the current target and remove it if it ain't
* precious. Then exit.
*
* Results:
* None.
*
* Side Effects:
* The target is removed and the process exits. If .INTERRUPT exists,
* its commands are run first WITH INTERRUPTS IGNORED..
* 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)
@ -190,7 +180,7 @@ CompatInterrupt(int signo)
kill(myPid, signo);
}
}
/*-
*-----------------------------------------------------------------------
* CompatRunCommand --
@ -215,7 +205,7 @@ 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 */
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 */
@ -224,21 +214,17 @@ CompatRunCommand(void *cmdp, void *gnp)
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 */
int argc; /* Number of arguments in av or 0 if not
* dynamically allocated */
Boolean local; /* TRUE if command should be executed
* locally */
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;
silent = (gn->type & OP_SILENT) != 0;
errCheck = !(gn->type & OP_IGNORE);
doIt = FALSE;
cmdNode = Lst_Member(gn->commands, cmd);
cmdStart = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
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
@ -252,10 +238,11 @@ CompatRunCommand(void *cmdp, void *gnp)
return 0;
}
cmd = cmdStart;
Lst_Replace(cmdNode, cmdStart);
LstNode_Set(cmdNode, cmdStart);
if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
(void)Lst_AtEnd(ENDNode->commands, cmdStart);
assert(ENDNode != NULL);
Lst_Append(ENDNode->commands, cmdStart);
return 0;
}
if (strcmp(cmdStart, "...") == 0) {
@ -266,7 +253,7 @@ CompatRunCommand(void *cmdp, void *gnp)
while ((*cmd == '@') || (*cmd == '-') || (*cmd == '+')) {
switch (*cmd) {
case '@':
silent = DEBUG(LOUD) ? FALSE : TRUE;
silent = !DEBUG(LOUD);
break;
case '-':
errCheck = FALSE;
@ -330,7 +317,6 @@ CompatRunCommand(void *cmdp, void *gnp)
if (DEBUG(JOB))
fprintf(debug_file, "Execute: '%s'\n", cmd);
again:
if (useShell) {
/*
* We need to pass the command off to the shell, typically
@ -352,9 +338,8 @@ CompatRunCommand(void *cmdp, void *gnp)
else
shargv[shargc++] = "-c";
shargv[shargc++] = cmd;
shargv[shargc++] = NULL;
shargv[shargc] = NULL;
av = shargv;
argc = 0;
bp = NULL;
mav = NULL;
} else {
@ -362,16 +347,12 @@ CompatRunCommand(void *cmdp, void *gnp)
* No meta-characters, so no need to exec a shell. Break the command
* into words to form an argument vector we can execute.
*/
mav = brk_string(cmd, &argc, TRUE, &bp);
if (mav == NULL) {
useShell = 1;
goto again;
}
Words words = Str_Words(cmd, FALSE);
mav = words.words;
bp = words.freeIt;
av = (void *)mav;
}
local = TRUE;
#ifdef USE_META
if (useMeta) {
meta_compat_start();
@ -392,10 +373,7 @@ CompatRunCommand(void *cmdp, void *gnp)
meta_compat_child();
}
#endif
if (local)
(void)execvp(av[0], (char *const *)UNCONST(av));
else
(void)execv(av[0], (char *const *)UNCONST(av));
(void)execvp(av[0], (char *const *)UNCONST(av));
execError("exec", av[0]);
_exit(1);
}
@ -403,7 +381,9 @@ CompatRunCommand(void *cmdp, void *gnp)
free(mav);
free(bp);
Lst_Replace(cmdNode, NULL);
/* XXX: Memory management looks suspicious here. */
/* XXX: Setting a list item to NULL is unexpected. */
LstNode_SetNull(cmdNode);
#ifdef USE_META
if (useMeta) {
@ -436,18 +416,18 @@ CompatRunCommand(void *cmdp, void *gnp)
#endif
if (status != 0) {
if (DEBUG(ERROR)) {
fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ",
fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ",
gn->name);
for (cp = cmd; *cp; ) {
if (isspace((unsigned char)*cp)) {
for (cp = cmd; *cp; ) {
if (isspace((unsigned char)*cp)) {
fprintf(debug_file, " ");
while (isspace((unsigned char)*cp))
while (isspace((unsigned char)*cp))
cp++;
} else {
fprintf(debug_file, "%c", *cp);
cp++;
cp++;
}
}
}
fprintf(debug_file, "\n");
}
printf("*** Error code %d", status);
@ -502,7 +482,7 @@ CompatRunCommand(void *cmdp, void *gnp)
return status;
}
/*-
*-----------------------------------------------------------------------
* Compat_Make --
@ -544,14 +524,14 @@ Compat_Make(void *gnp, void *pgnp)
Lst_ForEach(gn->children, Compat_Make, gn);
if ((gn->flags & REMAKE) == 0) {
gn->made = ABORTED;
pgn->flags &= ~REMAKE;
pgn->flags &= ~(unsigned)REMAKE;
goto cohorts;
}
if (Lst_Member(gn->iParents, pgn) != NULL) {
if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
free(p1);
bmake_free(p1);
}
/*
@ -614,7 +594,7 @@ Compat_Make(void *gnp, void *pgnp)
Lst_ForEach(gn->commands, CompatRunCommand, gn);
curTarg = NULL;
} else {
Job_Touch(gn, gn->type & OP_SILENT);
Job_Touch(gn, (gn->type & OP_SILENT) != 0);
}
} else {
gn->made = ERROR;
@ -640,7 +620,7 @@ Compat_Make(void *gnp, void *pgnp)
Make_TimeStamp(pgn, gn);
}
} else if (keepgoing) {
pgn->flags &= ~REMAKE;
pgn->flags &= ~(unsigned)REMAKE;
} else {
PrintOnError(gn, "\nStop.");
exit(1);
@ -650,18 +630,19 @@ Compat_Make(void *gnp, void *pgnp)
* Already had an error when making this beastie. Tell the parent
* to abort.
*/
pgn->flags &= ~REMAKE;
pgn->flags &= ~(unsigned)REMAKE;
} else {
if (Lst_Member(gn->iParents, pgn) != NULL) {
if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) {
char *p1;
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
free(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 &= ~REMAKE;
pgn->flags &= ~(unsigned)REMAKE;
break;
case MADE:
if ((gn->type & OP_EXEC) == 0) {
@ -683,22 +664,11 @@ Compat_Make(void *gnp, void *pgnp)
Lst_ForEach(gn->cohorts, Compat_Make, pgnp);
return 0;
}
/*-
*-----------------------------------------------------------------------
* Compat_Run --
* Initialize this mode and start making.
/* Initialize this module and start making.
*
* Input:
* targs List of target nodes to re-create
*
* Results:
* None.
*
* Side Effects:
* Guess what?
*
*-----------------------------------------------------------------------
* targs The target nodes to re-create
*/
void
Compat_Run(Lst targs)
@ -732,10 +702,10 @@ Compat_Run(Lst targs)
gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
if (gn != NULL) {
Compat_Make(gn, gn);
if (gn->made == ERROR) {
PrintOnError(gn, "\nStop.");
exit(1);
}
if (gn->made == ERROR) {
PrintOnError(gn, "\nStop.");
exit(1);
}
}
}
@ -756,8 +726,8 @@ Compat_Run(Lst targs)
* could not be made due to errors.
*/
errors = 0;
while (!Lst_IsEmpty (targs)) {
gn = (GNode *)Lst_DeQueue(targs);
while (!Lst_IsEmpty(targs)) {
gn = Lst_Dequeue(targs);
Compat_Make(gn, gn);
if (gn->made == UPTODATE) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: dir.h,v 1.18 2017/05/31 22:02:06 maya Exp $ */
/* $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.
@ -72,29 +72,34 @@
* from: @(#)dir.h 8.1 (Berkeley) 6/6/93
*/
/* dir.h --
*/
#ifndef MAKE_DIR_H
#define MAKE_DIR_H
typedef struct Path {
/* 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 table of files in directory */
Hash_Table files; /* Hash set of files in directory */
} Path;
void Dir_Init(const char *);
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(char *);
Boolean Dir_HasWildcards(const char *);
void Dir_Expand(const char *, Lst, Lst);
char *Dir_FindFile(const char *, Lst);
int Dir_FindHereOrAbove(char *, char *, char *, int);
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);
@ -103,6 +108,9 @@ void Dir_Concat(Lst, Lst);
void Dir_PrintDirectories(void);
void Dir_PrintPath(Lst);
void Dir_Destroy(void *);
void * Dir_CopyDir(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 */

100
contrib/bmake/enum.c Executable file
View File

@ -0,0 +1,100 @@
/* $NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: enum.c,v 1.6 2020/09/01 20:34:51 rillig Exp $");
#endif
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#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 */);
}

193
contrib/bmake/enum.h Executable file
View File

@ -0,0 +1,193 @@
/* $NetBSD: enum.h,v 1.9 2020/09/01 20:34:51 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <rillig@NetBSD.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAKE_ENUM_H
#define MAKE_ENUM_H
/* Generate string representations for bitmasks and simple enums. */
#include <stddef.h>
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

View File

@ -1,4 +1,4 @@
/* $NetBSD: for.c,v 1.54 2020/07/03 08:13:23 rillig Exp $ */
/* $NetBSD: for.c,v 1.67 2020/08/30 19:56:02 rillig Exp $ */
/*
* Copyright (c) 1992, The Regents of the University of California.
@ -30,14 +30,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: for.c,v 1.54 2020/07/03 08:13:23 rillig Exp $";
static char rcsid[] = "$NetBSD: for.c,v 1.67 2020/08/30 19:56:02 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)for.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: for.c,v 1.54 2020/07/03 08:13:23 rillig Exp $");
__RCSID("$NetBSD: for.c,v 1.67 2020/08/30 19:56:02 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -52,13 +52,7 @@ __RCSID("$NetBSD: for.c,v 1.54 2020/07/03 08:13:23 rillig Exp $");
*
*/
#include <assert.h>
#include <ctype.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
#include "buf.h"
#include "strlist.h"
#define FOR_SUB_ESCAPE_CHAR 1
@ -83,34 +77,22 @@ __RCSID("$NetBSD: for.c,v 1.54 2020/07/03 08:13:23 rillig Exp $");
* For_Run.
*/
static int forLevel = 0; /* Nesting level */
static int forLevel = 0; /* Nesting level */
/*
* State of a for loop.
*/
typedef struct _For {
Buffer buf; /* Body of loop */
strlist_t vars; /* Iteration variables */
strlist_t items; /* Substitution items */
char *parse_buf;
int short_var;
int sub_next;
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 For *accumFor; /* Loop being accumulated */
static char *
make_str(const char *ptr, int len)
{
char *new_ptr;
new_ptr = bmake_malloc(len + 1);
memcpy(new_ptr, ptr, len);
new_ptr[len] = 0;
return new_ptr;
}
static void
For_Free(For *arg)
@ -148,14 +130,13 @@ For_Eval(char *line)
{
For *new_for;
char *ptr = line, *sub;
int len;
size_t len;
int escapes;
unsigned char ch;
char **words, *word_buf;
int n, nwords;
Words words;
/* Skip the '.' and any following whitespace */
for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
for (ptr++; *ptr && isspace((unsigned char)*ptr); ptr++)
continue;
/*
@ -163,8 +144,8 @@ For_Eval(char *line)
* 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) {
!isspace((unsigned char)ptr[3])) {
if (ptr[0] == 'e' && strncmp(ptr + 1, "ndfor", 5) == 0) {
Parse_Error(PARSE_FATAL, "for-less endfor");
return -1;
}
@ -181,7 +162,7 @@ For_Eval(char *line)
/* Grab the variables. Terminate on "in". */
for (;; ptr += len) {
while (*ptr && isspace((unsigned char) *ptr))
while (*ptr && isspace((unsigned char)*ptr))
ptr++;
if (*ptr == '\0') {
Parse_Error(PARSE_FATAL, "missing `in' in for");
@ -196,7 +177,7 @@ For_Eval(char *line)
}
if (len == 1)
new_for->short_var = 1;
strlist_add_str(&new_for->vars, make_str(ptr, len), len);
strlist_add_str(&new_for->vars, bmake_strldup(ptr, len), len);
}
if (strlist_num(&new_for->vars) == 0) {
@ -205,7 +186,7 @@ For_Eval(char *line)
return -1;
}
while (*ptr && isspace((unsigned char) *ptr))
while (*ptr && isspace((unsigned char)*ptr))
ptr++;
/*
@ -216,23 +197,25 @@ For_Eval(char *line)
* We can't do the escapes here - because we don't know whether
* we are substuting into ${...} or $(...).
*/
sub = Var_Subst(NULL, ptr, VAR_GLOBAL, VARF_WANTRES);
sub = Var_Subst(ptr, VAR_GLOBAL, VARE_WANTRES);
/*
* Split into words allowing for quoted strings.
*/
words = brk_string(sub, &nwords, FALSE, &word_buf);
words = Str_Words(sub, FALSE);
free(sub);
if (words != NULL) {
for (n = 0; n < nwords; n++) {
ptr = words[n];
{
size_t n;
for (n = 0; n < words.len; n++) {
ptr = words.words[n];
if (!*ptr)
continue;
escapes = 0;
while ((ch = *ptr++)) {
switch(ch) {
switch (ch) {
case ':':
case '$':
case '\\':
@ -250,17 +233,17 @@ For_Eval(char *line)
* We have to dup words[n] to maintain the semantics of
* strlist.
*/
strlist_add_str(&new_for->items, bmake_strdup(words[n]), escapes);
strlist_add_str(&new_for->items, bmake_strdup(words.words[n]),
escapes);
}
free(words);
free(word_buf);
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 (%d) in .for substitution list"
" with %d vars", len, n);
"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.
@ -288,49 +271,35 @@ For_Accum(char *line)
if (*ptr == '.') {
for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
for (ptr++; *ptr && isspace((unsigned char)*ptr); ptr++)
continue;
if (strncmp(ptr, "endfor", 6) == 0 &&
(isspace((unsigned char) ptr[6]) || !ptr[6])) {
(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])) {
isspace((unsigned char)ptr[3])) {
forLevel++;
if (DEBUG(FOR))
(void)fprintf(debug_file, "For: new loop %d\n", forLevel);
}
}
Buf_AddBytes(&accumFor->buf, strlen(line), line);
Buf_AddStr(&accumFor->buf, line);
Buf_AddByte(&accumFor->buf, '\n');
return 1;
}
/*-
*-----------------------------------------------------------------------
* For_Run --
* Run the for loop, imitating the actions of an include file
*
* Results:
* None.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
static int
static size_t
for_var_len(const char *var)
{
char ch, var_start, var_end;
int depth;
int len;
size_t len;
var_start = *var;
if (var_start == 0)
@ -360,24 +329,24 @@ for_var_len(const char *var)
static void
for_substitute(Buffer *cmds, strlist_t *items, unsigned int item_no, char ech)
{
const char *item = strlist_str(items, item_no);
int len;
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_AddBytes(cmds, strlen(item), item);
(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 == '$') {
len = for_var_len(item);
size_t len = for_var_len(item);
if (len != 0) {
Buf_AddBytes(cmds, len + 1, item - 1);
Buf_AddBytes(cmds, item - 1, len + 1);
item += len;
continue;
}
@ -392,13 +361,14 @@ static char *
For_Iterate(void *v_arg, size_t *ret_len)
{
For *arg = v_arg;
int i, len;
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 */
@ -421,9 +391,9 @@ For_Iterate(void *v_arg, size_t *ret_len)
* to contrive a makefile where an unwanted substitution happens.
*/
cmd_cp = Buf_GetAll(&arg->buf, &len);
body_end = cmd_cp + len;
Buf_Init(&cmds, len + 256);
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;
@ -431,15 +401,15 @@ For_Iterate(void *v_arg, size_t *ret_len)
cp++;
/* Check variable name against the .for loop variables */
STRLIST_FOREACH(var, &arg->vars, i) {
len = strlist_info(&arg->vars, i);
if (memcmp(cp, var, len) != 0)
size_t vlen = strlist_info(&arg->vars, i);
if (memcmp(cp, var, vlen) != 0)
continue;
if (cp[len] != ':' && cp[len] != ech && cp[len] != '\\')
if (cp[vlen] != ':' && cp[vlen] != ech && cp[vlen] != '\\')
continue;
/* Found a variable match. Replace with :U<value> */
Buf_AddBytes(&cmds, cp - cmd_cp, cmd_cp);
Buf_AddBytes(&cmds, 2, ":U");
cp += len;
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;
@ -457,15 +427,15 @@ For_Iterate(void *v_arg, size_t *ret_len)
if (var[0] != ch || var[1] != 0)
continue;
/* Found a variable match. Replace with ${:U<value>} */
Buf_AddBytes(&cmds, cp - cmd_cp, cmd_cp);
Buf_AddBytes(&cmds, 3, "{:U");
Buf_AddBytesBetween(&cmds, cmd_cp, cp);
Buf_AddStr(&cmds, "{:U");
cmd_cp = ++cp;
for_substitute(&cmds, &arg->items, arg->sub_next + i, /*{*/ '}');
Buf_AddBytes(&cmds, 1, "}");
Buf_AddByte(&cmds, '}');
break;
}
}
Buf_AddBytes(&cmds, body_end - cmd_cp, cmd_cp);
Buf_AddBytesBetween(&cmds, cmd_cp, body_end);
cp = Buf_Destroy(&cmds, FALSE);
if (DEBUG(FOR))
@ -478,6 +448,7 @@ For_Iterate(void *v_arg, size_t *ret_len)
return cp;
}
/* Run the for loop, imitating the actions of an include file. */
void
For_Run(int lineno)
{
@ -487,9 +458,9 @@ For_Run(int lineno)
accumFor = NULL;
if (strlist_num(&arg->items) == 0) {
/* Nothing to expand - possibly due to an earlier syntax error. */
For_Free(arg);
return;
/* Nothing to expand - possibly due to an earlier syntax error. */
For_Free(arg);
return;
}
Parse_SetInput(NULL, lineno, -1, For_Iterate, arg);

View File

@ -1,4 +1,4 @@
/* $NetBSD: hash.c,v 1.22 2020/07/03 17:03:09 rillig Exp $ */
/* $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.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: hash.c,v 1.22 2020/07/03 17:03:09 rillig Exp $";
static char rcsid[] = "$NetBSD: hash.c,v 1.29 2020/09/01 21:11:31 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: hash.c,v 1.22 2020/07/03 17:03:09 rillig Exp $");
__RCSID("$NetBSD: hash.c,v 1.29 2020/09/01 21:11:31 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -89,9 +89,7 @@ __RCSID("$NetBSD: hash.c,v 1.22 2020/07/03 17:03:09 rillig Exp $");
* table. Hash tables grow automatically as the amount of
* information increases.
*/
#include "sprite.h"
#include "make.h"
#include "hash.h"
/*
* Forward references to local procedures that are used before they're
@ -107,29 +105,26 @@ static void RebuildTable(Hash_Table *);
#define rebuildLimit 3
/*
*---------------------------------------------------------
*
* Hash_InitTable --
*
* This routine just sets up the hash table.
/* 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 table.
* 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.
*
* Results:
* None.
*
* Side Effects:
* Memory is allocated for the initial bucket area.
*
*---------------------------------------------------------
*/
void
Hash_InitTable(Hash_Table *t, int numBuckets)
{
@ -146,118 +141,85 @@ Hash_InitTable(Hash_Table *t, int numBuckets)
continue;
}
t->numEntries = 0;
t->size = i;
t->mask = i - 1;
t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
t->maxchain = 0;
t->bucketsSize = i;
t->bucketsMask = i - 1;
t->buckets = hp = bmake_malloc(sizeof(*hp) * i);
while (--i >= 0)
*hp++ = NULL;
}
/*
*---------------------------------------------------------
*
* Hash_DeleteTable --
*
* This routine removes everything from a hash table
* and frees up the memory space it occupied (except for
* the space in the Hash_Table structure).
*
* Results:
* None.
*
* Side Effects:
* Lots of memory is freed up.
*
*---------------------------------------------------------
*/
/* 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->bucketPtr, i = t->size; --i >= 0;) {
for (hp = t->buckets, i = t->bucketsSize; --i >= 0;) {
for (h = *hp++; h != NULL; h = nexth) {
nexth = h->next;
free(h);
}
}
free(t->bucketPtr);
free(t->buckets);
/*
* Set up the hash table to cause memory faults on any future access
* attempts until re-initialization.
*/
t->bucketPtr = NULL;
t->buckets = NULL;
}
/*
*---------------------------------------------------------
*
* Hash_FindEntry --
*
* Searches a hash table for an entry corresponding to key.
/* Searches the hash table for an entry corresponding to the key.
*
* Input:
* t Hash table to search.
* key A hash key.
*
* Results:
* The return value is a pointer to the entry for key,
* if key was present in the table. If key was not
* present, NULL is returned.
*
* Side Effects:
* None.
*
*---------------------------------------------------------
* 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->bucketPtr == NULL) {
if (t == NULL || t->buckets == NULL) {
return NULL;
}
for (h = 0, p = key; *p;)
h = (h << 5) - h + *p++;
HASH(h, key, p);
p = key;
for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
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)
return e;
return NULL;
break;
}
if (chainlen > t->maxchain)
t->maxchain = chainlen;
return e;
}
/*
*---------------------------------------------------------
*
* Hash_CreateEntry --
*
* Searches a hash table for an entry corresponding to
* key. If no entry is found, then one is created.
/* 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 in with TRUE if new entry created,
* newPtr Filled with TRUE if new entry created,
* FALSE otherwise.
*
* Results:
* The return value is a pointer to the entry. If *newPtr
* isn't NULL, then *newPtr is filled in with TRUE if a
* new entry was created, and FALSE if an entry already existed
* with the given key.
*
* Side Effects:
* Memory may be allocated, and the hash buckets may be modified.
*---------------------------------------------------------
*/
Hash_Entry *
Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr)
{
@ -265,33 +227,44 @@ Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr)
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.
*/
for (h = 0, p = key; *p;)
h = (h << 5) - h + *p++;
HASH(h, key, p);
keylen = p - key;
p = key;
for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
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;
return e;
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->size)
if (t->numEntries >= rebuildLimit * t->bucketsSize)
RebuildTable(t);
e = bmake_malloc(sizeof(*e) + keylen);
hp = &t->bucketPtr[h & t->mask];
hp = &t->buckets[h & t->bucketsMask];
e->next = *hp;
*hp = e;
Hash_SetValue(e, NULL);
@ -304,23 +277,7 @@ Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr)
return e;
}
/*
*---------------------------------------------------------
*
* Hash_DeleteEntry --
*
* Delete the given hash table entry and free memory associated with
* it.
*
* Results:
* None.
*
* Side Effects:
* Hash chain that entry lives in is modified and memory is freed.
*
*---------------------------------------------------------
*/
/* Delete the given hash table entry and free memory associated with it. */
void
Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
{
@ -328,7 +285,7 @@ Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
if (e == NULL)
return;
for (hp = &t->bucketPtr[e->namehash & t->mask];
for (hp = &t->buckets[e->namehash & t->bucketsMask];
(p = *hp) != NULL; hp = &p->next) {
if (p == e) {
*hp = p->next;
@ -341,12 +298,7 @@ Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
abort();
}
/*
*---------------------------------------------------------
*
* Hash_EnumFirst --
* This procedure sets things up for a complete search
* of all entries recorded in the hash table.
/* Sets things up for enumerating all entries in the hash table.
*
* Input:
* t Table to be searched.
@ -355,57 +307,34 @@ Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
* Results:
* The return value is the address of the first entry in
* the hash table, or NULL if the table is empty.
*
* Side Effects:
* The information in searchPtr is initialized so that successive
* calls to Hash_Next will return successive HashEntry's
* from the table.
*
*---------------------------------------------------------
*/
Hash_Entry *
Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr)
{
searchPtr->tablePtr = t;
searchPtr->nextIndex = 0;
searchPtr->hashEntryPtr = NULL;
searchPtr->table = t;
searchPtr->nextBucket = 0;
searchPtr->entry = NULL;
return Hash_EnumNext(searchPtr);
}
/*
*---------------------------------------------------------
*
* Hash_EnumNext --
* This procedure returns successive entries in the hash table.
/* 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.
*
* Results:
* The return value is a pointer to the next HashEntry
* in the table, or NULL when the end of the table is
* reached.
*
* Side Effects:
* The information in searchPtr is modified to advance to the
* next entry.
*
*---------------------------------------------------------
*/
Hash_Entry *
Hash_EnumNext(Hash_Search *searchPtr)
{
Hash_Entry *e;
Hash_Table *t = searchPtr->tablePtr;
Hash_Table *t = searchPtr->table;
/*
* The hashEntryPtr field points to the most recently returned
* entry, or is nil if we are starting up. If not nil, we have
* 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->hashEntryPtr;
e = searchPtr->entry;
if (e != NULL)
e = e->next;
/*
@ -413,59 +342,49 @@ Hash_EnumNext(Hash_Search *searchPtr)
* find the next nonempty chain.
*/
while (e == NULL) {
if (searchPtr->nextIndex >= t->size)
if (searchPtr->nextBucket >= t->bucketsSize)
return NULL;
e = t->bucketPtr[searchPtr->nextIndex++];
e = t->buckets[searchPtr->nextBucket++];
}
searchPtr->hashEntryPtr = e;
searchPtr->entry = e;
return e;
}
/*
*---------------------------------------------------------
*
* RebuildTable --
* This local routine makes a new hash table that
* is larger than the old one.
*
* Results:
* None.
*
* Side Effects:
* The entire hash table is moved, so any bucket numbers
* from the old table are invalid.
*
*---------------------------------------------------------
*/
/* 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;
Hash_Entry **oldhp;
int oldsize;
oldhp = t->bucketPtr;
oldsize = i = t->size;
oldhp = t->buckets;
oldsize = i = t->bucketsSize;
i <<= 1;
t->size = i;
t->mask = mask = i - 1;
t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
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->bucketPtr[e->namehash & mask];
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)
void
Hash_ForEach(Hash_Table *t, void (*action)(void *, void *), void *data)
{
Hash_Search search;
Hash_Entry *e;
@ -475,3 +394,11 @@ void Hash_ForEach(Hash_Table *t, void (*action)(void *, void *), void *data)
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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hash.h,v 1.13 2020/07/03 17:03:09 rillig Exp $ */
/* $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.
@ -72,71 +72,51 @@
* from: @(#)hash.h 8.1 (Berkeley) 6/6/93
*/
/* hash.h --
*
* This file contains definitions used by the hash module,
* which maintains hash tables.
*/
/* Hash tables with strings as keys and arbitrary pointers as values. */
#ifndef _HASH_H
#define _HASH_H
/*
* The following defines one entry in the hash table.
*/
#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 *clientPtr; /* Arbitrary pointer */
unsigned namehash; /* hash value of key */
char name[1]; /* key string */
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 {
struct Hash_Entry **bucketPtr;/* Pointers to Hash_Entry, one
* for each bucket in the table. */
int size; /* Actual size of array. */
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 mask; /* Used to select bits for hashing. */
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 *tablePtr; /* Table being searched. */
int nextIndex; /* Next bucket to check (after current). */
Hash_Entry *hashEntryPtr; /* Next entry to check in current bucket. */
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;
/*
* Macros.
*/
static inline void * MAKE_ATTR_UNUSED
Hash_GetValue(Hash_Entry *h)
{
return h->value;
}
/*
* void * Hash_GetValue(h)
* Hash_Entry *h;
*/
#define Hash_GetValue(h) ((h)->clientPtr)
/*
* Hash_SetValue(h, val);
* Hash_Entry *h;
* char *val;
*/
#define Hash_SetValue(h, val) ((h)->clientPtr = (val))
/*
* Hash_Size(n) returns the number of words in an object of n bytes
*/
#define Hash_Size(n) (((n) + sizeof (int) - 1) / sizeof (int))
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 *);
@ -146,5 +126,6 @@ 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 /* _HASH_H */
#endif /* MAKE_HASH_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $ */
/* $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.
@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $";
static char rcsid[] = "$NetBSD: job.c,v 1.227 2020/08/30 19:56:02 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $");
__RCSID("$NetBSD: job.c,v 1.227 2020/08/30 19:56:02 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -112,7 +112,7 @@ __RCSID("$NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $");
*
* Job_ParseShell Given the line following a .SHELL target, parse
* the line as a shell specification. Returns
* FAILURE if the spec was incorrect.
* FALSE if the spec was incorrect.
*
* Job_Finish Perform any final processing which needs doing.
* This includes the execution of any commands
@ -142,7 +142,6 @@ __RCSID("$NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $");
#include <sys/time.h>
#include "wait.h"
#include <assert.h>
#include <errno.h>
#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
#include <poll.h>
@ -155,15 +154,12 @@ __RCSID("$NetBSD: job.c,v 1.201 2020/07/03 08:13:23 rillig Exp $");
#endif
#endif
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <utime.h>
#if defined(HAVE_SYS_SOCKET_H)
# include <sys/socket.h>
#endif
#include "make.h"
#include "hash.h"
#include "dir.h"
#include "job.h"
#include "pathnames.h"
@ -200,7 +196,6 @@ static int aborting = 0; /* why is the make aborting? */
* this tracks the number of tokens currently "out" to build jobs.
*/
int jobTokensRunning = 0;
int not_parallel = 0; /* set if .NOT_PARALLEL */
/*
* XXX: Avoid SunOS bug... FILENO() is fp->_file, and file
@ -327,9 +322,9 @@ static Shell *commandShell = &shells[DEFSHELL_INDEX]; /* this is the shell to
* Job_ParseShell function */
const char *shellPath = NULL, /* full pathname of
* executable image */
*shellName = NULL; /* last component of shell */
*shellName = NULL; /* last component of shell */
char *shellErrFlag = NULL;
static const char *shellArgv = NULL; /* Custom shell args */
static char *shellArgv = NULL; /* Custom shell args */
STATIC Job *job_table; /* The structures that describe them */
@ -386,11 +381,6 @@ static void JobSigLock(sigset_t *);
static void JobSigUnlock(sigset_t *);
static void JobSigReset(void);
#if !defined(MALLOC_OPTIONS)
# define MALLOC_OPTIONS "A"
#endif
const char *malloc_options= MALLOC_OPTIONS;
static unsigned
nfds_per_job(void)
{
@ -739,15 +729,14 @@ JobPrintCommand(void *cmdp, void *jobp)
char *escCmd = NULL; /* Command with quotes/backticks escaped */
char *cmd = (char *)cmdp;
Job *job = (Job *)jobp;
int i, j;
noSpecials = NoExecute(job->node);
if (strcmp(cmd, "...") == 0) {
job->node->type |= OP_SAVE_CMDS;
if ((job->flags & JOB_IGNDOTS) == 0) {
job->tailCmds = Lst_Succ(Lst_Member(job->node->commands,
cmd));
LstNode dotsNode = Lst_FindDatum(job->node->commands, cmd);
job->tailCmds = dotsNode != NULL ? LstNode_Next(dotsNode) : NULL;
return 1;
}
return 0;
@ -761,7 +750,7 @@ JobPrintCommand(void *cmdp, void *jobp)
numCommands += 1;
cmdStart = cmd = Var_Subst(NULL, cmd, job->node, VARF_WANTRES);
cmdStart = cmd = Var_Subst(cmd, job->node, VARE_WANTRES);
cmdTemplate = "%s\n";
@ -801,15 +790,17 @@ JobPrintCommand(void *cmdp, void *jobp)
*/
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];
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;
escCmd[j] = '\0';
}
if (shutUp) {
@ -942,15 +933,15 @@ JobPrintCommand(void *cmdp, void *jobp)
* Always returns 0
*
* Side Effects:
* The command is tacked onto the end of postCommands's commands list.
* The command is tacked onto the end of postCommands' commands list.
*
*-----------------------------------------------------------------------
*/
static int
JobSaveCommand(void *cmd, void *gn)
{
cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, VARF_WANTRES);
(void)Lst_AtEnd(postCommands->commands, cmd);
cmd = Var_Subst((char *)cmd, (GNode *)gn, VARE_WANTRES);
Lst_Append(postCommands->commands, cmd);
return 0;
}
@ -1140,7 +1131,7 @@ JobFinish (Job *job, WAIT_T status)
if (job->tailCmds != NULL) {
Lst_ForEachFrom(job->node->commands, job->tailCmds,
JobSaveCommand,
job->node);
job->node);
}
job->node->made = MADE;
if (!(job->flags & JOB_SPECIAL))
@ -1291,7 +1282,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
*/
Make_HandleUse(DEFAULT, gn);
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn);
free(p1);
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
@ -1318,7 +1309,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
(void)fprintf(stdout, "%s%s %s (continuing)\n", progname,
msg, gn->name);
(void)fflush(stdout);
return FALSE;
return FALSE;
} else {
(*abortProc)("%s%s %s. Stop", progname, msg, gn->name);
return FALSE;
@ -1361,7 +1352,7 @@ JobExec(Job *job, char **argv)
for (i = 0; argv[i] != NULL; i++) {
(void)fprintf(debug_file, "%s ", argv[i]);
}
(void)fprintf(debug_file, "\n");
(void)fprintf(debug_file, "\n");
}
/*
@ -1736,7 +1727,7 @@ JobStart(GNode *gn, int flags)
* up the graph.
*/
job->cmdFILE = stdout;
Job_Touch(gn, job->flags&JOB_SILENT);
Job_Touch(gn, job->flags&JOB_SILENT);
noExec = TRUE;
}
/* Just in case it isn't already... */
@ -1765,8 +1756,8 @@ JobStart(GNode *gn, int flags)
if (cmdsOK && aborting == 0) {
if (job->tailCmds != NULL) {
Lst_ForEachFrom(job->node->commands, job->tailCmds,
JobSaveCommand,
job->node);
JobSaveCommand,
job->node);
}
job->node->made = MADE;
Make_Update(job->node);
@ -2007,8 +1998,8 @@ JobRun(GNode *targ)
* 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(FALSE);
Lst_AtEnd(lst, targ);
Lst lst = Lst_Init();
Lst_Append(lst, targ);
(void)Make_Run(lst);
Lst_Destroy(lst, NULL);
JobStart(targ, JOB_SPECIAL);
@ -2235,8 +2226,9 @@ Shell_Init(void)
shellName++;
} else
#endif
shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
}
Var_Set_with_flags(".SHELL", shellPath, VAR_CMD, VAR_SET_READONLY);
if (commandShell->exit == NULL) {
commandShell->exit = "";
}
@ -2270,38 +2262,23 @@ Shell_Init(void)
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(NULL, "${" MAKE_JOB_PREFIX "}",
VAR_GLOBAL, VARF_WANTRES);
targPrefix = Var_Subst("${" MAKE_JOB_PREFIX "}",
VAR_GLOBAL, VARE_WANTRES);
}
/*-
*-----------------------------------------------------------------------
* Job_Init --
* Initialize the process module
*
* Input:
*
* Results:
* none
*
* Side Effects:
* lists and counters are initialized
*-----------------------------------------------------------------------
*/
/* Initialize the process module. */
void
Job_Init(void)
{
@ -2413,19 +2390,7 @@ static void JobSigReset(void)
(void)bmake_signal(SIGCHLD, SIG_DFL);
}
/*-
*-----------------------------------------------------------------------
* JobMatchShell --
* Find a shell in 'shells' given its name.
*
* Results:
* A pointer to the Shell structure.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
/* Find a shell in 'shells' given its name, or return NULL. */
static Shell *
JobMatchShell(const char *name)
{
@ -2448,7 +2413,7 @@ JobMatchShell(const char *name)
* line The shell spec
*
* Results:
* FAILURE if the specification was incorrect.
* FALSE if the specification was incorrect.
*
* Side Effects:
* commandShell points to a Shell structure (either predefined or
@ -2485,12 +2450,13 @@ JobMatchShell(const char *name)
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Boolean
Job_ParseShell(char *line)
{
Words wordsList;
char **words;
char **argv;
int argc;
size_t argc;
char *path;
Shell newShell;
Boolean fullSpec = FALSE;
@ -2500,17 +2466,20 @@ Job_ParseShell(char *line)
line++;
}
free(UNCONST(shellArgv));
free(shellArgv);
memset(&newShell, 0, sizeof(newShell));
/*
* Parse the specification by keyword
*/
words = brk_string(line, &argc, TRUE, &path);
wordsList = Str_Words(line, TRUE);
words = wordsList.words;
argc = wordsList.len;
path = wordsList.freeIt;
if (words == NULL) {
Error("Unterminated quoted string [%s]", line);
return FAILURE;
return FALSE;
}
shellArgv = path;
@ -2549,7 +2518,7 @@ Job_ParseShell(char *line)
Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",
*argv);
free(words);
return FAILURE;
return FALSE;
}
fullSpec = TRUE;
}
@ -2565,13 +2534,13 @@ Job_ParseShell(char *line)
if (newShell.name == NULL) {
Parse_Error(PARSE_FATAL, "Neither path nor name specified");
free(words);
return FAILURE;
return FALSE;
} else {
if ((sh = JobMatchShell(newShell.name)) == NULL) {
Parse_Error(PARSE_WARNING, "%s: No matching shell",
newShell.name);
free(words);
return FAILURE;
return FALSE;
}
commandShell = sh;
shellName = newShell.name;
@ -2607,7 +2576,7 @@ Job_ParseShell(char *line)
Parse_Error(PARSE_WARNING, "%s: No matching shell",
shellName);
free(words);
return FAILURE;
return FALSE;
}
commandShell = sh;
} else {
@ -2636,7 +2605,7 @@ Job_ParseShell(char *line)
* shell specification.
*/
free(words);
return SUCCESS;
return TRUE;
}
/*-
@ -2813,7 +2782,6 @@ Job_AbortAll(void)
continue;
}
/*-
*-----------------------------------------------------------------------
* JobRestartJobs --
@ -3154,7 +3122,7 @@ emul_poll(struct pollfd *fd, int nfd, int timeout)
usecs = timeout * 1000;
tv.tv_sec = usecs / 1000000;
tv.tv_usec = usecs % 1000000;
tvp = &tv;
tvp = &tv;
}
nselect = select(maxfd + 1, &rfds, &wfds, 0, tvp);

View File

@ -1,4 +1,4 @@
/* $NetBSD: job.h,v 1.43 2020/07/03 08:13:23 rillig Exp $ */
/* $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.
@ -77,8 +77,8 @@
* job.h --
* Definitions pertaining to the running of jobs in parallel mode.
*/
#ifndef _JOB_H_
#define _JOB_H_
#ifndef MAKE_JOB_H
#define MAKE_JOB_H
#define TMPPAT "makeXXXXXX" /* relative to tmpdir */
@ -110,7 +110,6 @@ emul_poll(struct pollfd *fd, int nfd, int timeout);
*/
#define POLL_MSEC 5000
/*-
* Job Table definitions.
*
@ -164,7 +163,7 @@ typedef struct Job {
* commands */
#define JOB_TRACED 0x400 /* we've sent 'set -x' */
int jobPipe[2]; /* Pipe for readind output from job */
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
@ -179,7 +178,6 @@ typedef struct Job {
#define inPipe jobPipe[0]
#define outPipe jobPipe[1]
/*-
* Shell Specifications:
* Each shell type has associated with it the following information:
@ -252,23 +250,20 @@ void Shell_Init(void);
const char *Shell_GetNewline(void);
void Job_Touch(GNode *, Boolean);
Boolean Job_CheckCommands(GNode *, void (*abortProc )(const char *, ...));
#define CATCH_BLOCK 1
void Job_CatchChildren(void);
void Job_CatchOutput(void);
void Job_Make(GNode *);
void Job_Init(void);
Boolean Job_Full(void);
Boolean Job_Empty(void);
ReturnStatus Job_ParseShell(char *);
Boolean Job_ParseShell(char *);
int Job_Finish(void);
void Job_End(void);
void Job_Wait(void);
void Job_AbortAll(void);
void JobFlagForMigration(int);
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 /* _JOB_H_ */
#endif /* MAKE_JOB_H */

641
contrib/bmake/lst.c Normal file
View File

@ -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 <inttypes.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#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 <sys/cdefs.h>
#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;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: lst.h,v 1.20 2014/09/07 20:55:34 joerg Exp $ */
/* $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.
@ -73,117 +73,107 @@
* from: @(#)lst.h 8.1 (Berkeley) 6/6/93
*/
/*-
* lst.h --
* Header for using the list library
*/
#ifndef _LST_H_
#define _LST_H_
/* Doubly-linked lists of arbitrary pointers. */
#include <sys/param.h>
#include <stdlib.h>
#ifndef MAKE_LST_H
#define MAKE_LST_H
#include "sprite.h"
/*
* basic typedef. This is what the Lst_ functions handle
*/
#include <sys/param.h>
#include <stdlib.h>
/* A doubly-linked list of pointers. */
typedef struct List *Lst;
/* A single node in the doubly-linked list. */
typedef struct ListNode *LstNode;
typedef void *DuplicateProc(void *);
typedef void FreeProc(void *);
/* 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);
#define LST_CONCNEW 0 /* create new LstNode's when using Lst_Concat */
#define LST_CONCLINK 1 /* relink LstNode's when using Lst_Concat */
/* Create or destroy a list */
/*
* Creation/destruction functions
*/
/* Create a new list */
Lst Lst_Init(Boolean);
/* Duplicate an existing list */
Lst Lst_Duplicate(Lst, DuplicateProc *);
/* Destroy an old one */
void Lst_Destroy(Lst, FreeProc *);
/* True if list is empty */
Boolean Lst_IsEmpty(Lst);
/* 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);
/*
* Functions to modify a list
*/
/* Insert an element before another */
ReturnStatus Lst_InsertBefore(Lst, LstNode, void *);
/* Insert an element after another */
ReturnStatus Lst_InsertAfter(Lst, LstNode, void *);
/* Place an element at the front of a lst. */
ReturnStatus Lst_AtFront(Lst, void *);
/* Place an element at the end of a lst. */
ReturnStatus Lst_AtEnd(Lst, void *);
/* Remove an element */
ReturnStatus Lst_Remove(Lst, LstNode);
/* Replace a node with a new value */
ReturnStatus Lst_Replace(LstNode, void *);
/* Concatenate two lists */
ReturnStatus Lst_Concat(Lst, Lst, int);
/* Get information about a list */
/*
* Node-specific functions
*/
/* Return first element in list */
LstNode Lst_First(Lst);
/* Return last element in list */
LstNode Lst_Last(Lst);
/* Return successor to given element */
LstNode Lst_Succ(LstNode);
/* Return predecessor to given element */
LstNode Lst_Prev(LstNode);
/* Get datum from LstNode */
void *Lst_Datum(LstNode);
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 *);
/*
* Functions for entire lists
*/
/* Find an element in a list */
LstNode Lst_Find(Lst, const void *, int (*)(const void *, const void *));
/* Find an element starting from somewhere */
LstNode Lst_FindFrom(Lst, LstNode, const void *,
int (*cProc)(const void *, const void *));
/*
* See if the given datum is on the list. Returns the LstNode containing
* the datum
*/
LstNode Lst_Member(Lst, void *);
/* Apply a function to all elements of a lst */
int Lst_ForEach(Lst, int (*)(void *, void *), void *);
/*
* Apply a function to all elements of a lst starting from a certain point.
* If the list is circular, the application will wrap around to the
* beginning of the list again.
*/
int Lst_ForEachFrom(Lst, LstNode, int (*)(void *, void *),
void *);
/*
* 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().
*/
/* Open the list */
ReturnStatus Lst_Open(Lst);
/* Next element please */
LstNode Lst_Next(Lst);
/* Done yet? */
Boolean Lst_IsAtEnd(Lst);
/* Finish table access */
void Lst_Close(Lst);
/* Modify a list */
/*
* for using the list as a queue
*/
/* Place an element at tail of queue */
ReturnStatus Lst_EnQueue(Lst, void *);
/* Remove an element from head of queue */
void *Lst_DeQueue(Lst);
/* 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);
#endif /* _LST_H_ */
/* 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 */

View File

@ -1,121 +0,0 @@
/* $NetBSD: lstAppend.c,v 1.15 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstAppend.c,v 1.15 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstAppend.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstAppend.c,v 1.15 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstAppend.c --
* Add a new node with a new datum after an existing node
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_InsertAfter --
* Create a new node and add it to the given list after the given node.
*
* Input:
* l affected list
* ln node after which to append the datum
* d said datum
*
* Results:
* SUCCESS if all went well.
*
* Side Effects:
* A new ListNode is created and linked in to the List. The lastPtr
* field of the List will be altered if ln is the last node in the
* list. lastPtr and firstPtr will alter if the list was empty and
* ln was NULL.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_InsertAfter(Lst l, LstNode ln, void *d)
{
List list;
ListNode lNode;
ListNode nLNode;
if (LstValid (l) && (ln == NULL && LstIsEmpty (l))) {
goto ok;
}
if (!LstValid (l) || LstIsEmpty (l) || ! LstNodeValid (ln, l)) {
return FAILURE;
}
ok:
list = l;
lNode = ln;
PAlloc (nLNode, ListNode);
nLNode->datum = d;
nLNode->useCount = nLNode->flags = 0;
if (lNode == NULL) {
if (list->isCirc) {
nLNode->nextPtr = nLNode->prevPtr = nLNode;
} else {
nLNode->nextPtr = nLNode->prevPtr = NULL;
}
list->firstPtr = list->lastPtr = nLNode;
} else {
nLNode->prevPtr = lNode;
nLNode->nextPtr = lNode->nextPtr;
lNode->nextPtr = nLNode;
if (nLNode->nextPtr != NULL) {
nLNode->nextPtr->prevPtr = nLNode;
}
if (lNode == list->lastPtr) {
list->lastPtr = nLNode;
}
}
return SUCCESS;
}

View File

@ -1,79 +0,0 @@
/* $NetBSD: lstAtEnd.c,v 1.14 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstAtEnd.c,v 1.14 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstAtEnd.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstAtEnd.c,v 1.14 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstAtEnd.c --
* Add a node at the end of the list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_AtEnd --
* Add a node to the end of the given list
*
* Input:
* l List to which to add the datum
* d Datum to add
*
* Results:
* SUCCESS if life is good.
*
* Side Effects:
* A new ListNode is created and added to the list.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_AtEnd(Lst l, void *d)
{
LstNode end;
end = Lst_Last(l);
return Lst_InsertAfter(l, end, d);
}

View File

@ -1,76 +0,0 @@
/* $NetBSD: lstAtFront.c,v 1.14 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstAtFront.c,v 1.14 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstAtFront.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstAtFront.c,v 1.14 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstAtFront.c --
* Add a node at the front of the list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_AtFront --
* Place a piece of data at the front of a list
*
* Results:
* SUCCESS or FAILURE
*
* Side Effects:
* A new ListNode is created and stuck at the front of the list.
* hence, firstPtr (and possible lastPtr) in the list are altered.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_AtFront(Lst l, void *d)
{
LstNode front;
front = Lst_First(l);
return Lst_InsertBefore(l, front, d);
}

View File

@ -1,85 +0,0 @@
/* $NetBSD: lstClose.c,v 1.12 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstClose.c,v 1.12 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstClose.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstClose.c,v 1.12 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstClose.c --
* Close a list for sequential access.
* 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. Because the list is circular, Lst_Next
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
* used to determine when to stop.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Close --
* Close a list which was opened for sequential access.
*
* Input:
* l The list to close
*
* Results:
* None.
*
* Side Effects:
* The list is closed.
*
*-----------------------------------------------------------------------
*/
void
Lst_Close(Lst l)
{
List list = l;
if (LstValid(l) == TRUE) {
list->isOpen = FALSE;
list->atEnd = Unknown;
}
}

View File

@ -1,184 +0,0 @@
/* $NetBSD: lstConcat.c,v 1.17 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstConcat.c,v 1.17 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstConcat.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstConcat.c,v 1.17 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* listConcat.c --
* Function to concatentate two lists.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Concat --
* Concatenate two lists. New elements are created to hold the data
* elements, if specified, but the elements themselves are not copied.
* If the elements should be duplicated to avoid confusion with another
* list, the Lst_Duplicate function should be called first.
* If LST_CONCLINK is specified, the second list is destroyed since
* its pointers have been corrupted and the list is no longer useable.
*
* Input:
* l1 The list to which l2 is to be appended
* l2 The list to append to l1
* flags LST_CONCNEW if LstNode's should be duplicated
* LST_CONCLINK if should just be relinked
*
* Results:
* SUCCESS if all went well. FAILURE otherwise.
*
* Side Effects:
* New elements are created and appended the first list.
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_Concat(Lst l1, Lst l2, int flags)
{
ListNode ln; /* original LstNode */
ListNode nln; /* new LstNode */
ListNode last; /* the last element in the list. Keeps
* bookkeeping until the end */
List list1 = l1;
List list2 = l2;
if (!LstValid (l1) || !LstValid (l2)) {
return FAILURE;
}
if (flags == LST_CONCLINK) {
if (list2->firstPtr != NULL) {
/*
* We set the nextPtr of the
* last element of list two to be NIL to make the loop easier and
* so we don't need an extra case should the first list turn
* out to be non-circular -- the final element will already point
* to NIL space and the first element will be untouched if it
* existed before and will also point to NIL space if it didn't.
*/
list2->lastPtr->nextPtr = NULL;
/*
* So long as the second list isn't empty, we just link the
* first element of the second list to the last element of the
* first list. If the first list isn't empty, we then link the
* last element of the list to the first element of the second list
* The last element of the second list, if it exists, then becomes
* the last element of the first list.
*/
list2->firstPtr->prevPtr = list1->lastPtr;
if (list1->lastPtr != NULL) {
list1->lastPtr->nextPtr = list2->firstPtr;
} else {
list1->firstPtr = list2->firstPtr;
}
list1->lastPtr = list2->lastPtr;
}
if (list1->isCirc && list1->firstPtr != NULL) {
/*
* If the first list is supposed to be circular and it is (now)
* non-empty, we must make sure it's circular by linking the
* first element to the last and vice versa
*/
list1->firstPtr->prevPtr = list1->lastPtr;
list1->lastPtr->nextPtr = list1->firstPtr;
}
free(l2);
} else if (list2->firstPtr != NULL) {
/*
* We set the nextPtr of the last element of list 2 to be nil to make
* the loop less difficult. The loop simply goes through the entire
* second list creating new LstNodes and filling in the nextPtr, and
* prevPtr to fit into l1 and its datum field from the
* datum field of the corresponding element in l2. The 'last' node
* follows the last of the new nodes along until the entire l2 has
* been appended. Only then does the bookkeeping catch up with the
* changes. During the first iteration of the loop, if 'last' is nil,
* the first list must have been empty so the newly-created node is
* made the first node of the list.
*/
list2->lastPtr->nextPtr = NULL;
for (last = list1->lastPtr, ln = list2->firstPtr;
ln != NULL;
ln = ln->nextPtr)
{
PAlloc (nln, ListNode);
nln->datum = ln->datum;
if (last != NULL) {
last->nextPtr = nln;
} else {
list1->firstPtr = nln;
}
nln->prevPtr = last;
nln->flags = nln->useCount = 0;
last = nln;
}
/*
* Finish bookkeeping. The last new element becomes the last element
* of list one.
*/
list1->lastPtr = last;
/*
* The circularity of both list one and list two must be corrected
* for -- list one because of the new nodes added to it; list two
* because of the alteration of list2->lastPtr's nextPtr to ease the
* above for loop.
*/
if (list1->isCirc) {
list1->lastPtr->nextPtr = list1->firstPtr;
list1->firstPtr->prevPtr = list1->lastPtr;
} else {
last->nextPtr = NULL;
}
if (list2->isCirc) {
list2->lastPtr->nextPtr = list2->firstPtr;
}
}
return SUCCESS;
}

View File

@ -1,76 +0,0 @@
/* $NetBSD: lstDatum.c,v 1.14 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstDatum.c,v 1.14 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstDatum.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstDatum.c,v 1.14 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstDatum.c --
* Return the datum associated with a list node.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Datum --
* Return the datum stored in the given node.
*
* Results:
* The datum or NULL if the node is invalid.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
void *
Lst_Datum(LstNode ln)
{
if (ln != NULL) {
return ln->datum;
} else {
return NULL;
}
}

View File

@ -1,86 +0,0 @@
/* $NetBSD: lstDeQueue.c,v 1.15 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstDeQueue.c,v 1.15 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstDeQueue.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstDeQueue.c,v 1.15 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstDeQueue.c --
* Remove the node and return its datum from the head of the list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_DeQueue --
* Remove and return the datum at the head of the given list.
*
* Results:
* The datum in the node at the head or NULL if the list
* is empty.
*
* Side Effects:
* The head node is removed from the list.
*
*-----------------------------------------------------------------------
*/
void *
Lst_DeQueue(Lst l)
{
void *rd;
ListNode tln;
tln = Lst_First(l);
if (tln == NULL) {
return NULL;
}
rd = tln->datum;
if (Lst_Remove(l, tln) == FAILURE) {
return NULL;
} else {
return rd;
}
}

View File

@ -1,101 +0,0 @@
/* $NetBSD: lstDestroy.c,v 1.16 2008/12/13 15:19:29 dsl 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstDestroy.c,v 1.16 2008/12/13 15:19:29 dsl Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstDestroy.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstDestroy.c,v 1.16 2008/12/13 15:19:29 dsl Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstDestroy.c --
* Nuke a list and all its resources
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Destroy --
* Destroy a list and free all its resources. If the freeProc is
* given, it is called with the datum from each node in turn before
* the node is freed.
*
* Results:
* None.
*
* Side Effects:
* The given list is freed in its entirety.
*
*-----------------------------------------------------------------------
*/
void
Lst_Destroy(Lst list, FreeProc *freeProc)
{
ListNode ln;
ListNode tln = NULL;
if (list == NULL)
return;
/* To ease scanning */
if (list->lastPtr != NULL)
list->lastPtr->nextPtr = NULL;
else {
free(list);
return;
}
if (freeProc) {
for (ln = list->firstPtr; ln != NULL; ln = tln) {
tln = ln->nextPtr;
freeProc(ln->datum);
free(ln);
}
} else {
for (ln = list->firstPtr; ln != NULL; ln = tln) {
tln = ln->nextPtr;
free(ln);
}
}
free(list);
}

View File

@ -1,107 +0,0 @@
/* $NetBSD: lstDupl.c,v 1.17 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstDupl.c,v 1.17 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstDupl.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstDupl.c,v 1.17 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* listDupl.c --
* Duplicate a list. This includes duplicating the individual
* elements.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Duplicate --
* Duplicate an entire list. If a function to copy a void *is
* given, the individual client elements will be duplicated as well.
*
* Input:
* l the list to duplicate
* copyProc A function to duplicate each void *
*
* Results:
* The new Lst structure or NULL if failure.
*
* Side Effects:
* A new list is created.
*-----------------------------------------------------------------------
*/
Lst
Lst_Duplicate(Lst l, DuplicateProc *copyProc)
{
Lst nl;
ListNode ln;
List list = l;
if (!LstValid (l)) {
return NULL;
}
nl = Lst_Init(list->isCirc);
if (nl == NULL) {
return NULL;
}
ln = list->firstPtr;
while (ln != NULL) {
if (copyProc != NULL) {
if (Lst_AtEnd(nl, copyProc(ln->datum)) == FAILURE) {
return NULL;
}
} else if (Lst_AtEnd(nl, ln->datum) == FAILURE) {
return NULL;
}
if (list->isCirc && ln == list->lastPtr) {
ln = NULL;
} else {
ln = ln->nextPtr;
}
}
return nl;
}

View File

@ -1,77 +0,0 @@
/* $NetBSD: lstEnQueue.c,v 1.14 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstEnQueue.c,v 1.14 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstEnQueue.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstEnQueue.c,v 1.14 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstEnQueue.c--
* Treat the list as a queue and place a datum at its end
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_EnQueue --
* Add the datum to the tail of the given list.
*
* Results:
* SUCCESS or FAILURE as returned by Lst_InsertAfter.
*
* Side Effects:
* the lastPtr field is altered all the time and the firstPtr field
* will be altered if the list used to be empty.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_EnQueue(Lst l, void *d)
{
if (LstValid (l) == FALSE) {
return FAILURE;
}
return Lst_InsertAfter(l, Lst_Last(l), d);
}

View File

@ -1,73 +0,0 @@
/* $NetBSD: lstFind.c,v 1.16 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstFind.c,v 1.16 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstFind.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstFind.c,v 1.16 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstFind.c --
* Find a node on a list.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Find --
* Find a node on the given list using the given comparison function
* and the given datum.
*
* Results:
* The found node or NULL if none matches.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_Find(Lst l, const void *d, int (*cProc)(const void *, const void *))
{
return Lst_FindFrom(l, Lst_First(l), d, cProc);
}

View File

@ -1,89 +0,0 @@
/* $NetBSD: lstFindFrom.c,v 1.16 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstFindFrom.c,v 1.16 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstFindFrom.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstFindFrom.c,v 1.16 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstFindFrom.c --
* Find a node on a list from a given starting point. Used by Lst_Find.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_FindFrom --
* Search for a node starting and ending with the given one on the
* given list using the passed datum and comparison function to
* determine when it has been found.
*
* Results:
* The found node or NULL
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_FindFrom(Lst l, LstNode ln, const void *d,
int (*cProc)(const void *, const void *))
{
ListNode tln;
if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) {
return NULL;
}
tln = ln;
do {
if ((*cProc)(tln->datum, d) == 0)
return tln;
tln = tln->nextPtr;
} while (tln != ln && tln != NULL);
return NULL;
}

View File

@ -1,76 +0,0 @@
/* $NetBSD: lstFirst.c,v 1.13 2020/07/03 08:37:56 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstFirst.c,v 1.13 2020/07/03 08:37:56 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstFirst.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstFirst.c,v 1.13 2020/07/03 08:37:56 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstFirst.c --
* Return the first node of a list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_First --
* Return the first node on the given list.
*
* Results:
* The first node or NULL if the list is empty.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_First(Lst l)
{
if (!LstValid (l) || LstIsEmpty (l)) {
return NULL;
} else {
return l->firstPtr;
}
}

View File

@ -1,75 +0,0 @@
/* $NetBSD: lstForEach.c,v 1.14 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstForEach.c,v 1.14 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstForEach.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstForEach.c,v 1.14 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstForeach.c --
* Perform a given function on all elements of a list.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_ForEach --
* Apply the given function to each element of the given list. The
* function should return 0 if Lst_ForEach should continue and non-
* zero if it should abort.
*
* Results:
* None.
*
* Side Effects:
* Only those created by the passed-in function.
*
*-----------------------------------------------------------------------
*/
/*VARARGS2*/
int
Lst_ForEach(Lst l, int (*proc)(void *, void *), void *d)
{
return Lst_ForEachFrom(l, Lst_First(l), proc, d);
}

View File

@ -1,124 +0,0 @@
/* $NetBSD: lstForEachFrom.c,v 1.18 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstForEachFrom.c,v 1.18 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstForEachFrom.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstForEachFrom.c,v 1.18 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* lstForEachFrom.c --
* Perform a given function on all elements of a list starting from
* a given point.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_ForEachFrom --
* 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.
*
* Results:
* None.
*
* Side Effects:
* Only those created by the passed-in function.
*
*-----------------------------------------------------------------------
*/
/*VARARGS2*/
int
Lst_ForEachFrom(Lst l, LstNode ln, int (*proc)(void *, void *),
void *d)
{
ListNode tln = ln;
List list = l;
ListNode next;
Boolean done;
int result;
if (!LstValid (list) || LstIsEmpty (list)) {
return 0;
}
do {
/*
* Take care of having the current element deleted out from under
* us.
*/
next = tln->nextPtr;
/*
* We're done with the traversal if
* - the next node to examine is the first in the queue or
* doesn't exist and
* - nothing's been added after the current node (check this
* after proc() has been called).
*/
done = (next == NULL || next == list->firstPtr);
(void) tln->useCount++;
result = (*proc) (tln->datum, d);
(void) 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->nextPtr) {
next = tln->nextPtr;
done = 0;
}
if (tln->flags & LN_DELETED) {
free((char *)tln);
}
tln = next;
} while (!result && !LstIsEmpty(list) && !done);
return result;
}

View File

@ -1,85 +0,0 @@
/* $NetBSD: lstInit.c,v 1.13 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstInit.c,v 1.13 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstInit.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstInit.c,v 1.13 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* init.c --
* Initialize a new linked list.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Init --
* Create and initialize a new list.
*
* Input:
* circ TRUE if the list should be made circular
*
* Results:
* The created list.
*
* Side Effects:
* A list is created, what else?
*
*-----------------------------------------------------------------------
*/
Lst
Lst_Init(Boolean circ)
{
List nList;
PAlloc (nList, List);
nList->firstPtr = NULL;
nList->lastPtr = NULL;
nList->isOpen = FALSE;
nList->isCirc = circ;
nList->atEnd = Unknown;
return nList;
}

View File

@ -1,121 +0,0 @@
/* $NetBSD: lstInsert.c,v 1.15 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstInsert.c,v 1.15 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstInsert.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstInsert.c,v 1.15 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstInsert.c --
* Insert a new datum before an old one
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_InsertBefore --
* Insert a new node with the given piece of data before the given
* node in the given list.
*
* Input:
* l list to manipulate
* ln node before which to insert d
* d datum to be inserted
*
* Results:
* SUCCESS or FAILURE.
*
* Side Effects:
* the firstPtr field will be changed if ln is the first node in the
* list.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_InsertBefore(Lst l, LstNode ln, void *d)
{
ListNode nLNode; /* new lnode for d */
ListNode lNode = ln;
List list = l;
/*
* check validity of arguments
*/
if (LstValid (l) && (LstIsEmpty (l) && ln == NULL))
goto ok;
if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) {
return FAILURE;
}
ok:
PAlloc (nLNode, ListNode);
nLNode->datum = d;
nLNode->useCount = nLNode->flags = 0;
if (ln == NULL) {
if (list->isCirc) {
nLNode->prevPtr = nLNode->nextPtr = nLNode;
} else {
nLNode->prevPtr = nLNode->nextPtr = NULL;
}
list->firstPtr = list->lastPtr = nLNode;
} else {
nLNode->prevPtr = lNode->prevPtr;
nLNode->nextPtr = lNode;
if (nLNode->prevPtr != NULL) {
nLNode->prevPtr->nextPtr = nLNode;
}
lNode->prevPtr = nLNode;
if (lNode == list->firstPtr) {
list->firstPtr = nLNode;
}
}
return SUCCESS;
}

View File

@ -1,105 +0,0 @@
/* $NetBSD: lstInt.h,v 1.22 2014/09/07 20:55:34 joerg 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: @(#)lstInt.h 8.1 (Berkeley) 6/6/93
*/
/*-
* lstInt.h --
* Internals for the list library
*/
#ifndef _LSTINT_H_
#define _LSTINT_H_
#include "../lst.h"
#include "../make_malloc.h"
typedef struct ListNode {
struct ListNode *prevPtr; /* previous element in list */
struct ListNode *nextPtr; /* next in list */
unsigned int useCount:8, /* Count of functions using the node.
* node may not be deleted until count
* goes to 0 */
flags:8; /* Node status flags */
void *datum; /* datum associated with this element */
} *ListNode;
/*
* Flags required for synchronization
*/
#define LN_DELETED 0x0001 /* List node should be removed when done */
typedef enum {
Head, Middle, Tail, Unknown
} Where;
typedef struct List {
ListNode firstPtr; /* first node in list */
ListNode lastPtr; /* last node in list */
Boolean isCirc; /* true if the list should be considered
* circular */
/*
* fields for sequential access
*/
Where atEnd; /* Where in the list the last access was */
Boolean isOpen; /* true if list has been Lst_Open'ed */
ListNode curPtr; /* current node, if open. NULL if
* *just* opened */
ListNode prevPtr; /* Previous node, if open. Used by
* Lst_Remove */
} *List;
/*
* PAlloc (var, ptype) --
* Allocate a pointer-typedef structure 'ptype' into the variable 'var'
*/
#define PAlloc(var,ptype) var = (ptype) bmake_malloc(sizeof *(var))
/*
* LstValid (l) --
* Return TRUE if the list l is valid
*/
#define LstValid(l) ((Lst)(l) != NULL)
/*
* LstNodeValid (ln, l) --
* Return TRUE if the LstNode ln is valid with respect to l
*/
#define LstNodeValid(ln, l) ((ln) != NULL)
/*
* LstIsEmpty (l) --
* TRUE if the list l is empty.
*/
#define LstIsEmpty(l) (((List)(l))->firstPtr == NULL)
#endif /* _LSTINT_H_ */

View File

@ -1,86 +0,0 @@
/* $NetBSD: lstIsAtEnd.c,v 1.14 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstIsAtEnd.c,v 1.14 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstIsAtEnd.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstIsAtEnd.c,v 1.14 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstIsAtEnd.c --
* Tell if the current node is at the end of the list.
* 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. Because the list is circular, Lst_Next
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
* used to determine when to stop.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_IsAtEnd --
* Return true if have reached the end of the given list.
*
* Results:
* TRUE if at the end of the list (this includes the list not being
* open or being invalid) or FALSE if not. We return TRUE if the list
* is invalid or unopend so as to cause the caller to exit its loop
* asap, the assumption being that the loop is of the form
* while (!Lst_IsAtEnd (l)) {
* ...
* }
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
Boolean
Lst_IsAtEnd(Lst l)
{
List list = l;
return !LstValid (l) || !list->isOpen ||
list->atEnd == Head || list->atEnd == Tail;
}

View File

@ -1,74 +0,0 @@
/* $NetBSD: lstIsEmpty.c,v 1.12 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstIsEmpty.c,v 1.12 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstIsEmpty.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstIsEmpty.c,v 1.12 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstIsEmpty.c --
* A single function to decide if a list is empty
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_IsEmpty --
* Return TRUE if the given list is empty.
*
* Results:
* TRUE if the list is empty, FALSE otherwise.
*
* Side Effects:
* None.
*
* A list is considered empty if its firstPtr == NULL (or if
* the list itself is NULL).
*-----------------------------------------------------------------------
*/
Boolean
Lst_IsEmpty(Lst l)
{
return !LstValid(l) || LstIsEmpty(l);
}

View File

@ -1,76 +0,0 @@
/* $NetBSD: lstLast.c,v 1.13 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstLast.c,v 1.13 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstLast.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstLast.c,v 1.13 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstLast.c --
* Return the last element of a list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Last --
* Return the last node on the list l.
*
* Results:
* The requested node or NULL if the list is empty.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_Last(Lst l)
{
if (!LstValid(l) || LstIsEmpty (l)) {
return NULL;
} else {
return l->lastPtr;
}
}

View File

@ -1,77 +0,0 @@
/* $NetBSD: lstMember.c,v 1.14 2013/11/14 00:01:28 sjg 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.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstMember.c,v 1.14 2013/11/14 00:01:28 sjg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstMember.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstMember.c,v 1.14 2013/11/14 00:01:28 sjg Exp $");
#endif
#endif /* not lint */
#endif
/*-
* lstMember.c --
* See if a given datum is on a given list.
*/
#include "lstInt.h"
LstNode
Lst_Member(Lst l, void *d)
{
List list = l;
ListNode lNode;
if (list == NULL) {
return NULL;
}
lNode = list->firstPtr;
if (lNode == NULL) {
return NULL;
}
do {
if (lNode->datum == d) {
return lNode;
}
lNode = lNode->nextPtr;
} while (lNode != NULL && lNode != list->firstPtr);
return NULL;
}

View File

@ -1,119 +0,0 @@
/* $NetBSD: lstNext.c,v 1.13 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstNext.c,v 1.13 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstNext.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstNext.c,v 1.13 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstNext.c --
* Return the next node for a list.
* 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. Because the list is circular, Lst_Next
* and Lst_Prev will go around the list forever. Lst_IsAtEnd must be
* used to determine when to stop.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Next --
* Return the next node for the given list.
*
* Results:
* The next node or NULL if the list has yet to be opened. Also
* if the list is non-circular and the end has been reached, NULL
* is returned.
*
* Side Effects:
* the curPtr field is updated.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_Next(Lst l)
{
ListNode tln;
List list = l;
if ((LstValid (l) == FALSE) ||
(list->isOpen == FALSE)) {
return NULL;
}
list->prevPtr = list->curPtr;
if (list->curPtr == NULL) {
if (list->atEnd == Unknown) {
/*
* If we're just starting out, atEnd will be Unknown.
* Then we want to start this thing off in the right
* direction -- at the start with atEnd being Middle.
*/
list->curPtr = tln = list->firstPtr;
list->atEnd = Middle;
} else {
tln = NULL;
list->atEnd = Tail;
}
} else {
tln = list->curPtr->nextPtr;
list->curPtr = tln;
if (tln == list->firstPtr || tln == NULL) {
/*
* If back at the front, then we've hit the end...
*/
list->atEnd = Tail;
} else {
/*
* Reset to Middle if gone past first.
*/
list->atEnd = Middle;
}
}
return tln;
}

View File

@ -1,86 +0,0 @@
/* $NetBSD: lstOpen.c,v 1.13 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstOpen.c,v 1.13 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstOpen.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstOpen.c,v 1.13 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstOpen.c --
* Open a list for sequential access. 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.
* If the list is circular, Lst_Next and Lst_Prev will go around
* the list forever. Lst_IsAtEnd must be used to determine when to stop.
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Open --
* Open a list for sequential access. A list can still be searched,
* etc., without confusing these functions.
*
* Results:
* SUCCESS or FAILURE.
*
* Side Effects:
* isOpen is set TRUE and curPtr is set to NULL so the
* other sequential functions no it was just opened and can choose
* the first element accessed based on this.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_Open(Lst l)
{
if (LstValid (l) == FALSE) {
return FAILURE;
}
(l)->isOpen = TRUE;
(l)->atEnd = LstIsEmpty (l) ? Head : Unknown;
(l)->curPtr = NULL;
return SUCCESS;
}

View File

@ -1,78 +0,0 @@
/* $NetBSD: lstPrev.c,v 1.4 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstPrev.c,v 1.4 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstSucc.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstPrev.c,v 1.4 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstPrev.c --
* return the predecessor to a given node
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Prev --
* Return the predecessor to the given node on its list.
*
* Results:
* The predecessor of the node, if it exists (note that on a circular
* list, if the node is the only one in the list, it is its own
* predecessor).
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_Prev(LstNode ln)
{
if (ln == NULL) {
return NULL;
} else {
return ln->prevPtr;
}
}

View File

@ -1,134 +0,0 @@
/* $NetBSD: lstRemove.c,v 1.17 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstRemove.c,v 1.17 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstRemove.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstRemove.c,v 1.17 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstRemove.c --
* Remove an element from a list
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Remove --
* Remove the given node from the given list.
*
* Results:
* SUCCESS or FAILURE.
*
* Side Effects:
* The list's firstPtr will be set to NULL if ln is the last
* node on the list. firsPtr and lastPtr will be altered if ln is
* either the first or last node, respectively, on the list.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_Remove(Lst l, LstNode ln)
{
List list = l;
ListNode lNode = ln;
if (!LstValid (l) || !LstNodeValid (ln, l)) {
return FAILURE;
}
/*
* unlink it from the list
*/
if (lNode->nextPtr != NULL) {
lNode->nextPtr->prevPtr = lNode->prevPtr;
}
if (lNode->prevPtr != NULL) {
lNode->prevPtr->nextPtr = lNode->nextPtr;
}
/*
* if either the firstPtr or lastPtr of the list point to this node,
* adjust them accordingly
*/
if (list->firstPtr == lNode) {
list->firstPtr = lNode->nextPtr;
}
if (list->lastPtr == lNode) {
list->lastPtr = lNode->prevPtr;
}
/*
* 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 (prevPtr == NULL), we set the
* end to be Unknown, since it is.
*/
if (list->isOpen && (list->curPtr == lNode)) {
list->curPtr = list->prevPtr;
if (list->curPtr == NULL) {
list->atEnd = Unknown;
}
}
/*
* the only way firstPtr can still point to ln is if ln is the last
* node on the list (the list is circular, so lNode->nextptr == lNode in
* this case). The list is, therefore, empty and is marked as such
*/
if (list->firstPtr == lNode) {
list->firstPtr = NULL;
}
/*
* note that the datum is unmolested. The caller must free it as
* necessary and as expected.
*/
if (lNode->useCount == 0) {
free(ln);
} else {
lNode->flags |= LN_DELETED;
}
return SUCCESS;
}

View File

@ -1,77 +0,0 @@
/* $NetBSD: lstReplace.c,v 1.14 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstReplace.c,v 1.14 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstReplace.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstReplace.c,v 1.14 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstReplace.c --
* Replace the datum in a node with a new datum
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Replace --
* Replace the datum in the given node with the new datum
*
* Results:
* SUCCESS or FAILURE.
*
* Side Effects:
* The datum field fo the node is altered.
*
*-----------------------------------------------------------------------
*/
ReturnStatus
Lst_Replace(LstNode ln, void *d)
{
if (ln == NULL) {
return FAILURE;
} else {
(ln)->datum = d;
return SUCCESS;
}
}

View File

@ -1,78 +0,0 @@
/* $NetBSD: lstSucc.c,v 1.14 2020/07/03 08:37:57 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: lstSucc.c,v 1.14 2020/07/03 08:37:57 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lstSucc.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: lstSucc.c,v 1.14 2020/07/03 08:37:57 rillig Exp $");
#endif
#endif /* not lint */
#endif
/*-
* LstSucc.c --
* return the successor to a given node
*/
#include "lstInt.h"
/*-
*-----------------------------------------------------------------------
* Lst_Succ --
* Return the successor to the given node on its list.
*
* Results:
* The successor of the node, if it exists (note that on a circular
* list, if the node is the only one in the list, it is its own
* successor).
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
LstNode
Lst_Succ(LstNode ln)
{
if (ln == NULL) {
return NULL;
} else {
return ln->nextPtr;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.279 2020/07/03 08:13:23 rillig Exp $ */
/* $NetBSD: main.c,v 1.331 2020/08/30 19:56:02 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,7 +69,7 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: main.c,v 1.279 2020/07/03 08:13:23 rillig Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.331 2020/08/30 19:56:02 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#else
__RCSID("$NetBSD: main.c,v 1.279 2020/07/03 08:13:23 rillig Exp $");
__RCSID("$NetBSD: main.c,v 1.331 2020/08/30 19:56:02 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -124,13 +124,13 @@ __RCSID("$NetBSD: main.c,v 1.279 2020/07/03 08:13:23 rillig Exp $");
#include <sys/utsname.h>
#include "wait.h"
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include "make.h"
#include "hash.h"
@ -162,7 +162,8 @@ 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 */
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 */
@ -180,14 +181,13 @@ Boolean beSilent; /* -s flag */
Boolean oldVars; /* variable substitution style */
Boolean checkEnvFirst; /* -e flag */
Boolean parseWarnFatal; /* -W flag */
Boolean jobServer; /* -J 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 void *, const void *);
static int ReadMakefile(const char *);
static void usage(void) MAKE_ATTR_DEAD;
static void purge_cached_realpaths(void);
@ -257,7 +257,7 @@ parse_debug_options(const char *argvalue)
for (modules = argvalue; *modules; ++modules) {
switch (*modules) {
case 'A':
debug = ~0;
debug = ~(0|DEBUG_LINT);
break;
case 'a':
debug |= DEBUG_ARCH;
@ -291,9 +291,15 @@ parse_debug_options(const char *argvalue)
++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;
@ -375,7 +381,7 @@ parse_debug_options(const char *argvalue)
/*
* does path contain any relative components
*/
static int
static Boolean
is_relpath(const char *path)
{
const char *cp;
@ -383,10 +389,7 @@ is_relpath(const char *path)
if (path[0] != '/')
return TRUE;
cp = path;
do {
cp = strstr(cp, "/.");
if (!cp)
break;
while ((cp = strstr(cp, "/.")) != NULL) {
cp += 2;
if (cp[0] == '/' || cp[0] == '\0')
return TRUE;
@ -394,7 +397,7 @@ is_relpath(const char *path)
if (cp[1] == '/' || cp[1] == '\0')
return TRUE;
}
} while (cp);
}
return FALSE;
}
@ -416,7 +419,7 @@ static void
MainParseArgs(int argc, char **argv)
{
char *p;
int c = '?';
char c = '?';
int arginc;
char *argvalue;
const char *getopt_def;
@ -531,7 +534,6 @@ MainParseArgs(int argc, char **argv)
} else {
Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
jobServer = TRUE;
}
break;
case 'N':
@ -553,7 +555,7 @@ MainParseArgs(int argc, char **argv)
case 'v':
if (argvalue == NULL) goto noarg;
printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS;
(void)Lst_AtEnd(variables, argvalue);
Lst_Append(variables, argvalue);
Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
break;
@ -581,7 +583,7 @@ MainParseArgs(int argc, char **argv)
break;
case 'f':
if (argvalue == NULL) goto noarg;
(void)Lst_AtEnd(makefiles, argvalue);
Lst_Append(makefiles, argvalue);
break;
case 'i':
ignoreErrors = TRUE;
@ -674,7 +676,7 @@ MainParseArgs(int argc, char **argv)
Punt("illegal (null) argument.");
if (*argv[1] == '-' && !dashDash)
goto rearg;
(void)Lst_AtEnd(create, bmake_strdup(argv[1]));
Lst_Append(create, bmake_strdup(argv[1]));
}
return;
@ -705,12 +707,10 @@ MainParseArgs(int argc, char **argv)
void
Main_ParseArgLine(const char *line)
{
char **argv; /* Manufactured argument vector */
int argc; /* Number of arguments in argv */
char *args; /* Space used by the args */
char *buf, *p1;
char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
size_t len;
Words words;
char *p1;
const char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
char *buf;
if (line == NULL)
return;
@ -733,21 +733,19 @@ Main_ParseArgLine(const char *line)
return;
}
#endif
buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
(void)snprintf(buf, len, "%s %s", argv0, line);
buf = str_concat3(argv0, " ", line);
free(p1);
argv = brk_string(buf, &argc, TRUE, &args);
if (argv == NULL) {
words = Str_Words(buf, TRUE);
if (words.words == NULL) {
Error("Unterminated quoted string [%s]", buf);
free(buf);
return;
}
free(buf);
MainParseArgs(argc, argv);
MainParseArgs((int)words.len, words.words);
free(args);
free(argv);
Words_Free(words);
}
Boolean
@ -775,7 +773,7 @@ Main_SetObjdir(const char *fmt, ...)
(void)fprintf(stderr, "make warning: %s: %s.\n",
path, strerror(errno));
} else {
strncpy(objdir, path, MAXPATHLEN);
snprintf(objdir, sizeof objdir, "%s", path);
Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
setenv("PWD", objdir, 1);
Dir_InitDot();
@ -792,37 +790,44 @@ Main_SetObjdir(const char *fmt, ...)
static Boolean
Main_SetVarObjdir(const char *var, const char *suffix)
{
char *p, *path, *xpath;
char *path_freeIt;
const char *path = Var_Value(var, VAR_CMD, &path_freeIt);
const char *xpath;
char *xpath_freeIt;
if ((path = Var_Value(var, VAR_CMD, &p)) == NULL ||
*path == '\0')
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 = Var_Subst(NULL, path, VAR_GLOBAL, VARF_WANTRES);
else
xpath = path;
xpath = xpath_freeIt = Var_Subst(path, VAR_GLOBAL,
VARE_WANTRES);
(void)Main_SetObjdir("%s%s", xpath, suffix);
if (xpath != path)
free(xpath);
free(p);
bmake_free(xpath_freeIt);
bmake_free(path_freeIt);
return TRUE;
}
/*-
* ReadAllMakefiles --
* wrapper around ReadMakefile() to read all.
*
* Results:
* TRUE if ok, FALSE on error
*/
static int
ReadAllMakefiles(const void *p, const void *q)
/* 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(p, q) == 0;
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
@ -835,7 +840,7 @@ str2Lst_Append(Lst lp, char *str, const char *sep)
sep = " \t";
for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
(void)Lst_AtEnd(lp, cp);
Lst_Append(lp, cp);
n++;
}
return n;
@ -863,13 +868,13 @@ siginfo(int signo MAKE_ATTR_UNUSED)
void
MakeMode(const char *mode)
{
char *mp = NULL;
char *mode_freeIt = NULL;
if (!mode)
mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}",
VAR_GLOBAL, VARF_WANTRES);
if (mode == NULL)
mode = mode_freeIt = Var_Subst("${" MAKE_MODE ":tl}",
VAR_GLOBAL, VARE_WANTRES);
if (mode && *mode) {
if (mode[0] != '\0') {
if (strstr(mode, "compat")) {
compatMake = TRUE;
forceJobs = FALSE;
@ -880,7 +885,7 @@ MakeMode(const char *mode)
#endif
}
free(mp);
free(mode_freeIt);
}
static void
@ -896,15 +901,13 @@ doPrintVars(void)
else
expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
for (ln = Lst_First(variables); ln != NULL;
ln = Lst_Succ(ln)) {
char *var = (char *)Lst_Datum(ln);
char *value;
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(NULL, var, VAR_GLOBAL,
VARF_WANTRES);
value = p1 = Var_Subst(var, VAR_GLOBAL, VARE_WANTRES);
} else if (expandVars) {
char tmp[128];
int len = snprintf(tmp, sizeof(tmp), "${%s}", var);
@ -912,13 +915,12 @@ doPrintVars(void)
if (len >= (int)sizeof(tmp))
Fatal("%s: variable name too big: %s",
progname, var);
value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL,
VARF_WANTRES);
value = p1 = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES);
} else {
value = Var_Value(var, VAR_GLOBAL, &p1);
}
printf("%s\n", value ? value : "");
free(p1);
bmake_free(p1);
}
}
@ -962,7 +964,7 @@ runTargets(void)
Compat_Run(targs);
outOfDate = FALSE;
}
Lst_Destroy(targs, NULL);
Lst_Free(targs);
return outOfDate;
}
@ -1079,7 +1081,7 @@ main(int argc, char **argv)
#else
#ifndef MACHINE_ARCH
#ifdef MAKE_MACHINE_ARCH
machine_arch = MAKE_MACHINE_ARCH;
machine_arch = MAKE_MACHINE_ARCH;
#else
machine_arch = "unknown";
#endif
@ -1113,11 +1115,11 @@ main(int argc, char **argv)
VAR_GLOBAL);
Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL);
create = Lst_Init(FALSE);
makefiles = Lst_Init(FALSE);
create = Lst_Init();
makefiles = Lst_Init();
printVars = 0;
debugVflag = FALSE;
variables = Lst_Init(FALSE);
variables = Lst_Init();
beSilent = FALSE; /* Print commands as executed */
ignoreErrors = FALSE; /* Pay attention to non-zero returns */
noExecute = FALSE; /* Execute all commands */
@ -1199,7 +1201,7 @@ main(int argc, char **argv)
#ifdef USE_META
meta_init();
#endif
Dir_Init(NULL); /* Dir_* safe to call from MainParseArgs */
Dir_Init();
/*
* First snag any flags out of the MAKE environment variable.
@ -1265,8 +1267,8 @@ main(int argc, char **argv)
(void)strncpy(curdir, pwd, MAXPATHLEN);
}
}
free(ptmp1);
free(ptmp2);
bmake_free(ptmp1);
bmake_free(ptmp2);
}
#endif
Var_Set(".CURDIR", curdir, VAR_GLOBAL);
@ -1280,7 +1282,7 @@ main(int argc, char **argv)
* and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
* of these paths exist, just use .CURDIR.
*/
Dir_Init(curdir);
Dir_InitDir(curdir);
(void)Main_SetObjdir("%s", curdir);
if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) &&
@ -1312,10 +1314,8 @@ main(int argc, char **argv)
if (!Lst_IsEmpty(create)) {
LstNode ln;
for (ln = Lst_First(create); ln != NULL;
ln = Lst_Succ(ln)) {
char *name = (char *)Lst_Datum(ln);
for (ln = Lst_First(create); ln != NULL; ln = LstNode_Next(ln)) {
char *name = LstNode_Datum(ln);
Var_Append(".TARGETS", name, VAR_GLOBAL);
}
} else
@ -1327,7 +1327,8 @@ main(int argc, char **argv)
* add the directories from the DEFSYSPATH (more than one may be given
* as dir1:...:dirn) to the system include path.
*/
if (syspath == NULL || *syspath == '\0')
/* XXX: mismatch: the -m option sets sysIncPath, not syspath */
if (syspath == NULL || syspath[0] == '\0')
syspath = defsyspath;
else
syspath = bmake_strdup(syspath);
@ -1353,48 +1354,46 @@ main(int argc, char **argv)
/*
* Read in the built-in rules first, followed by the specified
* makefile, if it was (makefile != NULL), or the default
* makefile and Makefile, in that order, if it wasn't.
* 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(FALSE);
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, NULL, ReadMakefile);
ln = Lst_Find(sysMkPath, ReadMakefileSucceeded, NULL);
if (ln == NULL)
Fatal("%s: cannot open %s.", progname,
(char *)Lst_Datum(ln));
(char *)LstNode_Datum(Lst_First(sysMkPath)));
}
if (!Lst_IsEmpty(makefiles)) {
LstNode ln;
ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
ln = Lst_Find(makefiles, ReadMakefileFailed, NULL);
if (ln != NULL)
Fatal("%s: cannot open %s.", progname,
(char *)Lst_Datum(ln));
(char *)LstNode_Datum(ln));
} else {
p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
VAR_CMD, VARF_WANTRES);
if (p1) {
p1 = Var_Subst("${" MAKEFILE_PREFERENCE "}",
VAR_CMD, VARE_WANTRES);
(void)str2Lst_Append(makefiles, p1, NULL);
(void)Lst_Find(makefiles, NULL, ReadMakefile);
(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(NULL, "${.MAKE.DEPENDFILE:T}",
VAR_CMD, VARF_WANTRES);
makeDependfile = Var_Subst("${.MAKE.DEPENDFILE:T}",
VAR_CMD, VARE_WANTRES);
doing_depend = TRUE;
(void)ReadMakefile(makeDependfile, NULL);
(void)ReadMakefile(makeDependfile);
doing_depend = FALSE;
}
@ -1404,14 +1403,14 @@ main(int argc, char **argv)
MakeMode(NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
free(p1);
bmake_free(p1);
if (!forceJobs && !compatMake &&
Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) {
char *value;
int n;
value = Var_Subst(NULL, "${.MAKE.JOBS}", VAR_GLOBAL, VARF_WANTRES);
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",
@ -1439,8 +1438,9 @@ main(int argc, char **argv)
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);
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 */
@ -1461,7 +1461,7 @@ main(int argc, char **argv)
*/
static char VPATH[] = "${VPATH}";
vpath = Var_Subst(NULL, VPATH, VAR_CMD, VARF_WANTRES);
vpath = Var_Subst(VPATH, VAR_CMD, VARE_WANTRES);
path = vpath;
do {
/* skip to end of directory */
@ -1502,9 +1502,9 @@ main(int argc, char **argv)
}
#ifdef CLEANUP
Lst_Destroy(variables, NULL);
Lst_Destroy(makefiles, NULL);
Lst_Destroy(create, (FreeProc *)free);
Lst_Free(variables);
Lst_Free(makefiles);
Lst_Destroy(create, free);
#endif
/* print the graph now it's been processed if the user requested it */
@ -1522,7 +1522,7 @@ main(int argc, char **argv)
meta_finish();
#endif
Suff_End();
Targ_End();
Targ_End();
Arch_End();
Var_End();
Parse_End();
@ -1533,23 +1533,16 @@ main(int argc, char **argv)
return outOfDate ? 1 : 0;
}
/*-
* ReadMakefile --
* Open and parse the given makefile.
/* Open and parse the given makefile, with all its side effects.
*
* Results:
* 0 if ok. -1 if couldn't open file.
*
* Side Effects:
* lots
*/
static int
ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
ReadMakefile(const char *fname)
{
const char *fname = p; /* makefile to read */
int fd;
size_t len = MAXPATHLEN;
char *name, *path = bmake_malloc(len);
char *name, *path = NULL;
if (!strcmp(fname, "-")) {
Parse_File(NULL /*stdin*/, -1);
@ -1557,22 +1550,16 @@ ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
} else {
/* if we've chdir'd, rebuild the path name */
if (strcmp(curdir, objdir) && *fname != '/') {
size_t plen = strlen(curdir) + strlen(fname) + 2;
if (len < plen)
path = bmake_realloc(path, len = 2 * plen);
(void)snprintf(path, len, "%s/%s", curdir, 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) */
plen = strlen(objdir) + strlen(fname) + 2;
if (len < plen)
path = bmake_realloc(path, len = 2 * plen);
(void)snprintf(path, len, "%s/%s", objdir, fname);
path = str_concat3(objdir, "/", fname);
fd = open(path, O_RDONLY);
if (fd != -1) {
fname = path;
@ -1613,31 +1600,32 @@ ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
/*-
* Cmd_Exec --
* Execute the command in cmd, and return the output of that command
* in a string.
* in a string. In the output, newlines are replaced with spaces.
*
* Results:
* A string containing the output of the command, or the empty string
* If errnum is not NULL, it contains the reason for the command failure
* 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 **errnum)
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() */
char *res; /* result */
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 cc; /* bytes read, or -1 */
int savederr; /* saved errno */
*errnum = NULL;
*errfmt = NULL;
if (!shellName)
Shell_Init();
@ -1653,7 +1641,7 @@ Cmd_Exec(const char *cmd, const char **errnum)
* Open a pipe for fetching its output
*/
if (pipe(fds) == -1) {
*errnum = "Couldn't create pipe for \"%s\"";
*errfmt = "Couldn't create pipe for \"%s\"";
goto bad;
}
@ -1682,7 +1670,7 @@ Cmd_Exec(const char *cmd, const char **errnum)
/*NOTREACHED*/
case -1:
*errnum = "Couldn't exec \"%s\"";
*errfmt = "Couldn't exec \"%s\"";
goto bad;
default:
@ -1696,12 +1684,12 @@ Cmd_Exec(const char *cmd, const char **errnum)
do {
char result[BUFSIZ];
cc = read(fds[0], result, sizeof(result));
if (cc > 0)
Buf_AddBytes(&buf, cc, result);
bytes_read = read(fds[0], result, sizeof(result));
if (bytes_read > 0)
Buf_AddBytes(&buf, result, (size_t)bytes_read);
}
while (cc > 0 || (cc == -1 && errno == EINTR));
if (cc == -1)
while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR));
if (bytes_read == -1)
savederr = errno;
/*
@ -1716,43 +1704,28 @@ Cmd_Exec(const char *cmd, const char **errnum)
JobReapChild(pid, status, FALSE);
continue;
}
cc = Buf_Size(&buf);
res_len = Buf_Size(&buf);
res = Buf_Destroy(&buf, FALSE);
if (savederr != 0)
*errnum = "Couldn't read shell's output for \"%s\"";
*errfmt = "Couldn't read shell's output for \"%s\"";
if (WIFSIGNALED(status))
*errnum = "\"%s\" exited on a signal";
*errfmt = "\"%s\" exited on a signal";
else if (WEXITSTATUS(status) != 0)
*errnum = "\"%s\" returned non-zero status";
*errfmt = "\"%s\" returned non-zero status";
/*
* Null-terminate the result, convert newlines to spaces and
* install it in the variable.
*/
res[cc] = '\0';
cp = &res[cc];
if (cc > 0 && *--cp == '\n') {
/*
* A final newline is just stripped
*/
*cp-- = '\0';
}
while (cp >= res) {
if (*cp == '\n') {
/* 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 = ' ';
}
cp--;
}
break;
}
return res;
bad:
res = bmake_malloc(1);
*res = '\0';
return res;
return bmake_strdup("");
}
/*-
@ -1888,7 +1861,7 @@ DieHorribly(void)
*/
void
Finish(int errors)
/* number of errors encountered in Make_Make */
/* number of errors encountered in Make_Make */
{
if (dieQuietly(NULL, -1))
exit(2);
@ -1956,13 +1929,13 @@ usage(void)
{
char *p;
if ((p = strchr(progname, '[')) != NULL)
*p = '\0';
*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",
"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);
}
@ -2010,7 +1983,8 @@ char *
cached_realpath(const char *pathname, char *resolved)
{
GNode *cache;
char *rp, *cp;
const char *rp;
char *cp;
if (!pathname || !pathname[0])
return NULL;
@ -2024,7 +1998,7 @@ cached_realpath(const char *pathname, char *resolved)
Var_Set(pathname, rp, cache);
} /* else should we negative-cache? */
free(cp);
bmake_free(cp);
return rp ? resolved : NULL;
}
@ -2070,9 +2044,14 @@ void
PrintOnError(GNode *gn, const char *s)
{
static GNode *en = NULL;
char tmp[64];
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;
@ -2092,14 +2071,10 @@ PrintOnError(GNode *gn, const char *s)
Var_Delete(".ERROR_CMD", VAR_GLOBAL);
Lst_ForEach(gn->commands, addErrorCMD, gn);
}
strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
sizeof(tmp) - 1);
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
if (*cp)
printf("%s", cp);
free(cp);
}
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);
/*
@ -2115,18 +2090,17 @@ PrintOnError(GNode *gn, const char *s)
void
Main_ExportMAKEFLAGS(Boolean first)
{
static int once = 1;
char tmp[64];
static Boolean once = TRUE;
const char *expr;
char *s;
if (once != first)
return;
once = 0;
once = FALSE;
strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
sizeof(tmp));
s = Var_Subst(NULL, tmp, VAR_CMD, VARF_WANTRES);
if (s && *s) {
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
@ -2147,8 +2121,8 @@ getTmpdir(void)
* Honor $TMPDIR but only if it is valid.
* Ensure it ends with /.
*/
tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
VARF_WANTRES);
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);
@ -2235,18 +2209,12 @@ s2Boolean(const char *s, Boolean bf)
* is FALSE, otherwise TRUE.
*/
Boolean
getBoolean(const char *name, Boolean bf)
getBoolean(const char *name, Boolean fallback)
{
char tmp[64];
char *cp;
if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
cp = Var_Subst(NULL, tmp, VAR_GLOBAL, VARF_WANTRES);
if (cp) {
bf = s2Boolean(cp, bf);
free(cp);
}
}
return bf;
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;
}

View File

@ -58,17 +58,10 @@ do_link() {
${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 \
BASE_OBJECTS="arch.o buf.o compat.o cond.o dir.o enum.o for.o getopt hash.o \
lst.o make.o make_malloc.o metachar.o parse.o sigcompat.o str.o strlist.o \
suff.o targ.o trace.o var.o util.o"
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}

View File

@ -1,4 +1,4 @@
/* $NetBSD: config.h,v 1.21 2012/03/31 00:12:24 christos Exp $ */
/* $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.
@ -100,7 +100,10 @@
* 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<xx> 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
@ -108,10 +111,9 @@
* 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 defined this. Under
* that don't have this problem, you should define this. Under
* NFS you probably should not, unless you aren't exporting jobs.
*/
#define LIBSUFF ".a"
#define RECHECK
/*

View File

@ -1,4 +1,4 @@
.\" $NetBSD: make.1,v 1.282 2020/06/06 20:28:42 wiz Exp $
.\" $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.
@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
.Dd June 5, 2020
.Dd August 28, 2020
.Dt MAKE 1
.Os
.Sh NAME
@ -166,8 +166,15 @@ 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 @
@ -311,7 +318,8 @@ 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).
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
@ -412,37 +420,44 @@ or more sources.
This creates a relationship where the targets
.Dq depend
on the sources
and are usually created from them.
The exact relationship between the target and the source is determined
by the operator that separates them.
The three operators are as follows:
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 \&:
A target is considered out-of-date if its modification time is less than
those of any of its sources.
Sources for a target accumulate over dependency lines when this operator
is used.
The target is removed if
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.
is interrupted, the target is removed.
.It Ic \&!
Targets are always re-created, but not until all sources have been
examined and re-created as necessary.
Sources for a target accumulate over dependency lines when this operator
is used.
The target is removed if
.Nm
is interrupted.
The same, but the target is always re-created whether or not it is out
of date.
.It Ic \&::
If no sources are specified, the target is always re-created.
Otherwise, a target is considered out-of-date if any of its sources has
been modified more recently than the target.
Sources for a target do not accumulate over dependency lines when this
operator is used.
The target will not be removed if
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 \&? ,
@ -608,7 +623,7 @@ 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, parenthesis, or whitespace are really best avoided!
braces, parentheses, or whitespace are really best avoided!
.Pp
If the result of expanding a variable contains a dollar sign
.Pq Ql \&$
@ -1137,6 +1152,9 @@ is set to the value of
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
@ -1182,7 +1200,7 @@ 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
Select only those words that match
Selects only those words that match
.Ar pattern .
The standard shell wildcard characters
.Pf ( Ql * ,
@ -1206,11 +1224,11 @@ This is identical to
but selects all words which do not match
.Ar pattern .
.It Cm \&:O
Order every word in variable alphabetically.
Orders every word in variable alphabetically.
.It Cm \&:Or
Order every word in variable in reverse alphabetical order.
Orders every word in variable in reverse alphabetical order.
.It Cm \&:Ox
Randomize words in variable.
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 \&:=
@ -1260,7 +1278,7 @@ If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:hash
Compute a 32-bit hash of the value and encode it as hex digits.
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 ,
@ -1270,7 +1288,7 @@ If a
.Va utc
value is not provided or is 0, the current time is used.
.It Cm \&:tA
Attempt to convert variable to an absolute path using
Attempts to convert variable to an absolute path using
.Xr realpath 3 ,
if that fails, the value is unchanged.
.It Cm \&:tl
@ -1282,7 +1300,7 @@ This modifier sets the separator to the character
If
.Ar c
is omitted, then no separator is used.
The common escapes (including octal numeric codes), work as expected.
The common escapes (including octal numeric codes) work as expected.
.It Cm \&:tu
Converts variable to upper-case letters.
.It Cm \&:tW
@ -1298,21 +1316,21 @@ See also
.Sm off
.It Cm \&:S No \&/ Ar old_string No \&/ Ar new_string No \&/ Op Cm 1gW
.Sm on
Modify the first occurrence of
Modifies the first occurrence of
.Ar old_string
in the variable's value, replacing it with
in each word of the variable's value, replacing it with
.Ar new_string .
If a
.Ql g
is appended to the last slash of the pattern, all occurrences
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 slash of the pattern, only the first word
is appended to the last delimiter of the pattern, only the first occurrence
is affected.
If a
.Ql W
is appended to the last slash of the pattern,
is appended to the last delimiter of the pattern,
then the value is treated as a single word
(possibly containing embedded white space).
If
@ -1381,13 +1399,6 @@ 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).
Note that
.Ql 1
and
.Ql g
are orthogonal; the former specifies whether multiple words are
potentially affected, the latter whether multiple substitutions can
potentially occur within each affected word.
.Pp
As for the
.Cm \&:S
@ -1398,9 +1409,9 @@ and
are subjected to variable expansion before being parsed as
regular expressions.
.It Cm \&:T
Replaces each word in the variable with its last component.
Replaces each word in the variable with its last path component.
.It Cm \&:u
Remove adjacent duplicate words (like
Removes adjacent duplicate words (like
.Xr uniq 1 ) .
.Sm off
.It Cm \&:\&? Ar true_string Cm \&: Ar false_string
@ -1416,7 +1427,7 @@ 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 is any words match "42" you need to use something like:
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
@ -1460,7 +1471,7 @@ in either the
or
.Ar old_string ,
only the first instance is treated specially (as the pattern character);
all subsequent instances are treated as regular characters
all subsequent instances are treated as regular characters.
.Pp
Variable expansion occurs in the normal fashion inside both
.Ar old_string
@ -1477,11 +1488,10 @@ This is the loop expansion mechanism from the OSF Development
Environment (ODE) make.
Unlike
.Cm \&.for
loops expansion occurs at the time of
reference.
Assign
loops, expansion occurs at the time of reference.
Assigns
.Ar temp
to each word in the variable and evaluate
to each word in the variable and evaluates
.Ar string .
The ODE convention is that
.Ar temp
@ -1492,7 +1502,7 @@ For example.
However a single character variable is often more readable:
.Dl ${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'${.newline}@}
.It Cm \&:_[=var]
Save the current variable value in
Saves the current variable value in
.Ql $_
or the named
.Va var
@ -1513,7 +1523,7 @@ is used to save the result of the
modifier which is later referenced using the index values from
.Ql :range .
.It Cm \&:U Ns Ar newval
If the variable is undefined
If the variable is undefined,
.Ar newval
is the value.
If the variable is defined, the existing value is returned.
@ -1523,7 +1533,7 @@ It is handy for setting per-target CFLAGS for instance:
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
If the variable is defined,
.Ar newval
is the value.
.It Cm \&:L
@ -1652,7 +1662,7 @@ 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
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
@ -1698,7 +1708,7 @@ The possible conditionals are as follows:
The message is printed along with the name of the makefile and line number,
then
.Nm
will exit.
will exit immediately.
.It Ic .export Ar variable ...
Export the specified global variable.
If no variable list is provided, all globals are exported
@ -1887,7 +1897,7 @@ 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
variable is being compared against 0, or an empty string in the case
of a string comparison.
.Pp
When
@ -1928,7 +1938,7 @@ 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-rules
.It Aq make-lines
.It Ic \&.endfor
.El
.Pp
@ -1940,7 +1950,7 @@ On each iteration of the loop, one word is taken and assigned to each
in order, and these
.Ic variables
are substituted into the
.Ic make-rules
.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

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.c,v 1.99 2020/07/03 08:13:23 rillig Exp $ */
/* $NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: make.c,v 1.99 2020/07/03 08:13:23 rillig Exp $";
static char rcsid[] = "$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: make.c,v 1.99 2020/07/03 08:13:23 rillig Exp $");
__RCSID("$NetBSD: make.c,v 1.133 2020/08/30 14:11:42 rillig Exp $");
#endif
#endif /* not lint */
#endif
@ -116,7 +116,7 @@ __RCSID("$NetBSD: make.c,v 1.99 2020/07/03 08:13:23 rillig Exp $");
*/
#include "make.h"
#include "hash.h"
#include "enum.h"
#include "dir.h"
#include "job.h"
@ -151,6 +151,43 @@ make_abort(GNode *gn, int line)
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 --
@ -189,7 +226,7 @@ MakeTimeStamp(void *pgn, void *cgn)
{
return Make_TimeStamp((GNode *)pgn, (GNode *)cgn);
}
/*-
*-----------------------------------------------------------------------
* Make_OODate --
@ -350,7 +387,7 @@ Make_OODate(GNode *gn)
return oodate;
}
/*-
*-----------------------------------------------------------------------
* MakeAddChild --
@ -378,11 +415,11 @@ MakeAddChild(void *gnp, void *lp)
if (DEBUG(MAKE))
fprintf(debug_file, "MakeAddChild: need to examine %s%s\n",
gn->name, gn->cohort_num);
(void)Lst_EnQueue(l, gn);
Lst_Enqueue(l, gn);
}
return 0;
}
/*-
*-----------------------------------------------------------------------
* MakeFindChild --
@ -412,31 +449,18 @@ MakeFindChild(void *gnp, void *pgnp)
return 0;
}
/*-
*-----------------------------------------------------------------------
* Make_HandleUse --
* Function called by Make_Run and SuffApplyTransform on the downward
* pass to handle .USE and transformation nodes. It implements the
* .USE and transformation functionality by copying the node's commands,
* type flags and children to the parent node.
/* 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.
* 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
*
* Results:
* none
*
* Side Effects:
* Children and commands may be added to the parent and the parent's
* type may be changed.
*
*-----------------------------------------------------------------------
*/
void
Make_HandleUse(GNode *cgn, GNode *pgn)
@ -452,52 +476,42 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) {
if (cgn->type & OP_USEBEFORE) {
/*
* .USEBEFORE --
* prepend the child's commands to the parent.
*/
Lst cmds = pgn->commands;
pgn->commands = Lst_Duplicate(cgn->commands, NULL);
(void)Lst_Concat(pgn->commands, cmds, LST_CONCNEW);
Lst_Destroy(cmds, NULL);
/* .USEBEFORE */
Lst_PrependAll(pgn->commands, cgn->commands);
} else {
/*
* .USE or target has no commands --
* append the child's commands to the parent.
*/
(void)Lst_Concat(pgn->commands, cgn->commands, LST_CONCNEW);
/* .USE, or target has no commands */
Lst_AppendAll(pgn->commands, cgn->commands);
}
}
if (Lst_Open(cgn->children) == SUCCESS) {
while ((ln = Lst_Next(cgn->children)) != NULL) {
GNode *tgn, *gn = (GNode *)Lst_Datum(ln);
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(NULL, gn->uname, pgn, VARF_WANTRES);
if (gn->name && gn->uname && strcmp(gn->name, gn->uname) != 0) {
/* See if we have a target for this node. */
tgn = Targ_FindNode(gn->name, TARG_NOCREATE);
if (tgn != NULL)
gn = tgn;
}
(void)Lst_AtEnd(pgn->children, gn);
(void)Lst_AtEnd(gn->parents, pgn);
pgn->unmade += 1;
/*
* 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);
}
Lst_Close(cgn->children);
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);
}
@ -547,7 +561,7 @@ MakeHandleUse(void *cgnp, void *pgnp)
* children the parent has. This is used by Make_Run to decide
* whether to queue the parent or examine its children...
*/
if ((ln = Lst_Member(pgn->children, cgn)) != NULL) {
if ((ln = Lst_FindDatum(pgn->children, cgn)) != NULL) {
Lst_Remove(pgn->children, ln);
pgn->unmade--;
}
@ -680,8 +694,8 @@ void
Make_Update(GNode *cgn)
{
GNode *pgn; /* the parent node */
char *cname; /* the child's name */
LstNode ln; /* Element in parents and iParents lists */
const char *cname; /* the child's name */
LstNode ln; /* Element in parents and implicitParents lists */
time_t mtime = -1;
char *p1;
Lst parents;
@ -691,7 +705,7 @@ Make_Update(GNode *cgn)
checked++;
cname = Var_Value(TARGET, cgn, &p1);
free(p1);
bmake_free(p1);
if (DEBUG(MAKE))
fprintf(debug_file, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num);
@ -724,123 +738,123 @@ Make_Update(GNode *cgn)
Lst_ForEach(centurion->order_succ, MakeBuildParent, Lst_First(toBeMade));
/* Now mark all the parents as having one less unmade child */
if (Lst_Open(parents) == SUCCESS) {
while ((ln = Lst_Next(parents)) != NULL) {
pgn = (GNode *)Lst_Datum(ln);
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, "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;
}
if (pgn->order_pred
&& 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;
(void)Lst_EnQueue(toBeMade, pgn);
fprintf(debug_file, "- not needed\n");
continue;
}
Lst_Close(parents);
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.
*/
if (Lst_Open(cgn->iParents) == SUCCESS) {
char *cpref = Var_Value(PREFIX, cgn, &p1);
Lst_Open(cgn->implicitParents);
{
const char *cpref = Var_Value(PREFIX, cgn, &p1);
while ((ln = Lst_Next(cgn->iParents)) != NULL) {
pgn = (GNode *)Lst_Datum(ln);
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);
}
}
free(p1);
Lst_Close(cgn->iParents);
bmake_free(p1);
Lst_Close(cgn->implicitParents);
}
}
/*-
*-----------------------------------------------------------------------
* MakeAddAllSrc --
@ -890,7 +904,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
cgn->type |= OP_MARK;
if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) {
char *child, *allsrc;
const char *child, *allsrc;
char *p1 = NULL, *p2 = NULL;
if (cgn->type & OP_ARCHV)
@ -904,7 +918,7 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
}
if (allsrc != NULL)
Var_Append(ALLSRC, allsrc, pgn);
free(p2);
bmake_free(p2);
if (pgn->type & OP_JOIN) {
if (cgn->made == MADE) {
Var_Append(OODATE, child, pgn);
@ -930,11 +944,11 @@ MakeAddAllSrc(void *cgnp, void *pgnp)
*/
Var_Append(OODATE, child, pgn);
}
free(p1);
bmake_free(p1);
}
return 0;
}
/*-
*-----------------------------------------------------------------------
* Make_DoAllVar --
@ -976,11 +990,11 @@ Make_DoAllVar(GNode *gn)
if (gn->type & OP_JOIN) {
char *p1;
Var_Set(TARGET, Var_Value(ALLSRC, gn, &p1), gn);
free(p1);
bmake_free(p1);
}
gn->flags |= DONE_ALLSRC;
}
/*-
*-----------------------------------------------------------------------
* MakeStartJobs --
@ -1023,7 +1037,8 @@ MakeBuildChild(void *v_cn, void *toBeMade_next)
return 0;
/* If this node is on the RHS of a .ORDER, check LHSs. */
if (cn->order_pred && Lst_ForEach(cn->order_pred, MakeCheckOrder, 0)) {
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 */
@ -1035,7 +1050,7 @@ MakeBuildChild(void *v_cn, void *toBeMade_next)
cn->made = REQUESTED;
if (toBeMade_next == NULL)
Lst_AtEnd(toBeMade, cn);
Lst_Append(toBeMade, cn);
else
Lst_InsertBefore(toBeMade, toBeMade_next, cn);
@ -1072,13 +1087,13 @@ MakeStartJobs(void)
GNode *gn;
int have_token = 0;
while (!Lst_IsEmpty (toBeMade)) {
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 = (GNode *)Lst_DeQueue(toBeMade);
gn = Lst_Dequeue(toBeMade);
if (DEBUG(MAKE))
fprintf(debug_file, "Examining %s%s...\n",
gn->name, gn->cohort_num);
@ -1147,7 +1162,7 @@ MakeStartJobs(void)
return FALSE;
}
/*-
*-----------------------------------------------------------------------
* MakePrintStatus --
@ -1179,15 +1194,15 @@ MakePrintStatusOrder(void *ognp, void *gnp)
/* not waiting for this one */
return 0;
printf(" `%s%s' has .ORDER dependency against %s%s "
"(made %d, flags %x, type %x)\n",
gn->name, gn->cohort_num,
ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type);
if (DEBUG(MAKE) && debug_file != stdout)
fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s "
"(made %d, flags %x, type %x)\n",
gn->name, gn->cohort_num,
ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type);
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;
}
@ -1214,12 +1229,13 @@ MakePrintStatus(void *gnp, void *v_errors)
case REQUESTED:
case BEINGMADE:
(*errors)++;
printf("`%s%s' was not built (made %d, flags %x, type %x)!\n",
gn->name, gn->cohort_num, gn->made, gn->flags, gn->type);
if (DEBUG(MAKE) && debug_file != stdout)
fprintf(debug_file,
"`%s%s' was not built (made %d, flags %x, type %x)!\n",
gn->name, gn->cohort_num, gn->made, gn->flags, gn->type);
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;
@ -1262,7 +1278,7 @@ MakePrintStatus(void *gnp, void *v_errors)
Lst_ForEach(gn->children, MakePrintStatus, errors);
return 0;
}
/*-
*-----------------------------------------------------------------------
@ -1281,7 +1297,7 @@ Make_ExpandUse(Lst targs)
GNode *gn; /* a temporary pointer */
Lst examine; /* List of targets to examine */
examine = Lst_Duplicate(targs, NULL);
examine = Lst_Copy(targs, NULL);
/*
* Make an initial downward pass over the graph, marking nodes to be made
@ -1291,8 +1307,8 @@ Make_ExpandUse(Lst targs)
* 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 = (GNode *)Lst_DeQueue(examine);
while (!Lst_IsEmpty(examine)) {
gn = Lst_Dequeue(examine);
if (gn->flags & REMAKE)
/* We've looked at this one already */
@ -1302,13 +1318,8 @@ Make_ExpandUse(Lst targs)
fprintf(debug_file, "Make_ExpandUse: examine %s%s\n",
gn->name, gn->cohort_num);
if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts)) {
/* Append all the 'cohorts' to the list of things to examine */
Lst new;
new = Lst_Duplicate(gn->cohorts, NULL);
Lst_Concat(new, examine, LST_CONCLINK);
examine = new;
}
if (gn->type & OP_DOUBLEDEP)
Lst_PrependAll(examine, gn->cohorts);
/*
* Apply any .USE rules before looking for implicit dependencies
@ -1349,7 +1360,7 @@ Make_ExpandUse(Lst targs)
Lst_ForEach(gn->children, MakeAddChild, examine);
}
Lst_Destroy(examine, NULL);
Lst_Free(examine);
}
/*-
@ -1369,8 +1380,8 @@ link_parent(void *cnp, void *pnp)
GNode *cn = cnp;
GNode *pn = pnp;
Lst_AtEnd(pn->children, cn);
Lst_AtEnd(cn->parents, pn);
Lst_Append(pn->children, cn);
Lst_Append(cn->parents, pn);
pn->unmade++;
return 0;
}
@ -1392,9 +1403,9 @@ add_wait_dep(void *v_cn, void *v_wn)
fprintf(debug_file, ".WAIT: add dependency %s%s -> %s\n",
cn->name, cn->cohort_num, wn->name);
Lst_AtEnd(wn->children, cn);
Lst_Append(wn->children, cn);
wn->unmade++;
Lst_AtEnd(cn->parents, wn);
Lst_Append(cn->parents, wn);
return 0;
}
@ -1417,18 +1428,18 @@ Make_ProcessWait(Lst targs)
pgn->flags = REMAKE;
pgn->type = OP_PHONY | OP_DEPENDS;
/* Get it displayed in the diag dumps */
Lst_AtFront(Targ_List(), pgn);
Lst_Prepend(Targ_List(), pgn);
Lst_ForEach(targs, link_parent, pgn);
/* Start building with the 'dummy' .MAIN' node */
MakeBuildChild(pgn, NULL);
examine = Lst_Init(FALSE);
Lst_AtEnd(examine, pgn);
examine = Lst_Init();
Lst_Append(examine, pgn);
while (!Lst_IsEmpty (examine)) {
pgn = Lst_DeQueue(examine);
while (!Lst_IsEmpty(examine)) {
pgn = Lst_Dequeue(examine);
/* We only want to process each child-list once */
if (pgn->flags & DONE_WAIT)
@ -1437,30 +1448,25 @@ Make_ProcessWait(Lst targs)
if (DEBUG(MAKE))
fprintf(debug_file, "Make_ProcessWait: examine %s\n", pgn->name);
if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (pgn->cohorts)) {
/* Append all the 'cohorts' to the list of things to examine */
Lst new;
new = Lst_Duplicate(pgn->cohorts, NULL);
Lst_Concat(new, examine, LST_CONCLINK);
examine = new;
}
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 = Lst_Datum(ln);
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_AtEnd(examine, cgn);
Lst_Append(examine, cgn);
}
}
Lst_Close(pgn->children);
}
Lst_Destroy(examine, NULL);
Lst_Free(examine);
}
/*-
@ -1493,7 +1499,7 @@ Make_Run(Lst targs)
int errors; /* Number of errors the Job module reports */
/* Start trying to make the current targets... */
toBeMade = Lst_Init(FALSE);
toBeMade = Lst_Init();
Make_ExpandUse(targs);
Make_ProcessWait(targs);

View File

@ -1,4 +1,4 @@
/* $NetBSD: make.h,v 1.109 2020/07/02 15:14:38 rillig Exp $ */
/* $NetBSD: make.h,v 1.137 2020/09/02 23:42:58 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@ -77,8 +77,8 @@
* The global definitions for pmake
*/
#ifndef _MAKE_H_
#define _MAKE_H_
#ifndef MAKE_MAKE_H
#define MAKE_MAKE_H
#ifdef HAVE_CONFIG_H
# include "config.h"
@ -86,7 +86,9 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
@ -132,8 +134,34 @@
#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */
#endif
#include "sprite.h"
/*
* 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"
@ -150,163 +178,190 @@
#define POSIX_SIGNALS
#endif
/*-
* The structure for an individual graph node. Each node has several
* pieces of data associated with it.
* 1) the name of the target it describes
* 2) the location of the target file in the file system.
* 3) the type of operator used to define its sources (qv. parse.c)
* 4) whether it is involved in this invocation of make
* 5) whether the target has been remade
* 6) whether any of its children has been remade
* 7) the number of its children that are, as yet, unmade
* 8) its modification time
* 9) the modification time of its youngest child (qv. make.c)
* 10) a list of nodes for which this is a source (parents)
* 11) a list of nodes on which this depends (children)
* 12) a list of nodes that depend on this, as gleaned from the
* transformation rules (iParents)
* 13) a list of ancestor nodes, which includes parents, iParents,
* and recursive parents of parents
* 14) a list of nodes of the same name created by the :: operator
* 15) a list of nodes that must be made (if they're made) before
* this node can be, but that do not enter into the datedness of
* this node.
* 16) a list of nodes that must be made (if they're made) before
* this node or any child of this node can be, but that do not
* enter into the datedness of this node.
* 17) a list of nodes that must be made (if they're made) after
* this node is, but that do not depend on this node, in the
* normal sense.
* 18) a Lst of ``local'' variables that are specific to this target
* and this target only (qv. var.c [$@ $< $?, etc.])
* 19) a Lst of strings that are commands to be given to a shell
* to create this target.
*/
typedef struct GNode {
char *name; /* The target's name */
char *uname; /* The unexpanded name of a .USE node */
char *path; /* The full pathname of the file */
int type; /* Its type (see the OP flags, below) */
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;
int flags;
#define REMAKE 0x1 /* this target needs to be (re)made */
#define CHILDMADE 0x2 /* children of this target were made */
#define FORCE 0x4 /* children don't exist, and we pretend made */
#define DONE_WAIT 0x8 /* Set by Make_ProcessWait() */
#define DONE_ORDER 0x10 /* Build requested by .ORDER processing */
#define FROM_DEPEND 0x20 /* Node created from .depend */
#define DONE_ALLSRC 0x40 /* We do it once only */
#define CYCLE 0x1000 /* Used by MakePrintStatus */
#define DONECYCLE 0x2000 /* Used by MakePrintStatus */
#define INTERNAL 0x4000 /* Internal use only */
enum enum_made {
UNMADE, DEFERRED, REQUESTED, BEINGMADE,
MADE, UPTODATE, ERROR, ABORTED
} made; /* Set to reflect the state of processing
* on this node:
* 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).
*/
int unmade; /* The number of unmade children */
time_t mtime; /* Its modification time */
struct GNode *cmgn; /* The youngest child */
Lst iParents; /* Links to parents for which this is an
* implied source, if any */
Lst cohorts; /* Other nodes for the :: operator */
Lst parents; /* Nodes that depend on this one */
Lst children; /* Nodes on which this one depends */
Lst order_pred; /* .ORDER nodes we need made */
Lst order_succ; /* .ORDER nodes who need us */
char cohort_num[8]; /* #n for this cohort */
int unmade_cohorts;/* # of unmade instances on the
cohorts list */
struct GNode *centurion; /* Pointer to the first instance of a ::
node; only set when on a cohorts list */
unsigned int checked; /* Last time we tried to makle this node */
Hash_Table context; /* The local variables */
Lst commands; /* Creation commands */
struct _Suff *suffix; /* Suffix for the node (determined by
* Suff_FindDeps and opaque to everyone
* but the Suff module) */
const char *fname; /* filename where the GNode got defined */
int lineno; /* line number where the GNode got defined */
} GNode;
/*
* The OP_ constants are used when parsing a dependency line as a way of
/* 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 lefthand side of an operator, though it may have been on the
* righthand side...
*/
#define OP_DEPENDS 0x00000001 /* Execution of commands depends on
* kids (:) */
#define OP_FORCE 0x00000002 /* Always execute commands (!) */
#define OP_DOUBLEDEP 0x00000004 /* Execution of commands depends on kids
* per line (::) */
#define OP_OPMASK (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP)
* 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,
#define OP_OPTIONAL 0x00000008 /* Don't care if the target doesn't
* exist and can't be created */
#define OP_USE 0x00000010 /* Use associated commands for parents */
#define OP_EXEC 0x00000020 /* Target is never out of date, but always
* execute commands anyway. Its time
* doesn't matter, so it has none...sort
* of */
#define OP_IGNORE 0x00000040 /* Ignore errors when creating the node */
#define OP_PRECIOUS 0x00000080 /* Don't remove the target when
* interrupted */
#define OP_SILENT 0x00000100 /* Don't echo commands when executed */
#define OP_MAKE 0x00000200 /* 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 */
#define OP_JOIN 0x00000400 /* Target is out-of-date only if any of its
* children was out-of-date */
#define OP_MADE 0x00000800 /* Assume the children of the node have
* been already made */
#define OP_SPECIAL 0x00001000 /* Special .BEGIN, .END, .INTERRUPT */
#define OP_USEBEFORE 0x00002000 /* Like .USE, only prepend commands */
#define OP_INVISIBLE 0x00004000 /* The node is invisible to its parents.
* I.e. it doesn't show up in the parents's
* local variables. */
#define OP_NOTMAIN 0x00008000 /* The node is exempt from normal 'main
* target' processing in parse.c */
#define OP_PHONY 0x00010000 /* Not a file target; run always */
#define OP_NOPATH 0x00020000 /* Don't search for file in the path */
#define OP_WAIT 0x00040000 /* .WAIT phony node */
#define OP_NOMETA 0x00080000 /* .NOMETA do not create a .meta file */
#define OP_META 0x00100000 /* .META we _do_ want a .meta file */
#define OP_NOMETA_CMP 0x00200000 /* Do not compare commands in .meta file */
#define OP_SUBMAKE 0x00400000 /* Possibly a submake node */
/* Attributes applied by PMake */
#define OP_TRANSFORM 0x80000000 /* The node is a transformation rule */
#define OP_MEMBER 0x40000000 /* Target is a member of an archive */
#define OP_LIB 0x20000000 /* Target is a library */
#define OP_ARCHV 0x10000000 /* Target is an archive construct */
#define OP_HAS_COMMANDS 0x08000000 /* Target has all the commands it should.
* Used when parsing to catch multiple
* commands for a target */
#define OP_SAVE_CMDS 0x04000000 /* Saving commands on .END (Compat) */
#define OP_DEPS_FOUND 0x02000000 /* Already processed by Suff_FindDeps */
#define OP_MARK 0x01000000 /* Node found while expanding .ALLSRC */
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)
/*
@ -329,18 +384,6 @@ typedef struct GNode {
#define TARG_CREATE 0x01 /* create node if not found */
#define TARG_NOHASH 0x02 /* don't look in/add to hash table */
/*
* These constants are all used by the Str_Concat function to decide how the
* final string should look. If STR_ADDSPACE is given, a space will be
* placed between the two strings. If STR_ADDSLASH is given, a '/' will
* be used instead of a space. If neither is given, no intervening characters
* will be placed between the two strings in the final output. If the
* STR_DOFREE bit is set, the two input strings will be freed before
* Str_Concat returns.
*/
#define STR_ADDSPACE 0x01 /* add a space when Str_Concat'ing */
#define STR_ADDSLASH 0x02 /* add a slash when Str_Concat'ing */
/*
* Error levels for parsing. PARSE_FATAL means the process cannot continue
* once the makefile has been parsed. PARSE_WARNING means it can. Passed
@ -353,9 +396,11 @@ typedef struct GNode {
/*
* Values returned by Cond_Eval.
*/
#define COND_PARSE 0 /* Parse the next lines */
#define COND_SKIP 1 /* Skip the next lines */
#define COND_INVALID 2 /* Not a conditional statement */
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.
@ -403,7 +448,6 @@ extern Boolean doing_depend; /* TRUE if processing .depend */
extern Boolean checkEnvFirst; /* TRUE if environment should be searched for
* variables before the global context */
extern Boolean jobServer; /* a jobServer already exists */
extern Boolean parseWarnFatal; /* TRUE if makefile parsing warnings are
* treated as errors */
@ -420,7 +464,6 @@ extern GNode *VAR_INTERNAL; /* Variables defined internally by make
extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
* in the Makefile itself */
extern GNode *VAR_CMD; /* Variables defined on the command line */
extern GNode *VAR_FOR; /* Iteration variables */
extern char var_Error[]; /* Value returned by Var_Parse when an error
* is encountered. It actually points to
* an empty string, so naive callers needn't
@ -439,6 +482,8 @@ extern char *progname; /* The program name */
extern char *makeDependfile; /* .depend */
extern char **savedEnv; /* if we replaced environ this will be non-NULL */
extern int makelevel;
/*
* We cannot vfork() in a child of vfork().
* Most systems do not enforce this but some do.
@ -464,7 +509,7 @@ extern pid_t myPid;
* There is one bit per module. It is up to the module what debug
* information to print.
*/
extern FILE *debug_file; /* Output written here - default stdout */
extern FILE *debug_file; /* Output is written here - default stderr */
extern int debug;
#define DEBUG_ARCH 0x00001
#define DEBUG_COND 0x00002
@ -481,12 +526,15 @@ extern int debug;
#define DEBUG_ERROR 0x01000
#define DEBUG_LOUD 0x02000
#define DEBUG_META 0x04000
#define DEBUG_HASH 0x08000
#define DEBUG_GRAPH3 0x10000
#define DEBUG_SCRIPT 0x20000
#define DEBUG_PARSE 0x40000
#define DEBUG_CWD 0x80000
#define DEBUG_LINT 0x100000
#define CONCAT(a,b) a##b
#define DEBUG(module) (debug & CONCAT(DEBUG_,module))
@ -501,16 +549,13 @@ void Make_HandleUse(GNode *, GNode *);
void Make_Update(GNode *);
void Make_DoAllVar(GNode *);
Boolean Make_Run(Lst);
char * Check_Cwd_Cmd(const char *);
void Check_Cwd(const char **);
int dieQuietly(GNode *, int);
void PrintOnError(GNode *, const char *);
void Main_ExportMAKEFLAGS(Boolean);
Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
int mkTempFile(const char *, char **);
int str2Lst_Append(Lst, char *, const char *);
int cached_lstat(const char *, void *);
int cached_stat(const char *, void *);
void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
#ifdef __GNUC__
#define UNCONST(ptr) ({ \
@ -524,10 +569,10 @@ int cached_stat(const char *, void *);
#endif
#ifndef MIN
#define MIN(a, b) ((a < b) ? a : b)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) ((a > b) ? a : b)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
@ -547,4 +592,4 @@ int cached_stat(const char *, void *);
#define KILLPG(pid, sig) killpg((pid), (sig))
#endif
#endif /* _MAKE_H_ */
#endif /* MAKE_MAKE_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: make_malloc.c,v 1.12 2020/07/03 08:02:55 rillig Exp $ */
/* $NetBSD: make_malloc.c,v 1.18 2020/09/02 06:10:44 rillig Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -28,7 +28,7 @@
#ifdef MAKE_NATIVE
#include <sys/cdefs.h>
__RCSID("$NetBSD: make_malloc.c,v 1.12 2020/07/03 08:02:55 rillig Exp $");
__RCSID("$NetBSD: make_malloc.c,v 1.18 2020/09/02 06:10:44 rillig Exp $");
#endif
#include <stdio.h>
@ -41,10 +41,7 @@ __RCSID("$NetBSD: make_malloc.c,v 1.12 2020/07/03 08:02:55 rillig Exp $");
#ifndef USE_EMALLOC
static MAKE_ATTR_DEAD void enomem(void);
/*
* enomem --
* die when out of memory.
*/
/* die when out of memory. */
static MAKE_ATTR_DEAD void
enomem(void)
{
@ -52,10 +49,7 @@ enomem(void)
exit(2);
}
/*
* bmake_malloc --
* malloc, but die on error.
*/
/* malloc, but die on error. */
void *
bmake_malloc(size_t len)
{
@ -66,10 +60,7 @@ bmake_malloc(size_t len)
return p;
}
/*
* bmake_strdup --
* strdup, but die on error.
*/
/* strdup, but die on error. */
char *
bmake_strdup(const char *str)
{
@ -82,33 +73,17 @@ bmake_strdup(const char *str)
return memcpy(p, str, len);
}
/*
* bmake_strndup --
* strndup, but die on error.
*/
/* Allocate a string starting from str with exactly len characters. */
char *
bmake_strndup(const char *str, size_t max_len)
bmake_strldup(const char *str, size_t len)
{
size_t len;
char *p;
if (str == NULL)
return NULL;
len = strlen(str);
if (len > max_len)
len = max_len;
p = bmake_malloc(len + 1);
char *p = bmake_malloc(len + 1);
memcpy(p, str, len);
p[len] = '\0';
return p;
}
/*
* bmake_realloc --
* realloc, but die on error.
*/
/* realloc, but die on error. */
void *
bmake_realloc(void *ptr, size_t size)
{
@ -117,3 +92,10 @@ bmake_realloc(void *ptr, size_t size)
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));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: make_malloc.h,v 1.4 2009/01/24 14:43:29 dsl Exp $ */
/* $NetBSD: make_malloc.h,v 1.10 2020/08/29 16:47:45 rillig Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -30,12 +30,25 @@
void *bmake_malloc(size_t);
void *bmake_realloc(void *, size_t);
char *bmake_strdup(const char *);
char *bmake_strndup(const char *, size_t);
char *bmake_strldup(const char *, size_t);
#else
#include <util.h>
#define bmake_malloc(x) emalloc(x)
#define bmake_realloc(x,y) erealloc(x,y)
#define bmake_strdup(x) estrdup(x)
#define bmake_strndup(x,y) estrndup(x,y)
#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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: meta.c,v 1.86 2020/07/11 00:39:53 sjg Exp $ */
/* $NetBSD: meta.c,v 1.113 2020/09/02 04:08:54 rillig Exp $ */
/*
* Implement 'meta' mode.
@ -47,6 +47,7 @@ char * dirname(char *);
#endif
#include "make.h"
#include "dir.h"
#include "job.h"
#ifdef USE_FILEMON
@ -318,7 +319,7 @@ meta_name(char *mname, size_t mnamelen,
static int
is_submake(void *cmdp, void *gnp)
{
static char *p_make = NULL;
static const char *p_make = NULL;
static int p_len;
char *cmd = cmdp;
GNode *gn = gnp;
@ -333,7 +334,7 @@ is_submake(void *cmdp, void *gnp)
}
cp = strchr(cmd, '$');
if ((cp)) {
mp = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
mp = Var_Subst(cmd, gn, VARE_WANTRES);
cmd = mp;
}
cp2 = strstr(cmd, p_make);
@ -372,13 +373,13 @@ printCMD(void *cmdp, void *mfpp)
{
meta_file_t *mfp = mfpp;
char *cmd = cmdp;
char *cp = NULL;
char *cmd_freeIt = NULL;
if (strchr(cmd, '$')) {
cmd = cp = Var_Subst(NULL, cmd, mfp->gn, VARF_WANTRES);
cmd = cmd_freeIt = Var_Subst(cmd, mfp->gn, VARE_WANTRES);
}
fprintf(mfp->fp, "CMD %s\n", cmd);
free(cp);
free(cmd_freeIt);
return 0;
}
@ -403,7 +404,7 @@ static Boolean
meta_needed(GNode *gn, const char *dname,
char *objdir, int verbose)
{
struct stat fs;
struct make_stat mst;
if (verbose)
verbose = DEBUG(META);
@ -437,7 +438,7 @@ meta_needed(GNode *gn, const char *dname,
}
/* The object directory may not exist. Check it.. */
if (cached_stat(dname, &fs) != 0) {
if (cached_stat(dname, &mst) != 0) {
if (verbose)
fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
gn->name);
@ -488,7 +489,7 @@ meta_create(BuildMon *pbm, GNode *gn)
char *mp;
/* Describe the target we are building */
mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, VARF_WANTRES);
mp = Var_Subst("${" MAKE_META_PREFIX "}", gn, VARE_WANTRES);
if (*mp)
fprintf(stdout, "%s\n", mp);
free(mp);
@ -546,7 +547,7 @@ meta_create(BuildMon *pbm, GNode *gn)
}
out:
for (i--; i >= 0; i--) {
free(p[i]);
bmake_free(p[i]);
}
return mf.fp;
@ -629,24 +630,19 @@ meta_mode_init(const char *make_mode)
/*
* We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
*/
metaBailiwick = Lst_Init(FALSE);
metaBailiwickStr = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}",
VAR_GLOBAL, VARF_WANTRES);
if (metaBailiwickStr) {
str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL);
}
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(FALSE);
metaIgnorePaths = Lst_Init();
Var_Append(MAKE_META_IGNORE_PATHS,
"/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
metaIgnorePathsStr = Var_Subst(NULL,
"${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
VARF_WANTRES);
if (metaIgnorePathsStr) {
str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL);
}
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}
@ -654,12 +650,12 @@ meta_mode_init(const char *make_mode)
cp = NULL;
if (Var_Value(MAKE_META_IGNORE_PATTERNS, VAR_GLOBAL, &cp)) {
metaIgnorePatterns = TRUE;
free(cp);
bmake_free(cp);
}
cp = NULL;
if (Var_Value(MAKE_META_IGNORE_FILTER, VAR_GLOBAL, &cp)) {
metaIgnoreFilter = TRUE;
free(cp);
bmake_free(cp);
}
}
@ -822,8 +818,8 @@ meta_job_output(Job *job, char *cp, const char *nl)
if (!meta_prefix) {
char *cp2;
meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
VAR_GLOBAL, VARF_WANTRES);
meta_prefix = Var_Subst("${" MAKE_META_PREFIX "}",
VAR_GLOBAL, VARE_WANTRES);
if ((cp2 = strchr(meta_prefix, '$')))
meta_prefix_len = cp2 - meta_prefix;
else
@ -894,9 +890,11 @@ meta_job_finish(Job *job)
void
meta_finish(void)
{
Lst_Destroy(metaBailiwick, NULL);
if (metaBailiwick != NULL)
Lst_Free(metaBailiwick);
free(metaBailiwickStr);
Lst_Destroy(metaIgnorePaths, NULL);
if (metaIgnorePaths != NULL)
Lst_Free(metaIgnorePaths);
free(metaIgnorePathsStr);
}
@ -958,39 +956,23 @@ prefix_match(void *p, void *q)
return strncmp(path, prefix, n) == 0;
}
/*
* looking for exact or prefix/ match to
* Lst_Find wants 0 to stop search
*/
static int
/* See if the path equals prefix or starts with "prefix/". */
static Boolean
path_match(const void *p, const void *q)
{
const char *prefix = q;
const char *path = p;
const char *prefix = q;
size_t n = strlen(prefix);
int rc;
if ((rc = strncmp(path, prefix, n)) == 0) {
switch (path[n]) {
case '\0':
case '/':
break;
default:
rc = 1;
break;
}
}
return rc;
if (strncmp(path, prefix, n) != 0)
return FALSE;
return path[n] == '\0' || path[n] == '/';
}
/* Lst_Find wants 0 to stop search */
static int
static Boolean
string_match(const void *p, const void *q)
{
const char *p1 = p;
const char *p2 = q;
return strcmp(p1, p2);
return strcmp(p, q) == 0;
}
@ -1015,12 +997,12 @@ meta_ignore(GNode *gn, const char *p)
}
if (metaIgnorePatterns) {
const char *expr;
char *pm;
Var_Set(".p.", p, gn);
pm = Var_Subst(NULL,
"${" MAKE_META_IGNORE_PATTERNS ":@m@${.p.:M$m}@}",
gn, VARF_WANTRES);
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))
@ -1040,7 +1022,7 @@ meta_ignore(GNode *gn, const char *p)
snprintf(fname, sizeof(fname),
"${%s:L:${%s:ts:}}",
p, MAKE_META_IGNORE_FILTER);
fm = Var_Subst(NULL, fname, gn, VARF_WANTRES);
fm = Var_Subst(fname, gn, VARE_WANTRES);
if (*fm == '\0') {
#ifdef DEBUG_META_MODE
if (DEBUG(META))
@ -1122,7 +1104,7 @@ meta_oodate(GNode *gn, Boolean oodate)
goto oodate_out;
dname = fname3;
missingFiles = Lst_Init(FALSE);
missingFiles = Lst_Init();
/*
* We need to check if the target is out-of-date. This includes
@ -1147,7 +1129,7 @@ meta_oodate(GNode *gn, Boolean oodate)
int pid;
int x;
LstNode ln;
struct stat fs;
struct make_stat mst;
if (!buf) {
bufsz = 8 * BUFSIZ;
@ -1240,7 +1222,7 @@ meta_oodate(GNode *gn, Boolean oodate)
CHECK_VALID_META(p);
pid = atoi(p);
if (pid > 0 && pid != lastpid) {
char *ldir;
const char *ldir;
char *tp;
if (lastpid > 0) {
@ -1254,12 +1236,12 @@ meta_oodate(GNode *gn, Boolean oodate)
ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
if (ldir) {
strlcpy(latestdir, ldir, sizeof(latestdir));
free(tp);
bmake_free(tp);
}
ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp);
if (ldir) {
strlcpy(lcwd, ldir, sizeof(lcwd));
free(tp);
bmake_free(tp);
}
}
/* Skip past the pid. */
@ -1337,15 +1319,16 @@ meta_oodate(GNode *gn, Boolean oodate)
case 'D': /* unlink */
if (*p == '/' && !Lst_IsEmpty(missingFiles)) {
/* remove any missingFiles entries that match p */
if ((ln = Lst_Find(missingFiles, p,
path_match)) != NULL) {
ln = Lst_Find(missingFiles, path_match, p);
if (ln != NULL) {
LstNode nln;
char *tp;
do {
nln = Lst_FindFrom(missingFiles, Lst_Succ(ln),
p, path_match);
tp = Lst_Datum(ln);
nln = Lst_FindFrom(missingFiles,
LstNode_Next(ln),
path_match, p);
tp = LstNode_Datum(ln);
Lst_Remove(missingFiles, ln);
free(tp);
} while ((ln = nln) != NULL);
@ -1411,11 +1394,11 @@ meta_oodate(GNode *gn, Boolean oodate)
if ((strstr("tmp", p)))
break;
if ((link_src != NULL && cached_lstat(p, &fs) < 0) ||
(link_src == NULL && cached_stat(p, &fs) < 0)) {
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, p, string_match) == NULL)
Lst_AtEnd(missingFiles, bmake_strdup(p));
if (Lst_Find(missingFiles, string_match, p) == NULL)
Lst_Append(missingFiles, bmake_strdup(p));
}
}
break;
@ -1475,7 +1458,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (DEBUG(META))
fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp);
#endif
if (cached_stat(*sdp, &fs) == 0) {
if (cached_stat(*sdp, &mst) == 0) {
found = 1;
p = *sdp;
}
@ -1485,12 +1468,12 @@ meta_oodate(GNode *gn, Boolean oodate)
if (DEBUG(META))
fprintf(debug_file, "%s: %d: found: %s\n", fname, lineno, p);
#endif
if (!S_ISDIR(fs.st_mode) &&
fs.st_mtime > gn->mtime) {
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(fs.st_mode)) {
} else if (S_ISDIR(mst.mst_mode)) {
/* Update the latest directory. */
cached_realpath(p, latestdir);
}
@ -1500,8 +1483,8 @@ meta_oodate(GNode *gn, Boolean oodate)
* A referenced file outside of CWD is missing.
* We cannot catch every eventuality here...
*/
if (Lst_Find(missingFiles, p, string_match) == NULL)
Lst_AtEnd(missingFiles, bmake_strdup(p));
if (Lst_Find(missingFiles, string_match, p) == NULL)
Lst_Append(missingFiles, bmake_strdup(p));
}
}
if (buf[0] == 'E') {
@ -1524,7 +1507,7 @@ meta_oodate(GNode *gn, Boolean oodate)
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 = (char *)Lst_Datum(ln);
char *cmd = LstNode_Datum(ln);
Boolean hasOODATE = FALSE;
if (strstr(cmd, "$?"))
@ -1539,7 +1522,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (DEBUG(META))
fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
}
cmd = Var_Subst(NULL, cmd, gn, VARF_WANTRES|VARF_UNDEFERR);
cmd = Var_Subst(cmd, gn, VARE_WANTRES|VARE_UNDEFERR);
if ((cp = strchr(cmd, '\n'))) {
int n;
@ -1576,7 +1559,7 @@ meta_oodate(GNode *gn, Boolean oodate)
oodate = TRUE;
}
free(cmd);
ln = Lst_Succ(ln);
ln = LstNode_Next(ln);
}
} else if (strcmp(buf, "CWD") == 0) {
/*
@ -1601,7 +1584,7 @@ meta_oodate(GNode *gn, Boolean oodate)
if (!Lst_IsEmpty(missingFiles)) {
if (DEBUG(META))
fprintf(debug_file, "%s: missing files: %s...\n",
fname, (char *)Lst_Datum(Lst_First(missingFiles)));
fname, (char *)LstNode_Datum(Lst_First(missingFiles)));
oodate = TRUE;
}
if (!oodate && !have_filemon && filemonMissing) {
@ -1628,7 +1611,7 @@ meta_oodate(GNode *gn, Boolean oodate)
}
}
Lst_Destroy(missingFiles, (FreeProc *)free);
Lst_Destroy(missingFiles, free);
if (oodate && needOODATE) {
/*
@ -1638,12 +1621,12 @@ meta_oodate(GNode *gn, Boolean oodate)
*/
Var_Delete(OODATE, gn);
Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn);
free(cp);
bmake_free(cp);
}
oodate_out:
for (i--; i >= 0; i--) {
free(pa[i]);
bmake_free(pa[i]);
}
return oodate;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $ */
/* $NetBSD: metachar.c,v 1.6 2020/08/03 20:43:41 rillig Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#endif
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $");
__RCSID("$NetBSD: metachar.c,v 1.6 2020/08/03 20:43:41 rillig Exp $");
#endif
#include "metachar.h"
@ -52,37 +52,37 @@ __RCSID("$NetBSD: metachar.c,v 1.5 2015/06/19 08:03:35 mlelstv Exp $");
*/
unsigned char _metachar[128] = {
// nul soh stx etx eot enq ack bel
/* nul soh stx etx eot enq ack bel */
1, 0, 0, 0, 0, 0, 0, 0,
// bs ht nl vt np cr so si
/* bs ht nl vt np cr so si */
0, 0, 1, 0, 0, 0, 0, 0,
// dle dc1 dc2 dc3 dc4 nak syn etb
/* dle dc1 dc2 dc3 dc4 nak syn etb */
0, 0, 0, 0, 0, 0, 0, 0,
// can em sub esc fs gs rs us
/* can em sub esc fs gs rs us */
0, 0, 0, 0, 0, 0, 0, 0,
// sp ! " # $ % & '
/* 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 1 2 3 4 5 6 7 */
0, 0, 0, 0, 0, 0, 0, 0,
// 8 9 : ; < = > ?
/* 8 9 : ; < = > ? */
0, 0, 0, 1, 1, 0, 1, 1,
// @ A B C D E F G
/* @ A B C D E F G */
0, 0, 0, 0, 0, 0, 0, 0,
// H I J K L M N O
/* H I J K L M N O */
0, 0, 0, 0, 0, 0, 0, 0,
// P Q R S T U V W
/* P Q R S T U V W */
0, 0, 0, 0, 0, 0, 0, 0,
// X Y Z [ \ ] ^ _
/* X Y Z [ \ ] ^ _ */
0, 0, 0, 1, 1, 1, 1, 0,
// ` a b c d e f g
/* ` a b c d e f g */
1, 0, 0, 0, 0, 0, 0, 0,
// h i j k l m n o
/* h i j k l m n o */
0, 0, 0, 0, 0, 0, 0, 0,
// p q r s t u v w
/* p q r s t u v w */
0, 0, 0, 0, 0, 0, 0, 0,
// x y z { | } ~ del
/* x y z { | } ~ del */
0, 0, 0, 1, 1, 1, 1, 0,
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: metachar.h,v 1.4 2015/06/21 20:26:02 christos Exp $ */
/* $NetBSD: metachar.h,v 1.7 2020/08/25 17:37:09 rillig Exp $ */
/*-
* Copyright (c) 2015 The NetBSD Foundation, Inc.
@ -28,25 +28,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _METACHAR_H
#define _METACHAR_H
#ifndef MAKE_METACHAR_H
#define MAKE_METACHAR_H
#include <ctype.h>
#include "make.h"
extern unsigned char _metachar[];
#define ismeta(c) _metachar[(c) & 0x7f]
static inline int
hasmeta(const char *cmd)
{
while (!ismeta(*cmd))
cmd++;
return *cmd != '\0';
}
static inline int
static inline int MAKE_ATTR_UNUSED
needshell(const char *cmd, int white)
{
while (!ismeta(*cmd) && *cmd != ':' && *cmd != '=') {
@ -58,4 +49,4 @@ needshell(const char *cmd, int white)
return *cmd != '\0';
}
#endif /* _METACHAR_H */
#endif /* MAKE_METACHAR_H */

View File

@ -1,3 +1,106 @@
2020-08-26 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* dirdeps-targets.mk: include Makefile.dirdeps.options
* dirdeps.mk: use _TARGETS if defined for DIRDEPS_CACHE
2020-08-09 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* host-target.mk: Darwin use MACHINE for HOST_ARCH too
* dirdeps-options.mk: improve debug output
2020-07-22 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* Get rid of BUILD_AT_LEVEL0, MK_DIRDEPS_BUILD makes more sense.
2020-07-16 Simon J Gerraty <sjg@beast.crufty.net>
* dirdeps.mk (DIRDEP_LOADAVG_REPORT): make it easy to record
load averages at intervals during build.
2020-07-15 Simon J Gerraty <sjg@beast.crufty.net>
* 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 <sjg@beast.crufty.net>
* dirdeps.mk: further optimize dirdeps.cache
generate a DIRDEPS.${.TARGET} list for other purposes
and improve the layout.
2020-07-10 Simon J Gerraty <sjg@beast.crufty.net>
* dirdeps.mk: optimize content of dirdeps.cache
@ -124,7 +227,7 @@
* install-mk (MK_VERSION): 20180919
* dirdeps-options.mk: .undef cannot handle var that expands to
more than one var.
more than one var.
2018-07-08 Simon J Gerraty <sjg@beast.crufty.net>
@ -309,8 +412,8 @@
2016-12-12 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20161212
* meta2deps.py: set pid_cwd[pid] when we process 'C'hdir,
* meta2deps.py: set pid_cwd[pid] when we process 'C'hdir,
rather than when we detect pid change.
2016-12-07 Simon J. Gerraty <sjg@bad.crufty.net>
@ -322,7 +425,7 @@
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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20161126
@ -374,18 +477,18 @@
2016-08-13 Simon J. Gerraty <sjg@bad.crufty.net>
* meta.sys.mk (.MAKE.META.IGNORE_PATHS):
* meta.sys.mk (.MAKE.META.IGNORE_PATHS):
in meta mode we can ignore the mtime of makefiles
2016-08-02 Simon J. Gerraty <sjg@bad.crufty.net>
* 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
@ -408,7 +511,7 @@
* install-mk (MK_VERSION): 20160530
* meta.stage.mk: we assume ${CLEANFILES} gets .NOPATH
make it so.
2016-05-12 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20160512
@ -418,7 +521,7 @@
skip INCLUDES_* for staged libs unless SRC_* defined.
* own.mk: add INCLUDEDIR
2016-04-18 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk: when doing -f dirdeps.mk if target suppies no
@ -428,9 +531,9 @@
2016-04-07 Simon J. Gerraty <sjg@bad.crufty.net>
* meta.autodep.mk: issue a warning if UPDATE_DEPENDFILE=NO due to
NO_FILEMON_COOKIE
NO_FILEMON_COOKIE
* dirdeps.mk: move the logic that allows for
* dirdeps.mk: move the logic that allows for
make -f dirdeps.mk some/dir.${TARGET_SPEC}
inside the check for !target(_DIRDEP_USE)
@ -438,15 +541,15 @@
* 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):
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20160401
* meta2deps.py: fix old print statement when debugging.
* gendirdeps.mk: META2DEPS_CMD append M2D_EXCLUDES with -X
@ -455,12 +558,12 @@
2016-03-22 Simon J. Gerraty <sjg@bad.crufty.net>
* 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 <sjg@bad.crufty.net>
@ -469,9 +572,9 @@
* 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.
well as outside it.
2016-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
@ -509,17 +612,17 @@
we cannot use the '$$' trick, but .export-literal does the job
we need.
* auto.dep.mk: make use .dinclude if we can.
2016-02-05 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk:
* 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
These will be built normally but the current
DEP_RELDIR will not depend on then (to avoid cycles).
This makes it easy to hook things like unit-tests into build.
2016-01-21 Simon J. Gerraty <sjg@bad.crufty.net>
@ -541,7 +644,7 @@
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 <sjg@bad.crufty.net>
@ -560,8 +663,8 @@
2015-10-20 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20151020
* dirdeps.mk: Add logic for
* dirdeps.mk: Add logic for
make -f dirdeps.mk some/dir.${TARGET_SPEC}
2015-10-14 Simon J. Gerraty <sjg@bad.crufty.net>
@ -587,16 +690,16 @@
2015-06-15 Simon J. Gerraty <sjg@bad.crufty.net>
* 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:
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.
@ -605,11 +708,11 @@
2015-06-06 Simon J. Gerraty <sjg@bad.crufty.net>
* 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 <sjg@bad.crufty.net>
@ -626,19 +729,19 @@
* 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.
Also skip staging at level 0.
2015-04-30 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20150430
* dirdeps.mk: fix _count_dirdeps for non-cache case.
2015-04-16 Simon J. Gerraty <sjg@bad.crufty.net>
* 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
@ -646,21 +749,21 @@
2015-04-01 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20150401
* meta2deps.sh: support @list
* meta2deps.py: updates from Juniper
o add EXCLUDES
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 <sjg@bad.crufty.net>
* 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.
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,
@ -669,15 +772,15 @@
2014-11-18 Simon J. Gerraty <sjg@bad.crufty.net>
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20141111
@ -695,24 +798,24 @@
for GENDIRDEPS_FILTER to avoid surprises.
2014-10-10 Simon J. Gerraty <sjg@bad.crufty.net>
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20140911
* dirdeps.mk: add bootstrap target to simplify adding support for
new MACHINE.
2014-09-01 Simon J. Gerraty <sjg@bad.crufty.net>
* gendirdeps.mk: Add handling of GENDIRDEPS_FILTER_DIR_VARS and
@ -722,7 +825,7 @@
2014-08-28 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20140828
* cython.mk: capture logic for building python extension modules
with Cython.
@ -735,8 +838,8 @@
* install-mk (MK_VERSION): 20140801
* dep.mk: use explicit MKDEP_MK rather than overload MKDEP to
identify the autodep.mk variant.
identify the autodep.mk variant.
* sys.dependfile.mk: delete .MAKE.DEPENDFILE if its
initial value does not match .MAKE.DEPENDFILE_PREFIX
@ -774,7 +877,7 @@
build).
* dirdeps.mk (__depdirs): ensure // don't sneak in
* gendirdeps.mk (DIRDEPS): ensure // don't sneak in
@ -794,7 +897,7 @@
2014-02-09 Simon J. Gerraty <sjg@bad.crufty.net>
* options.mk: cleanup and simplify semanitcs
* 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.
@ -815,7 +918,7 @@
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)
Makefile.depend)
Add some more debug info.
2013-09-04 Simon J. Gerraty <sjg@bad.crufty.net>
@ -828,7 +931,7 @@
* install-mk (MK_VERSION): 20130801
* libs.mk: update to match progs.mk
2013-07-26 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20130726
@ -837,13 +940,13 @@
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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20130716
* own.mk: add GPROG as an option
* prog.mk: honor MK_GPROF==yes
2013-05-10 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): 20130505
@ -878,7 +981,7 @@
* 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 <sjg@bad.crufty.net>
* gendirdeps.mk: revert the dance around .MAKE.DEPENDFILE_DEFAULT
@ -893,7 +996,7 @@
* 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 <sjg@bad.crufty.net>
@ -909,7 +1012,7 @@
2013-03-07 Simon J. Gerraty <sjg@bad.crufty.net>
* sys.dependfile.mk (.MAKE.DEPENDFILE_DEFAULT):
* 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
@ -926,12 +1029,12 @@
2013-02-10 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20130210
* import latest dirdeps.mk, gendirdeps.mk and meta2deps.py
from Juniper.
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20130123
@ -976,13 +1079,13 @@
* 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 <sjg@bad.crufty.net>
* 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 <sjg@bad.crufty.net>
* meta.stage.mk (STAGE_DIR_FILTER): track dirs we stage to in
@ -1004,11 +1107,11 @@
* install-mk (MK_VERSION): bump version to 20120711
* dep.mk: add explicit dependencies on SRCS after applying
SRCS_DEP_FILTER
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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20120626
@ -1020,14 +1123,14 @@
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20120420
* add sys.dependfile.mk so we can experiment with
.MAKE.DEPENDFILE_PREFERENCE
.MAKE.DEPENDFILE_PREFERENCE
* meta.autodep.mk: _DEPENDFILE is precious!
2012-03-15 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20120315
@ -1068,37 +1171,37 @@
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 <sjg@bad.crufty.net>
* install-new.mk separate the cmp and copy logic to its own function.
2011-10-28 Simon J. Gerraty <sjg@bad.crufty.net>
* 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.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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20111010
o minor tweak to *dirdeps.mk from Juniper sjg@
2011-10-01 Simon J. Gerraty <sjg@bad.crufty.net>
* 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
cross-building
* autoconf.mk: add autoconf-input as a hook for regenerating
AUTOCONF_INPUTS (configure).
2011-08-24 Simon J. Gerraty <sjg@bad.crufty.net>
* meta.autodep.mk: if we do not have OBJS, .depend isn't a useful
trigger for updating Makefile.depend*
trigger for updating Makefile.depend*
2011-08-08 Simon J. Gerraty <sjg@bad.crufty.net>
@ -1155,7 +1258,7 @@
2011-04-03 Simon J. Gerraty <sjg@bad.crufty.net>
* rst2htm.mk: convert rst to s5 (slides) or plain html depending
on target name.
on target name.
2011-03-30 Simon J. Gerraty <sjg@bad.crufty.net>
@ -1167,16 +1270,16 @@
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 <sjg@bad.crufty.net>
* meta.stage.mk: add stage_symlinks and leverage StageLinks for
stage_libs
stage_libs
2011-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
* dirdeps.mk: correct value for _depdir_files depends on
.MAKE.DEPENDFILE
.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
@ -1216,7 +1319,7 @@
2010-09-24 Simon J. Gerraty <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20100919
include dirdeps.mk et al from Juniper Networks,
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
@ -1282,7 +1385,7 @@
* 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 <sjg@bad.crufty.net>
* obj.mk: add objwarn to keep freebsd makefiles happy
@ -1294,7 +1397,7 @@
* 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 <sjg@bad.crufty.net>
* install-mk (MK_VERSION): bump version to 20100404
@ -1335,7 +1438,7 @@
* sys.mk,libnames.mk add .-include <local.*>
this allows local customization without the need to edit the
distributed files.
distributed files.
2009-12-14 Simon J. Gerraty <sjg@void.crufty.net>
@ -1361,7 +1464,7 @@
2009-11-17 Simon J. Gerraty <sjg@void.crufty.net>
* install-mk (MK_VERSION): bump version
* host-target.mk: only export the expensive stuff
* 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!
@ -1411,7 +1514,7 @@
* install-mk (MK_VERSION): bump version
* general cleanup
* dpadd.mk introduce DPMAGIC_LIBS_*
* dpadd.mk introduce DPMAGIC_LIBS_*
2007-04-30 Simon J. Gerraty <sjg@void.crufty.net>
@ -1453,10 +1556,10 @@
* 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.
specific warnings.
* For .cc sources, turn off warnings that g++ vomits on.
2006-11-08 Simon J. Gerraty <sjg@void.crufty.net>
@ -1483,11 +1586,11 @@
2006-03-01 Simon J. Gerraty <sjg@void.crufty.net>
* install-mk (MK_VERSION): bump version to 20060301
* autodep.mk (.depend):
* 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 <sjg@void.crufty.net>
* install-mk (MK_VERSION): bump version to 20051104
@ -1512,7 +1615,7 @@
2004-02-15 Simon J. Gerraty <sjg@void.crufty.net>
* own.mk: don't use NetBSD's _SRC_TOP_ it can
cause confusion. Also don't take just 'mk' as a
cause confusion. Also don't take just 'mk' as a
srctop indicator.
2004-02-14 Simon J. Gerraty <sjg@void.crufty.net>
@ -1538,7 +1641,7 @@
* 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 <sjg@void.crufty.net>
* install-mk (MK_VERSION): 20030928
@ -1554,8 +1657,8 @@
2003-07-31 Simon J. Gerraty <sjg@void.crufty.net>
* install-mk: add ability to use cp -f when updating
destination .mk files. Also now possible to play games with
* 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.
@ -1575,4 +1678,4 @@
* install-mk: Allow FORCE_SYS_MK to come from env

View File

@ -61,6 +61,7 @@ warnings.mk
whats.mk
yacc.mk
dirdeps.mk
dirdeps-cache-update.mk
dirdeps-options.mk
dirdeps-targets.mk
gendirdeps.mk

View File

@ -1,10 +1,10 @@
# $Id: README,v 1.1 1997/03/11 07:27:15 sjg Exp $
# $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.
apply.
# $NetBSD: bsd.README,v 1.18 1997/01/13 00:54:23 mark Exp $
# @(#)bsd.README 5.1 (Berkeley) 5/11/90
@ -347,9 +347,9 @@ If foo has multiple source files, add the line:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The include file <bsd.subdir.mk> contains the default targets for building
subdirectories. It has the same eight targets as <bsd.prog.mk>: all,
subdirectories. It has the same eight targets as <bsd.prog.mk>: all,
clean, cleandir, depend, includes, install, lint, and tags. For all of
the directories listed in the variable SUBDIRS, the specified directory
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.

View File

@ -1,16 +1,16 @@
#
# RCSid:
# $Id: auto.dep.mk,v 1.5 2016/04/05 15:58:37 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -20,11 +20,11 @@
# set MKDEP_MK=auto.dep.mk and dep.mk will include us
# This version differs from autodep.mk, in that
# 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.
@ -37,7 +37,7 @@ __${.PARSEFILE}__:
# set this to -MMD to ignore /usr/include
# actually it ignores <> so may not be a great idea
CFLAGS_MD ?= -MD
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}

View File

@ -1,14 +1,14 @@
# $Id: auto.obj.mk,v 1.15 2017/11/04 21:05:04 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -16,7 +16,7 @@
ECHO_TRACE ?= echo
.ifndef Mkdirs
# A race condition in some versions of mkdir, means that it can bail
# 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.
@ -53,7 +53,7 @@ __objdir:= ${__objdir}
# We need to chdir, make the directory if needed
.if !exists(${__objdir}/) && \
(${.TARGETS} == "" || ${.TARGETS:Nclean*:N*clean:Ndestroy*} != "")
# This will actually make it...
# This will actually make it...
__objdir_made != echo ${__objdir}/; umask ${OBJDIR_UMASK:U002}; \
${ECHO_TRACE} "[Creating objdir ${__objdir}...]" >&2; \
${Mkdirs}; Mkdirs ${__objdir}

View File

@ -1,14 +1,14 @@
# $Id: autoconf.mk,v 1.9 2017/08/13 20:03:13 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -49,7 +49,7 @@ CLEANFILES+= config.recheck config.gen config.status *.meta
AUTOCONF ?= autoconf
AUTOHEADER ?= autoheader
# expand it to a full path
# expand it to a full path
AUTOCONF := ${AUTOCONF:${M_whence}}
.if exists(${AUTOCONF})

View File

@ -1,16 +1,16 @@
#
# RCSid:
# $Id: autodep.mk,v 1.37 2020/04/17 21:08:17 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
@ -51,7 +51,7 @@ ${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
# 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.
@ -64,7 +64,7 @@ __dependsrcs= ${__dependsrcsx:O:u}
# set this to -MMD to ignore /usr/include
# actually it ignores <> so may not be a great idea
CFLAGS_MD?=-MD
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
@ -73,8 +73,8 @@ 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}
CPPFLAGS_MD=${CFLAGS:M-[IUD]*} ${CPPFLAGS}
CXXFLAGS_MD=${CXXFLAGS:M-[IUD]*} ${CPPFLAGS}
# just in case these need to be different
CC_MD?=${CC}

View File

@ -1,14 +1,14 @@
# $Id: compiler.mk,v 1.6 2019/09/28 17:12:00 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,15 +1,15 @@
# RCSid:
# $Id: cython.mk,v 1.7 2018/03/25 18:46:11 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -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 <dirdeps.mk>
.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

View File

@ -1,6 +1,6 @@
# $Id: dirdeps-options.mk,v 1.9 2018/09/20 00:07:19 sjg Exp $
# $Id: dirdeps-options.mk,v 1.17 2020/08/07 01:57:38 sjg Exp $
#
# @(#) Copyright (c) 2018, Simon J. Gerraty
# @(#) 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.
@ -37,6 +37,11 @@
# 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
@ -47,21 +52,43 @@ DIRDEPS_OPTIONS ?=
.if ${.MAKE.LEVEL} == 0
# :U below avoids potential errors when we :=
.for o in ${DIRDEPS_OPTIONS:tu}
DIRDEPS += ${DIRDEPS.$o.${MK_$o:U}:U}
# 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:tu}
.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:tu}
.for o in ${DIRDEPS_OPTIONS}
.for d in ${DIRDEPS.$o.yes} ${DIRDEPS.$o.no}
.if exists(${SRCTOP}/$d)
GENDIRDEPS_FILTER += N$d*

View File

@ -1,15 +1,15 @@
# RCSid:
# $Id: dirdeps-targets.mk,v 1.10 2020/06/06 22:41:02 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -25,7 +25,16 @@
# 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
@ -125,12 +134,38 @@ DIRDEPS := ${DIRDEPS:O:u}
.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 <dirdeps.mk>
.endif
DIRDEPS_TARGETS_SKIP += all clean* destroy*
.for t in ${.TARGETS:${DIRDEPS_TARGETS_SKIP:${M_ListToSkip}}}
$t: dirdeps
.endfor
.endfor
.endif
.endif

View File

@ -1,4 +1,4 @@
# $Id: dirdeps.mk,v 1.106 2020/07/11 16:25:17 sjg Exp $
# $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.
@ -41,7 +41,7 @@
# or .<target_spec> 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 .<target_spec>.
@ -50,29 +50,22 @@
#
# 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 .<target_spec>
# 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).
#
# BUILD_AT_LEVEL0
# Indicates whether .MAKE.LEVEL 0 builds anything:
# if "no" sub-makes are used to build everything,
# if "yes" sub-makes are only used to build for other machines.
# It is best to use "no", but this can require fixing some
# makefiles to not do anything at .MAKE.LEVEL 0.
#
# TARGET_SPEC_VARS
# The default value is just MACHINE, and for most environments
# this is sufficient. The _DIRDEP_USE target actually sets
@ -113,12 +106,12 @@
# # 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.
@ -137,6 +130,19 @@
# 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) || \
@ -157,11 +163,6 @@ _DIRDEP_USE_LEVEL?= 0
_CURDIR ?= ${.CURDIR}
_OBJDIR ?= ${.OBJDIR}
now_utc = ${%s:L:gmtime}
.if !defined(start_utc)
start_utc := ${now_utc}
.endif
.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
# This little trick let's us do
#
@ -223,6 +224,7 @@ _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
@ -307,6 +309,7 @@ DEP_MACHINE := ${_DEP_TARGET_SPEC}
# 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.
@ -337,7 +340,7 @@ BUILD_DIRDEPS ?= yes
.if ${MK_DIRDEPS_CACHE} == "yes"
# this is where we will cache all our work
DIRDEPS_CACHE ?= ${_OBJDIR:tA}/dirdeps.cache${.TARGETS:Nall:O:u:ts-:S,/,_,g:S,^,.,:N.}
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}@} != ""
@ -393,6 +396,18 @@ DIRDEPS_FILTER += M${_DEP_RELDIR}
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
@ -400,7 +415,7 @@ DIRDEP_DIR ?= ${.TARGET:R}
_DIRDEP_USE: .USE .MAKE
@for m in ${.MAKE.MAKEFILE_PREFERENCE}; do \
test -s ${.TARGET:R}/$$m || continue; \
echo "${TRACER}Checking ${.TARGET:R} for ${.TARGET:E} ..."; \
echo "${TRACER}Checking ${.TARGET:S,${SRCTOP}/,,} for ${.TARGET:E} ..."; \
${DIRDEP_USE_PRELUDE} \
MACHINE_ARCH= NO_SUBDIR=1 ${DIRDEP_USE_ENV} \
TARGET_SPEC=${.TARGET:E} \
@ -480,9 +495,13 @@ dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
dirdeps MK_DIRDEPS_CACHE=no BUILD_DIRDEPS=no
# these should generally do
BUILD_DIRDEPS_MAKEFILE ?= ${MAKEFILE}
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.
@ -494,26 +513,28 @@ ${DIRDEPS_CACHE}: .META .NOMETA_CMP
+@MAKELEVEL=${.MAKE.LEVEL} DIRDEPS_CACHE=${DIRDEPS_CACHE} \
DIRDEPS="${DIRDEPS}" \
TARGET_SPEC=${TARGET_SPEC} \
MAKEFLAGS= ${.MAKE} -C ${_CURDIR} -f ${BUILD_DIRDEPS_MAKEFILE} \
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' >> ${.TARGET}.new && \
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:[#]}'; } >&3
@{ 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:[#]} seconds=`expr ${now_utc} - ${start_utc}`"
@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
@ -570,19 +591,7 @@ _build_dirs =
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# pickup other machines for this dir if necessary
.if ${BUILD_AT_LEVEL0:Uyes} == "no"
_build_dirs += ${_machines:@m@${_CURDIR}.$m@}
.else
_build_dirs += ${_machines:N${DEP_TARGET_SPEC}:@m@${_CURDIR}.$m@}
.if ${DEP_TARGET_SPEC} == ${TARGET_SPEC}
# pickup local dependencies now
.if ${MAKE_VERSION} < 20160220
.-include <.depend>
.else
.dinclude <.depend>
.endif
.endif
.endif
.endif
.if ${_debug_reldir}
@ -635,7 +644,7 @@ _build_dirs := ${_build_dirs:${M_dep_qual_fixes:ts:}:O:u}
.endif # empty DIRDEPS
_build_all_dirs += ${_build_dirs}
_build_all_dirs += ${_build_dirs} ${_build_xtra_dirs}
_build_all_dirs := ${_build_all_dirs:O:u}
# Normally if doing make -V something,
@ -647,12 +656,7 @@ _build_all_dirs := ${_build_all_dirs:O:u}
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}@}
.if !empty(_new_dirdeps)
.export _new_dirdeps
x!= echo; { echo; echo "dirdeps: \\"; \
for x in $$_new_dirdeps; do echo " $$x \\"; done; echo; \
for x in $$_new_dirdeps; do echo "$$x: _DIRDEP_USE"; done; } >&3
.endif
.export _build_xtra_dirs _new_dirdeps
.if !empty(DEP_EXPORT_VARS)
# Discouraged, but there are always exceptions.
# Handle it here rather than explain how.
@ -676,7 +680,8 @@ DEP_EXPORT_VARS=
# this builds the dependency graph
.for m in ${_machines}
.if ${BUILD_DIRDEPS_CACHE} == "yes" && !empty(_build_dirs)
x!= echo; { echo; echo "${_this_dir}.$m: \\"; } >&3
x!= echo; { echo; echo 'DIRDEPS.${_this_dir}.$m = \'; } >&3
_cache_deps =
.endif
# it would be nice to do :N${.TARGET}
.if !empty(__qual_depdirs)
@ -685,11 +690,7 @@ x!= echo; { echo; echo "${_this_dir}.$m: \\"; } >&3
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$q}
.endif
.if ${BUILD_DIRDEPS_CACHE} == "yes"
_cache_deps := ${_build_dirs:M*.$q}
.if !empty(_cache_deps)
.export _cache_deps
x!= echo; for x in $$_cache_deps; do echo " $$x \\"; done >&3
.endif
_cache_deps += ${_build_dirs:M*.$q}
.else
${_this_dir}.$m: ${_build_dirs:M*.$q}
.endif
@ -699,11 +700,17 @@ ${_this_dir}.$m: ${_build_dirs:M*.$q}
.info ${DEP_RELDIR}.$m: graph: ${_build_dirs:M*.$m:N${_this_dir}.$m}
.endif
.if ${BUILD_DIRDEPS_CACHE} == "yes"
_cache_deps := ${_build_dirs:M*.$m:N${_this_dir}.$m}
.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
@ -773,6 +780,27 @@ _DEP_RELDIR := ${RELDIR}
# This is a final opportunity to add/hook global rules.
.-include <local.dirdeps-build.mk>
# 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>

View File

@ -1,14 +1,14 @@
# $Id: dpadd.mk,v 1.27 2019/05/17 13:58:53 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -75,7 +75,7 @@
# and -L${STAGE_OBJTOP}/usr/lib are sufficient, and we should
# have no need of anything else.
#
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@ -98,7 +98,7 @@ RELOBJTOP?= ${OBJTOP}
RELSRCTOP?= ${SRCTOP}
# we get included just about everywhere so this is handy...
# C*DEBUG_XTRA are for defining on cmd line etc
# 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}
@ -180,14 +180,14 @@ 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
@ -198,7 +198,7 @@ DPMAGIC_LIBS += ${__dpadd_magic_libs} \
# 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.
#
@ -215,8 +215,8 @@ INCLUDES_${__lib:T:R}?= -I${exists(${SRC_${__lib:T:R}}/h):?${SRC_${__lib:T:R}}/h
.endfor
# even for staged libs we sometimes
# need to allow direct -I to avoid cicular dependencies
# 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
@ -267,7 +267,7 @@ __dpadd_last_incs += ${__dpadd_magic_libs:O:u:@s@${SRC_LIBS_${s:T:R}:U}@:@x@${IN
__dpadd_last_incs := \
${__dpadd_last_incs:N-I/usr/*} \
${__dpadd_incs:M-I/usr/*} \
${__dpadd_last_incs:M-I/usr/*}
${__dpadd_last_incs:M-I/usr/*}
__dpadd_incs := ${__dpadd_incs:N-I/usr/*}
.endif
@ -310,12 +310,12 @@ dpadd: .NOTMAIN
.endif
.ifdef SRC_PATHADD
# We don't want to assume that we need to .PATH every element of
# 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
# 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}

View File

@ -1,14 +1,14 @@
# $Id: files.mk,v 1.6 2017/05/07 02:21:02 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,18 +1,18 @@
# $Id: gendirdeps.mk,v 1.44 2020/06/23 04:21:51 sjg Exp $
# $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:
# 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.
# 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.
#
# 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
@ -23,7 +23,7 @@
# 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.
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This makefile [re]generates ${.MAKE.DEPENDFILE}
@ -104,7 +104,7 @@ GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_DIR_VARS:@v@S,${$v},_{${v}},@}
GENDIRDEPS_FILTER += ${GENDIRDEPS_FILTER_VARS:@v@S,/${$v}/,/_{${v}}/,@:NS,//,*:u}
.endif
# this (*should* be set in meta.sys.mk)
# this (*should* be set in meta.sys.mk)
# is the script that extracts what we want.
META2DEPS ?= ${.PARSEDIR}/meta2deps.sh
META2DEPS := ${META2DEPS}
@ -122,7 +122,7 @@ _py_d =
.if ${META2DEPS:E} == "py"
# we can afford to do this all the time.
DPDEPS ?= no
META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d}
META2DEPS_CMD = ${_time} ${PYTHON} ${META2DEPS} ${_py_d}
.if ${DPDEPS:tl} != "no"
META2DEPS_CMD += -D ${DPDEPS}
.endif
@ -155,8 +155,8 @@ M2D_OBJROOTS += ${STAGE_ROOT}
# 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
.if defined(SB_BACKING_SB)
META2DEPS_CMD += -S ${SB_BACKING_SB}/src
M2D_OBJROOTS += ${SB_BACKING_SB}/${SB_OBJPREFIX}
.endif
@ -177,7 +177,7 @@ _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,
# 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
@ -234,10 +234,10 @@ dir_list += ${ddeps}
# 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
# 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
# so we add
# ${"${dir_list:M*bsd/sys/${MACHINE_ARCH}/include}":?bsd/include:}
# to GENDIRDEPS_DIR_LIST_XTRAS
_objtops = ${OBJTOP} ${_OBJTOP} ${_objtop}
@ -272,11 +272,11 @@ DIRDEPS = \
# 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
# 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,
# 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:}}@}@} \
@ -309,7 +309,7 @@ SRC_DIRDEPS = \
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}
# 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;
@ -324,7 +324,7 @@ ${SRC_DIRDEPS_FILE}: ${META_FILES} ${_this} ${META2DEPS}
.endif
.endif
.endif
_include_src_dirdeps ?=
_include_src_dirdeps ?=
all: ${_DEPENDFILE}
@ -339,11 +339,7 @@ CAT_DEPEND ?= .depend
.PHONY: ${_DEPENDFILE}
.endif
.if ${BUILD_AT_LEVEL0:Uno:tl} == "no"
LOCAL_DEPENDS_GUARD ?= _{.MAKE.LEVEL} > 0
.else
LOCAL_DEPENDS_GUARD ?= _{DEP_RELDIR} == _{_DEP_RELDIR}
.endif
# 'cat .depend' should suffice, but if we are mixing build modes
# .depend may contain things we don't want.

View File

@ -1,5 +1,5 @@
# RCSid:
# $Id: host-target.mk,v 1.12 2020/07/08 23:35:29 sjg Exp $
# $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)
@ -16,7 +16,7 @@ _HOST_MACHINE != uname -m
.endif
.if !defined(_HOST_ARCH)
# for NetBSD prefer $MACHINE (amd64 rather than x86_64)
.if ${_HOST_OSNAME:NNetBSD} == ""
.if ${_HOST_OSNAME:NDarwin:NNetBSD} == ""
_HOST_ARCH := ${_HOST_MACHINE}
.else
_HOST_ARCH != uname -p 2> /dev/null || uname -m

View File

@ -1,14 +1,14 @@
# $Id: host.libnames.mk,v 1.4 2010/01/11 23:01:31 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,14 +1,14 @@
# $Id: inc.mk,v 1.7 2017/05/06 17:29:45 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,14 +1,14 @@
# $Id: init.mk,v 1.17 2020/05/25 20:15:07 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -65,7 +65,11 @@ CC_PIC?= -DPIC
CXX_PIC?= ${CC_PIC}
PROFFLAGS?= -DGPROF -DPROF
.if ${.MAKE.LEVEL:U1} == 0 && ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
# 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

View File

@ -33,7 +33,7 @@
#
# 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".
#
@ -55,22 +55,22 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
# $Id: install-mk,v 1.174 2020/07/10 21:50:14 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
MK_VERSION=20200710
MK_VERSION=20200826
OWNER=
GROUP=
MODE=444
@ -137,7 +137,7 @@ if [ -s $SYS_MK -a -d $dest ]; then
sys_mk_dir=`realpath $SYS_MK_DIR`
if [ $dest = $sys_mk_dir ]; then
case "$os" in
*BSD*) SKIP_SYS_MK=:
*BSD*) SKIP_SYS_MK=:
SKIP_BSD_MK=:
;;
*) # could be fake?

View File

@ -1,14 +1,14 @@
# $Id: install-new.mk,v 1.3 2012/03/24 18:25:49 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,16 +1,16 @@
#
# RCSid:
# $Id: java.mk,v 1.14 2007/11/22 08:16:25 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -53,7 +53,7 @@ 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
# 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}

View File

@ -1,4 +1,4 @@
# $Id: lib.mk,v 1.70 2020/05/02 02:10:20 sjg Exp $
# $Id: lib.mk,v 1.71 2020/08/19 17:51:53 sjg Exp $
.if !target(__${.PARSEFILE}__)
__${.PARSEFILE}__:
@ -67,7 +67,7 @@ META_NOECHO?= echo
# Alpha-specific shared library flags
FPICFLAGS ?= -fPIC
CPICFLAGS ?= -fPIC -DPIC
CPPPICFLAGS?= -DPIC
CPPPICFLAGS?= -DPIC
CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
APICFLAGS ?=
.elif ${MACHINE_ARCH} == "mipsel" || ${MACHINE_ARCH} == "mipseb"
@ -87,7 +87,7 @@ 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
# If you use -fPIC you need to define BIGPIC to turn on 32-bit
# relocations in asm code
FPICFLAGS ?= -fPIC
CPICFLAGS ?= -fPIC -DPIC
@ -102,7 +102,7 @@ SHLIB_SOVERSION=${SHLIB_FULLVERSION}
SHLIB_SHFLAGS=
FPICFLAGS ?= -fPIC
CPICFLAGS?= -fPIC -DPIC
CPPPICFLAGS?= -DPIC
CPPPICFLAGS?= -DPIC
CAPICFLAGS?= ${CPPPICFLAGS} ${CPICFLAGS}
APICFLAGS?= -k
@ -246,7 +246,7 @@ 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
# 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
@ -272,7 +272,7 @@ ${CXX_SUFFIXES:%=%.o}:
${COMPILE.cc} ${.IMPSRC}
.S.o .s.o:
${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC}
${COMPILE.S} ${CFLAGS:M-[ID]*} ${AINC} ${.IMPSRC}
.if (${LD_X} == "")
.c.po:
@ -382,7 +382,7 @@ _LIBS+= ${libLDORDER_INC}
.endif
.if !defined(_SKIP_BUILD)
realbuild: ${_LIBS}
realbuild: ${_LIBS}
.endif
all: _SUBDIRUSE

View File

@ -1,14 +1,14 @@
# $Id: libnames.mk,v 1.8 2016/04/05 15:58:37 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,14 +1,14 @@
# $Id: libs.mk,v 1.3 2013/08/02 18:28:48 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -82,12 +82,18 @@ UPDATE_DEPENDFILE = NO
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)
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})
(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

View File

@ -1,14 +1,14 @@
# $Id: links.mk,v 1.6 2014/09/29 17:14:40 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,14 +1,14 @@
# $Id: manifest.mk,v 1.2 2014/10/31 18:06:17 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -21,12 +21,12 @@
# ${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}.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.
# eg.
# MODE.sbin = 550
# MODE.usr/sbin = 550
# MODE.dirs = 555
@ -37,7 +37,7 @@
# 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
# but we can use
# ${MANIFEST}.SRCS.sbin += ${OBJTOP}/bin/sh-static/sh-static
# STORE.sbin/sh-static = sbin/sh
#
@ -47,7 +47,7 @@
UID.dirs ?= 0
GID.dirs ?= 0
MODE.dirs ?= 775
FLAGS.dirs ?=
FLAGS.dirs ?=
UID.files ?= 0
GID.files ?= 0

View File

@ -1,4 +1,4 @@
# $Id: meta.autodep.mk,v 1.50 2018/06/08 01:25:31 sjg Exp $
# $Id: meta.autodep.mk,v 1.52 2020/07/18 05:57:57 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@ -57,7 +57,7 @@ _OBJTOP ?= ${OBJTOP}
_OBJROOT ?= ${OBJROOT:U${_OBJTOP}}
_DEPENDFILE := ${_CURDIR}/${.MAKE.DEPENDFILE:T}
.if ${.MAKE.LEVEL} > 0 || ${BUILD_AT_LEVEL0:Uyes:tl} == "yes"
.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}
@ -73,10 +73,8 @@ UPDATE_DEPENDFILE = NO
.endif
.if ${.MAKE.LEVEL} == 0
.if ${BUILD_AT_LEVEL0:Uyes:tl} == "no"
UPDATE_DEPENDFILE = NO
.endif
.endif
.if !exists(${_DEPENDFILE})
_bootstrap_dirdeps = yes
.endif
@ -283,9 +281,7 @@ ${_DEPENDFILE}: ${_depend} ${.PARSEDIR}/gendirdeps.mk ${META2DEPS} $${.MAKE.MET
.endif
.if ${_bootstrap_dirdeps} == "yes"
.if ${BUILD_AT_LEVEL0:Uno} == "no"
DIRDEPS+= ${RELDIR}.${TARGET_SPEC:U${MACHINE}}
.endif
# make sure this is included at least once
.include <dirdeps.mk>
.else
@ -312,7 +308,7 @@ _reldir_finish: .NOMETA
_reldir_failed: .NOMETA
@echo "${TIME_STAMP} Failed ${RELDIR}.${TARGET_SPEC} seconds=$$(( ${now_utc} - ${start_utc} )) ${meta_stats}"
.if defined(WITH_META_STATS) && ${.MAKE.LEVEL} > 0
.if !defined(WITHOUT_META_STATS) && ${.MAKE.LEVEL} > 0
.END: _reldir_finish
.ERROR: _reldir_failed
.endif

View File

@ -1,14 +1,14 @@
# $Id: meta.stage.mk,v 1.59 2020/04/25 18:18:27 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

View File

@ -1,4 +1,4 @@
# $Id: meta.subdir.mk,v 1.11 2015/11/24 22:26:51 sjg Exp $
# $Id: meta.subdir.mk,v 1.12 2020/08/19 17:51:53 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@ -6,10 +6,10 @@
# 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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -32,7 +32,7 @@ DIRDEPS = ${SUBDIR:N.WAIT:O:u:@d@${RELDIR}/$d@}
.include <meta.autodep.mk>
.else
# this is the cunning bit
# actually it is probably a bit risky
# 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.

View File

@ -1,4 +1,4 @@
# $Id: meta.sys.mk,v 1.36 2020/05/16 23:21:48 sjg Exp $
# $Id: meta.sys.mk,v 1.38 2020/08/19 17:51:53 sjg Exp $
#
# @(#) Copyright (c) 2010-2020, Simon J. Gerraty
@ -6,10 +6,10 @@
# 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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#
@ -155,12 +155,6 @@ dirdeps:
# the first .MAIN: is what counts
# by default dirdeps is all we want at level0
.MAIN: dirdeps
# tell dirdeps.mk what we want
BUILD_AT_LEVEL0 = no
.endif
.if ${.TARGETS:Nall} == ""
# it works best if we do everything via sub-makes
BUILD_AT_LEVEL0 ?= no
.endif
.endif

View File

@ -25,7 +25,7 @@
'W' files opened for write or read-write,
for filemon V3 and earlier.
'E' files executed.
'L' files linked
@ -37,20 +37,20 @@
"""
RCSid:
$Id: meta2deps.py,v 1.30 2020/06/08 23:05:00 sjg Exp $
$Id: meta2deps.py,v 1.33 2020/08/19 17:51:53 sjg Exp $
Copyright (c) 2011-2019, Simon J. Gerraty
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:
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.
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.
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
@ -62,8 +62,8 @@
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.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import os, re, sys
@ -164,7 +164,7 @@ def sort_unique(list, cmp=None, key=None, reverse=False):
def add_trims(x):
return ['/' + x + '/',
'/' + x,
'/' + x,
x + '/',
x]
@ -181,7 +181,7 @@ class MetaFile:
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:
@ -198,7 +198,7 @@ def __init__(self, name, conf={}):
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.
@ -222,7 +222,7 @@ def __init__(self, name, conf={}):
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)
@ -310,11 +310,11 @@ def reset(self):
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)
@ -333,7 +333,7 @@ def file_depends(self, out=None):
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:
@ -392,10 +392,10 @@ def try_parse(self, name=None, file=None):
# 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"
@ -506,6 +506,8 @@ def parse(self, name=None, file=None):
continue
elif w[0] in 'ERWS':
path = w[2]
if path == '.':
continue
self.parse_path(path, cwd, w[0], w)
if not file:
@ -601,13 +603,13 @@ def parse_path(self, path, cwd, op=None, w=[]):
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.
@ -615,7 +617,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
add "SRCTOP" to the "SRCTOPS" list.
-C "CURDIR"
-O "OBJROOT"
add "OBJROOT" to the "OBJROOTS" list.
@ -626,7 +628,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
-H "HOST_TARGET"
-D "DPDEPS"
-d bumps debug level
"""
@ -666,7 +668,7 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
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':

View File

@ -5,11 +5,11 @@
#
# 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.
@ -75,20 +75,20 @@
# RCSid:
# $Id: meta2deps.sh,v 1.12 2016/12/13 20:44:16 sjg Exp $
# $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:
# 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.
# 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.
#
# 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
@ -99,14 +99,14 @@
# 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.
# 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' |
@ -167,7 +167,7 @@ meta2deps() {
case "$MACHINE" in
host) _ht=$HOST_TARGET;;
esac
for o in $OBJROOTS
do
case "$MACHINE,/$o/" in
@ -201,7 +201,7 @@ meta2deps() {
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.*
@ -272,10 +272,10 @@ meta2deps() {
eval cwd_$pid=$cwd
continue
;;
F,*) # $path is new pid
F,*) # $path is new pid
eval cwd_$path=$cwd ldir_$path=$ldir
continue
;;
;;
*) dir=${path%/*}
case "$path" in
$src_re|$obj_re) ;;

View File

@ -14,17 +14,17 @@ Many years ago, when building large software projects, I used GNU make
to simplify developing complex build trees.
Since the early 90's my main development machines, run BSD
(NetBSD_ to be precise), 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 were quite tightly
linked to building the BSD tree.
(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
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.
@ -59,7 +59,7 @@ 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
provided by bmake_ that allow simple makefiles such as the above to
*just work* on many different systems.
@ -67,7 +67,7 @@ mk-files
========
This section provides a brief description of some of the ``*.mk``
files.
files.
sys.mk
------
@ -76,7 +76,7 @@ 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.
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)
@ -97,7 +97,7 @@ examples/sys.clean-env.mk
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}
@ -169,7 +169,7 @@ lib${LIB}.a
An archive lib of ``.o`` files, this is the default
lib${LIB}_p.a
A profiled lib of ``.po`` files.
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".
@ -194,7 +194,7 @@ lib${LIB}.${LD_so}
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``.
the system's ``sys.mk``.
libnames.mk
-----------
@ -204,22 +204,19 @@ 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.
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``::
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.
sjg.libnames.mk
not part of the mk-files distribution.
host.libnames.mk
contains logic to find any libs named in ``HOST_LIBS`` in
``HOST_LIBDIRS``.
@ -248,7 +245,7 @@ else in various ways::
# it also has the same effect as SRC_LIBS
DPADD += ${LIBSSLFD}
# indicate that not only must libsslfd be built,
# indicate that not only must libsslfd be built,
# but that we need to link with it.
# this is almost exactly equivalent to
# DPADD += ${LIBSSLFD}
@ -324,7 +321,7 @@ 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 clue as it visits each subdir::
Traditionally, ``subdir.mk`` prints clues as it visits each subdir::
===> ssl
===> ssl/lib
@ -342,7 +339,7 @@ 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``).
(``link`` -> ``target``).
The logic is generally in a ``_*_SCRIPT`` which is referenced in a
``_*_USE`` (``.USE``) target.
@ -353,7 +350,7 @@ 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
@ -394,10 +391,10 @@ post process the ``.d`` files into ``.depend``.
auto.dep.mk
-----------
A much simpler implementation than autodep.mk_ it uses
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
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
@ -452,7 +449,7 @@ 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.
customizations.
rst2htm.mk
----------
@ -470,7 +467,7 @@ Meta mode
=========
The 20110505 and later versions of ``mk-files`` include a number of
makefiles contributed by Juniper Networks, Inc.
makefiles contributed by Juniper Networks, Inc.
These allow the latest version of bmake_ to run in `meta mode`_
see `dirdeps.mk`_
@ -499,5 +496,5 @@ where you unpacked the tar file, you can::
.. _mk.tar.gz: http://www.crufty.net/ftp/pub/sjg/mk.tar.gz
:Author: sjg@crufty.net
:Revision: $Id: mk-files.txt,v 1.18 2018/12/08 07:27:15 sjg Exp $
:Revision: $Id: mk-files.txt,v 1.20 2020/08/19 17:51:53 sjg Exp $
:Copyright: Crufty.NET

View File

@ -1,16 +1,16 @@
#!/bin/sh
# $Id: mkopt.sh,v 1.12 2020/06/23 04:16:35 sjg Exp $
# $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
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# left intact.
#
# Please send copies of changes and bug-fixes to:
# sjg@crufty.net
#

Some files were not shown because too many files have changed in this diff Show More