summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--Makefile.inc3
-rw-r--r--README7
-rw-r--r--custom/Makefile2
-rwxr-xr-xcustom/endianness (renamed from custom/endianess)2
-rwxr-xr-xcustom/prog_nbmkdep7
-rw-r--r--doc/LICENSE2
-rw-r--r--doc/NEWS64
-rw-r--r--doc/TODO45
-rw-r--r--examples/Makefile42
-rw-r--r--examples/Makefile.inc11
-rw-r--r--examples/hello_RBTREE/Makefile10
-rw-r--r--examples/hello_RBTREE/expect.out7
-rw-r--r--examples/hello_RBTREE/hello_RBTREE.c82
-rw-r--r--examples/hello_RBTREE/input.in12
-rw-r--r--examples/hello_RBTREE/test.mk8
-rw-r--r--examples/hello_SLIST/Makefile10
-rw-r--r--examples/hello_SLIST/expect.out7
-rw-r--r--examples/hello_SLIST/hello_SLIST.c66
-rw-r--r--examples/hello_SLIST/input.in7
-rw-r--r--examples/hello_SLIST/test.mk8
-rw-r--r--examples/hello_calc2/Makefile10
-rw-r--r--examples/hello_calc2/expect.out18
-rw-r--r--examples/hello_calc2/parser.y2
-rw-r--r--examples/hello_customtests/Makefile6
-rw-r--r--examples/hello_customtests/expect.out8
-rw-r--r--examples/hello_customtests/test.mk4
-rw-r--r--examples/hello_customtests2/test.mk4
-rw-r--r--examples/hello_cxxlib/cxxlib/linkme.mk2
-rw-r--r--examples/hello_dictd/expect.out157
-rw-r--r--examples/hello_dictd/libcommon/linkme.mk2
-rw-r--r--examples/hello_dictd/libdz/linkme.mk2
-rw-r--r--examples/hello_dictd/libmaa/linkme.mk2
-rw-r--r--examples/hello_dictd/test.mk25
-rw-r--r--examples/hello_files/test.mk2
-rw-r--r--examples/hello_iconv/Makefile18
-rw-r--r--examples/hello_iconv/expect.out1
-rw-r--r--examples/hello_iconv/hello_iconv.c21
-rw-r--r--examples/hello_iconv/test.mk7
-rw-r--r--examples/hello_lex/test.mk4
-rw-r--r--examples/hello_plugins2/app/Makefile8
-rw-r--r--examples/hello_plugins2/expect.out6
-rw-r--r--examples/hello_strlcpy/getline.c28
-rw-r--r--examples/hello_strlcpy/hello.c1
-rw-r--r--examples/hello_strlcpy2/Makefile13
-rw-r--r--examples/hello_strlcpy2/expect.out93
-rw-r--r--examples/hello_strlcpy2/hello.c30
-rw-r--r--examples/hello_strlcpy2/input.in23
-rw-r--r--examples/hello_strlcpy2/missing/getline.c67
-rw-r--r--examples/hello_strlcpy2/missing/strlcpy.c51
-rw-r--r--examples/hello_strlcpy2/test.mk38
-rw-r--r--examples/hello_strlcpy3/Makefile11
-rw-r--r--examples/hello_strlcpy3/expect.out101
-rw-r--r--examples/hello_strlcpy3/hello.c32
-rw-r--r--examples/hello_strlcpy3/input.in23
-rw-r--r--examples/hello_strlcpy3/test.mk40
-rw-r--r--examples/hello_subdirs/Makefile.inc1
-rw-r--r--examples/hello_subdirs/prog1/expect.out2
-rw-r--r--examples/hello_subdirs/prog1/test.mk3
-rw-r--r--examples/hello_subdirs/prog2/expect.out2
-rw-r--r--examples/hello_subdirs/prog2/test.mk3
-rw-r--r--examples/hello_yacc/test.mk2
-rw-r--r--examples/pkgconfig3/Makefile8
-rw-r--r--examples/pkgconfig3/expect.out1
-rw-r--r--examples/pkgconfig3/pkgconfig3.c13
-rw-r--r--examples/pkgconfig3/test.mk7
-rw-r--r--examples/subprojects/Makefile46
-rw-r--r--examples/subprojects/expect.out51
-rw-r--r--examples/subprojects/libhello1/linkme.mk2
-rw-r--r--examples/subprojects/libhello2/linkme.mk2
-rw-r--r--examples/subprojects/test.mk26
-rw-r--r--examples/tools/expect.out102
-rw-r--r--examples/tools/libs/bar/linkme.mk2
-rw-r--r--examples/tools/libs/foo/linkme.mk2
-rw-r--r--examples/tools/libs/qux/linkme.mk2
-rw-r--r--examples/tools/test.mk13
-rw-r--r--examples/tools2/Makefile3
-rw-r--r--examples/tools2/expect.out49
-rw-r--r--examples/tools2/libs/bar/linkme.mk2
-rw-r--r--examples/tools2/libs/foo/linkme.mk2
-rw-r--r--examples/tools2/libs/qux/linkme.mk2
-rw-r--r--examples/tools2/test.mk12
-rw-r--r--features/Makefile37
-rw-r--r--features/getline/getline.c49
-rw-r--r--features/mkc_RB.h16
-rw-r--r--features/mkc_SLIST.h16
-rw-r--r--features/mkc_getline.h17
-rw-r--r--features/mkc_imp.f_RB.mk7
-rw-r--r--features/mkc_imp.f_SLIST.mk30
-rw-r--r--features/mkc_imp.f_getline.mk7
-rw-r--r--features/mkc_imp.f_libdl.mk8
-rw-r--r--features/mkc_imp.f_libm.mk5
-rw-r--r--features/mkc_imp.f_strlcat.mk7
-rw-r--r--features/mkc_imp.f_strlcpy.mk7
-rw-r--r--features/mkc_libdl.h18
-rw-r--r--features/mkc_libm.h12
-rw-r--r--features/mkc_strlcat.h16
-rw-r--r--features/mkc_strlcpy.h16
-rw-r--r--features/netbsd_sys_queue.h743
-rw-r--r--features/netbsd_sys_tree.h741
-rw-r--r--features/strlcat/strlcat.c60
-rw-r--r--features/strlcpy/strlcpy.c55
-rw-r--r--main.mk25
-rw-r--r--mk/Makefile7
-rw-r--r--mk/configure.mk47
-rw-r--r--mk/mkc.init.mk281
-rw-r--r--mk/mkc_imp.checkprogs.mk29
-rw-r--r--mk/mkc_imp.conf-final.mk49
-rw-r--r--mk/mkc_imp.final.mk2
-rw-r--r--mk/mkc_imp.lib.mk6
-rw-r--r--mk/mkc_imp.mk75
-rw-r--r--mk/mkc_imp.objdir.mk1
-rw-r--r--mk/mkc_imp.pkg-config.mk58
-rw-r--r--mk/mkc_imp.platform.sys.mk25
-rw-r--r--mk/mkc_imp.prog.mk9
-rw-r--r--mk/mkc_imp.rules.mk99
-rw-r--r--mk/mkc_imp.subprj.mk52
-rw-r--r--mk/mkc_imp.vars.mk.in1
-rw-r--r--presentation/_mkc_prog_dot.err0
-rw-r--r--presentation/_mkc_prog_dot.res1
-rw-r--r--presentation/_mkc_prog_dvips.err0
-rw-r--r--presentation/_mkc_prog_dvips.res1
-rw-r--r--presentation/_mkc_prog_latex.err0
-rw-r--r--presentation/_mkc_prog_latex.res1
-rw-r--r--presentation/_mkc_prog_ps2pdf.err0
-rw-r--r--presentation/_mkc_prog_ps2pdf.res1
-rw-r--r--presentation/presentation.pdfbin0 -> 160669 bytes
-rw-r--r--presentation/presentation.tex2
-rw-r--r--scripts/mk-configure.7.in235
-rw-r--r--scripts/mkc_check_common.sh8
-rwxr-xr-xscripts/mkc_check_custom6
-rw-r--r--scripts/mkc_check_custom.158
-rwxr-xr-xscripts/mkc_check_decl59
-rw-r--r--scripts/mkc_check_decl.18
-rwxr-xr-xscripts/mkc_check_funclib2
-rw-r--r--tests/Makefile33
-rw-r--r--tests/Makefile.inc1
-rw-r--r--tests/configure_test/expect.out12
-rw-r--r--tests/configure_test/mkc_test.mk14
-rw-r--r--tests/configure_test/mkc_test_preset.mk2
-rw-r--r--tests/create_cachedir/Makefile8
-rw-r--r--tests/create_cachedir/expect.out2
-rw-r--r--tests/create_cachedir/hello.c5
-rw-r--r--tests/create_cachedir/test.mk22
-rw-r--r--tests/endianess/Makefile14
-rw-r--r--tests/endianess/expect.out3
-rw-r--r--tests/endianess/test.mk12
-rw-r--r--tests/mkinstall/test.mk2
-rw-r--r--tests/pkg_config_1_1/Makefile7
-rw-r--r--tests/pkg_config_1_1/test.mk14
-rw-r--r--tests/rec_makefiles/Makefile.common (renamed from tests/rec_makefiles/Makefile.rec)3
-rw-r--r--tests/rec_makefiles/expect.out12
-rw-r--r--tests/rec_makefiles/subdir1/Makefile.rec1
-rw-r--r--tests/rec_makefiles/subdir1/subsubdir1/Makefile.rec1
-rw-r--r--tests/rec_makefiles/subdir1/subsubdir2/Makefile.rec1
-rw-r--r--tests/rec_makefiles/subdir2/Makefile.rec1
-rw-r--r--tests/rec_makefiles/test.mk6
-rw-r--r--tests/reqd/expect.out2
-rw-r--r--tests/reqd2/expect.out2
-rw-r--r--tests/reqd3/expect.out2
-rw-r--r--tests/reqd4/expect.out2
-rw-r--r--tests/reqd_clean_cache/Makefile4
-rw-r--r--tests/reqd_clean_cache/expect.out1
-rw-r--r--tests/reqd_clean_cache/test.mk1
-rw-r--r--tests/require_prototype/Makefile14
-rw-r--r--tests/require_prototype/expect.out1
-rw-r--r--tests/require_prototype/test.mk5
-rw-r--r--tests/sys_queue/Makefile11
-rw-r--r--tests/sys_queue/hello.c17
-rw-r--r--tests/test_subprj_dash/Makefile1
170 files changed, 4241 insertions, 637 deletions
diff --git a/Makefile b/Makefile
index 0214e33..f92bdac 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,3 @@
.MAIN: all
.DEFAULT:
- ${MAKE} ${MAKEFLAGS} -m ${.CURDIR}/mk -f main.mk ${.TARGET}
+ @unset ROOT_GROUP; ${MAKE} ${MAKEFLAGS} -m ${.CURDIR}/mk -m ${.CURDIR}/features -f main.mk ${.TARGET}
diff --git a/Makefile.inc b/Makefile.inc
index 90716ad..ae58017 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -1,10 +1,11 @@
-VERSION = 0.25.0
+VERSION = 0.26.0
BIRTHDATE = 2009-02-21
MKFILESDIR ?= ${PREFIX}/share/mkc-mk
DOCDIR ?= ${PREFIX}/share/doc/mk-configure
BUILTINSDIR ?= ${PREFIX}/share/mk-configure/custom
+FEATURESDIR ?= ${PREFIX}/share/mk-configure/features
INTEXTS_REPLS += version ${VERSION}
INTEXTS_REPLS += AWK ${AWK}
diff --git a/README b/README
index 11ea316..bb39f50 100644
--- a/README
+++ b/README
@@ -25,7 +25,7 @@ mk-configure features:
libraries and function implementation, function definitions,
defines, types, struct members etc.
- - A number of built-in checks for, e.g., system endianess, GNU bison
+ - A number of built-in checks for, e.g., system endianness, GNU bison
or GNU flex programs and many others.
- Automatic dependency analysis built-in for C, C++ and Fortran (not
@@ -322,7 +322,10 @@ INSTALLATION:
Traditional BSD mkdep(1) is also good but NetBSD version is just better.
- 3)
+ 3) Download mk-configure source from either
+ http://mova.org/~cheusov/pub/mk-configure or
+ http://sourceforge.net/projects/mk-configure and unpack tarball.
+
# cd mk-configure-X.Y.Z/
# export PREFIX=/usr/local (the default)
diff --git a/custom/Makefile b/custom/Makefile
index b64b177..c79e9ab 100644
--- a/custom/Makefile
+++ b/custom/Makefile
@@ -1,4 +1,4 @@
-SCRIPTS = endianess prog_bison prog_flex prog_gawk prog_gm4
+SCRIPTS = endianness prog_bison prog_flex prog_gawk prog_gm4
SCRIPTSDIR = ${BUILTINSDIR}
diff --git a/custom/endianess b/custom/endianness
index 3393806..fb7d76e 100755
--- a/custom/endianess
+++ b/custom/endianness
@@ -13,7 +13,7 @@ export LC_ALL
##################################################
-pathpart=endianess
+pathpart=endianness
. mkc_check_common.sh
trap "rm -f $tmpc $tmpo" 0
diff --git a/custom/prog_nbmkdep b/custom/prog_nbmkdep
index 19f2de7..aad3716 100755
--- a/custom/prog_nbmkdep
+++ b/custom/prog_nbmkdep
@@ -6,4 +6,11 @@
# See LICENSE file in the distribution.
############################################################
+# workround for crappylaris
+if test -z "$CRAPPYLIS" -a -x /usr/xpg4/bin/sh; then
+ CRAPPYLIS=1
+ export CRAPPYLIS
+ exec /usr/xpg4/bin/sh "$0" "$@"
+fi
+
${0%%/prog_nbmkdep}/prog_mkdep --
diff --git a/doc/LICENSE b/doc/LICENSE
index 1a914f1..b55bbb2 100644
--- a/doc/LICENSE
+++ b/doc/LICENSE
@@ -4,7 +4,7 @@ See individual files for details.
######################################################################
-Copyright (c) 2009-2013 by Aleksey Cheusov
+Copyright (c) 2009-2014 by Aleksey Cheusov
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/doc/NEWS b/doc/NEWS
index 43a0f4a..323adaf 100644
--- a/doc/NEWS
+++ b/doc/NEWS
@@ -1,4 +1,66 @@
======================================================================
+Version 0.26.0, by Aleksey Cheusov, Mon, 3 Feb 2014 00:32:51 +0300
+
+ "Features" framework was implemented (variable MKC_FEATURES). In
+ general, a feature is something that has problems with
+ portability. This may be a function name or header missing on some
+ platforms, for example. What developer needs to do is to add
+ FEATURENAME to MKC_FEATURES variable and add #include
+ <mkc_FEATURENAME.h> where it is needed. Internally, system
+ requiremets are checked in the automatically included
+ mkc_imp.f_FEATURENAME.mk file and all required actions (includes,
+ define checks etc.) are made in mkc_FEATURENAME.h header file.
+ Currently the following features are provided: strlcat, strlcpy,
+ getline, libm, libdl, RB, SPLAY, SLIST, SIMPLEQ, STAILQ, LIST, TAILQ
+ and CIRCLEQ. Original idea was stolen from pkgsrc.
+
+ mkc_imp.pkg-config.mk:
+ - New variables MKC_CHECK_PKGCONFIG and MKC_REQUIRE_PKGCONFIG were
+ introduced. They work just like other MKC_{CHECK,REQUIRE}_*
+ variables from mkc.configure.mk. Thanks to Andrew Shadura for
+ pushing me to this direction.
+
+ mkc.configure.mk:
+ - MKC_{CHECK,REQUIRE}_PROTOTYPES were introduced. With their help
+ mk-configure is able to check C function prototypes. This
+ feature was proposed by Andrew Shadura.
+
+ If ${MKC_CACHEDIR} does not exit, it is automatically created.
+
+ ${SRCTOP}/Makefile.common is included by all subprojects if it
+ exists. It can be used as a replacement or addition for
+ ../Makefile.inc.
+
+ Valiables SRCDIR_<dir>, SRC_PATHADD, MKC_SOURCE_DIR, LDFLAGS0 and
+ LDADD0 were introduced.
+
+ Wrongly named builtin 'endianess' was renamed to 'endianness'.
+ Thanks to Andew Shadura for the report and fix!
+
+ mk-configure itself is now 2-level project.
+ This allows me to run an arbitrary regression test like the following
+ bmake test-examples/hello_world
+ Hurray! :-)
+
+ mkc.subprj.mk:
+ - Now it works correctly if NOSUBDIR is not empty.
+ Also, NOSUBDIR affects NODEPS and therefore the dependency graph.
+ - New target "print-deps" that outputs the dependency graph was
+ introduced.
+
+ -O is added to CFLAGS if USE_FORT==yes, seen on Linux/ppc64/gcc
+
+ Documentation: clean-ups, grammar fixes, minor improvements.
+
+ Fix. Some @@ patterns in mk-configure.7 should not be replaced with
+ directories. Thanks to Andrew Shadura for the report!
+
+ This release was successfully tested on the following platforms:
+ NetBSD-6.1/amd64, FreeBSD-8.3/amd64, OpenBSD-{4.9,5.3}/x86,
+ DragonFlyBSD-3.4/x86, Linux/{x86,amd64}, SunOS-5.10/sparc,
+ SunOS-5.11/x86.
+
+======================================================================
Version 0.25.0, by Aleksey Cheusov, Wed, 1 Jan 2014 19:28:55 +0300
Build infrastructure for mk-c itself was completely reimplemented.
@@ -616,7 +678,7 @@ Version 0.13.0, by Aleksey Cheusov, Sun, 27 Dec 2009 17:06:06 +0200
So called built-in checks are implemented. See MKC_CHECK_BUILTINS
variable. Built-in checks are checks provided by mk-configure. At
- the moment the following checks are implemented: endianess,
+ the moment the following checks are implemented: endianness,
prog_flex, prog_bison, prog_gawk, prog_gm4. See mk-configure.7 for
the documentation.
diff --git a/doc/TODO b/doc/TODO
index bcfa7de..5bc9e8b 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,8 +1,12 @@
============================================================
-Plan 0.25.0
+Plan 0.26.0
+
+- Special marker for checks that cannot be possible in cross-compiling
Some thoughts inspired by talks with Michael Crogan
+- MKASNEEDED=yes => ld --as-needed
+
- During development of huge projects it may make sense to always keep
"installed" version of the software somewhere (FAKEPREFIX?)
and always keep it synced.
@@ -16,13 +20,14 @@ Some thoughts inspired by talks with Michael Crogan
- VARIANTS for libraries.
+- _mkc_done_<prj>_<trg>
+
- project "roundup" for testing
- Better explain how "test" target works, maybe as a couple of slides
in the PDF presentation. With and without mkc.minitest.mk.
- One more example/ for TARGETS, demonstrating such things as
- "mkcmake release/debug/profile" or "mkcmake all_clang/all_gcc"
- or "valgrind_test"/"gcov_test" etc.
+ "mkcmake all_clang/all_gcc" or "valgrind_test"/"gcov_test" etc.
- Additional slides in PDF for virtual subprojects.
Notes about "virtual subproject" in examples/.
- Notes in examples/hello_dictd and other examples based on
@@ -34,7 +39,7 @@ Some thoughts inspired by talks with Michael Crogan
like shlock(1) or flock(1) is needed for this.
- Example is needed for how to embed autoconf-based subproject into a
project based on mk-configure. The sad fact is autoconf/automake is
- everywhere. So, it would be nice integrate mk-c into reality.
+ everywhere. So, it would be nice to integrate mk-c into reality.
mkc_imp.autotools.mk is needed for this.
- Alternative .depend generation, e.g. like it is described in GNU
make info files
@@ -52,20 +57,22 @@ Some thoughts inspired by talks with Michael Crogan
"meta mode" he invented.
- Better support for working without installation to /. -rpath, additional
directories for objects, binaries and libs.
+- symlinks in object directories to source files for easier running
+ unitest, for example. lndir(1).
Some "targets" from TARGETS should set MKCHECKS to "no"
ronn(1) : markdown to man pages
------------------------------------------
-gcc -L/usr/pkg/lib -R/usr/pkg/lib -o hello_lex hello_lex.o -ll
-yacc calc.y
-mv y.tab.c calc.c
-gcc -I/usr/pkg/include -c -o calc.o calc.c
-gcc -L/usr/pkg/lib -R/usr/pkg/lib -o hello_calc calc.o
-ERROR: cannot find program -y
-Cannot find bison, good bye!
-------------------------------------------
+ Reimplement linkme.mk. It is not flexible enough.
+ - Additional type of dependencies in mkc.subprjs.mk (LIBDEPS =
+ libfoo:bar ...), pass them to subprojects using enironment and
+ include appropriate libfoo/linkme.mk if it is
+ available. Otherwise, use default -l and -I.
+ or
+ - keep linkme.mk and avoid direct use of CPPFLAGS, LDADD and
+ DPLIBDIRS. Instead use special variables XXX.includes,
+ XXX.ldflags, XXX.ldadd, SRCDIR_<lib> and OBJDIR_<lib>.
custom test failed -> exit status of mkcmake should not be zero
MKC_CUSTOM_ERR.qqqq -> error message before exiting just like
@@ -81,8 +88,6 @@ Cannot find bison, good bye!
- BINSUBDIR, LIBSUBDIR, LIBEXECSUBDIR etc...
- Fix USE_SSP support for clang (-mllvm -stack-protector-buffer-size=1)
- @sysconfdir@/mkc.conf
- - LDFLAGS vs. LDFLAGS in link.me (global paths before project's)
- - Reimplement linkme.mk. It is not flexible enough.
- USE_RPATH
- OBJCOPTS_<proj>
- Regression tests:
@@ -112,14 +117,13 @@ Plan 2)
dynamic symbol table (GNU ld)
- EXPORT_SYMBOLS_REGEXP
- - recheck documentation for Makefile.rec
- Syllable, Haiku, OpenServer/UnixWare and HURD
- lcc and tcc compilers
- epm -> rpm, SVR4 pkg etc.
- mkc_imp.filelist.mk
- FL_NOPREFIX
- FL_PERSUBPRJ
- - IRIX: "endianess" and EXPORT_SYMBOLS
+ - IRIX: "endianness" and EXPORT_SYMBOLS
============================================================
Plan 3)
@@ -141,10 +145,6 @@ Plan 3)
Save defines to config.h and set HAVE_CONFIG_H to 1
for compiling.
- = MKC_NEED_FUNCLIBS - the same as MKC_SOURCE_FUNCLIBS but
- implementation is taken from mk-c.
- Ex: MKC_NEED_FUNCLIBS += strlcat strlcpy getline
-
= MKC_CUSTOM_premk, MKC_CUSTOM_postmk
= Online tutorial
@@ -153,7 +153,8 @@ Plan 3)
= shared libraries support for nwcc and other compilers.
= Comparison with quagmire, kBuild, CMake, scons, waf, framewerk, pmk,
- MagicMakefiles, bjam, pymake etc.
+ MagicMakefiles, bjam, pymake, bitmake, pkgconf,
+ http://sourceforge.net/projects/mkbuild etc.
= Often compilers need special options to compile pthread code.
Support for MKPTHREAD=yes|no is needed.
diff --git a/examples/Makefile b/examples/Makefile
deleted file mode 100644
index 0934f7b..0000000
--- a/examples/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-# for regression tests
-NOEXPORT_VARNAMES = MKC_CACHEDIR
-
-_THISDIR_ =
-.export _THISDIR_
-
-# examples
-SUBDIR+= hello_world
-SUBDIR+= hello_scripts
-SUBDIR+= hello_files
-SUBDIR+= hello_sizeof
-SUBDIR+= hello_lex
-SUBDIR+= hello_yacc
-SUBDIR+= hello_calc2
-SUBDIR+= subprojects
-SUBDIR+= hello_compilers
-SUBDIR+= hello_plugins
-SUBDIR+= hello_plugins2
-SUBDIR+= hello_glib2
-SUBDIR+= hello_subdirs
-SUBDIR+= hello_strlcpy
-SUBDIR+= hello_customtests
-SUBDIR+= hello_customtests2
-SUBDIR+= hello_requirements
-SUBDIR+= hello_cxx
-SUBDIR+= hello_cxxlib
-SUBDIR+= hello_dictd
-SUBDIR+= hello_lua
-SUBDIR+= hello_lua2
-SUBDIR+= hello_lua3
-SUBDIR+= hello_superfs
-SUBDIR+= hello_xxzip
-SUBDIR+= hello_progs
-SUBDIR+= hello_progs2
-SUBDIR+= tools
-SUBDIR+= tools2
-
-.ifdef WITH_require_tools
-SUBDIR+= hello_require_tools
-.endif
-
-.include <mkc.mk>
diff --git a/examples/Makefile.inc b/examples/Makefile.inc
index 32e2d30..eadc408 100644
--- a/examples/Makefile.inc
+++ b/examples/Makefile.inc
@@ -1 +1,10 @@
-CLEANDIRS+= ${.CURDIR}/usr ${.CURDIR}/opt
+CLEANDIRS += ${.CURDIR}/usr ${.CURDIR}/opt
+
+.ifdef SRCDIR_custom
+# regression test for mk-configure
+MKC_CACHEDIR = ${.CURDIR}
+BUILTINSDIR = ${SRCDIR_custom}
+FEATURESDIR = ${SRCDIR_features}
+SHRTOUT = no
+.export MKC_CACHEDIR BUILTINSDIR FEATURESDIR SHRTOUT
+.endif
diff --git a/examples/hello_RBTREE/Makefile b/examples/hello_RBTREE/Makefile
new file mode 100644
index 0000000..6b68c0b
--- /dev/null
+++ b/examples/hello_RBTREE/Makefile
@@ -0,0 +1,10 @@
+PROG = hello_RBTREE
+
+WARNS = 4
+
+MKC_FEATURES = RB
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/hello_RBTREE/expect.out b/examples/hello_RBTREE/expect.out
new file mode 100644
index 0000000..f130512
--- /dev/null
+++ b/examples/hello_RBTREE/expect.out
@@ -0,0 +1,7 @@
+NetBSD
+black currant
+blackberry
+cranberry
+gooseberry
+red currant
+strawberry
diff --git a/examples/hello_RBTREE/hello_RBTREE.c b/examples/hello_RBTREE/hello_RBTREE.c
new file mode 100644
index 0000000..bfcf96b
--- /dev/null
+++ b/examples/hello_RBTREE/hello_RBTREE.c
@@ -0,0 +1,82 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <mkc_RB.h>
+
+struct berry {
+ RB_ENTRY(berry) link;
+ char *berry;
+};
+
+static int berrys_cmp (struct berry *a, struct berry *b)
+{
+ return strcmp (a->berry, b->berry);
+}
+
+static RB_HEAD (berrys_entries, berry) berrys = RB_INITIALIZER(&berrys);
+RB_PROTOTYPE (berrys_entries, berry, link, berrys_cmp);
+RB_GENERATE (berrys_entries, berry, link, berrys_cmp);
+
+static void output_berries (void)
+{
+ struct berry *data;
+ data = (struct berry *) RB_MIN (berrys_entries, &berrys);
+ while (data){
+ puts (data->berry);
+ data = (struct berry *) RB_NEXT (berrys_entries, &berrys, data);
+ }
+}
+
+static void destroy_berries (void)
+{
+ struct berry *data, *next;
+ data = (struct berry *) RB_MIN (berrys_entries, &berrys);
+ while (data){
+ next = (struct berry *) RB_NEXT (berrys_entries, &berrys, data);
+ RB_REMOVE (berrys_entries, &berrys, data);
+ free (data->berry);
+ free (data);
+
+ data = next;
+ }
+}
+
+static void add_berry (char *s)
+{
+ struct berry *n = malloc (sizeof (*n));
+ struct berry *data;
+
+ n->berry = s;
+
+ data = RB_INSERT (berrys_entries, &berrys, n);
+ if (data){
+ free (s);
+ free (n);
+ }
+}
+
+int main (int argc, char **argv)
+{
+ char buf [100];
+ size_t len;
+
+ while (fgets (buf, sizeof (buf), stdin)){
+ len = strlen (buf);
+ if (len > 0 && buf [len-1] == '\n')
+ buf [len-1] = 0;
+
+ add_berry (strdup (buf));
+ }
+
+ output_berries ();
+ destroy_berries ();
+
+ return 0;
+}
diff --git a/examples/hello_RBTREE/input.in b/examples/hello_RBTREE/input.in
new file mode 100644
index 0000000..1b03e8f
--- /dev/null
+++ b/examples/hello_RBTREE/input.in
@@ -0,0 +1,12 @@
+cranberry
+gooseberry
+strawberry
+strawberry
+blackberry
+black currant
+red currant
+NetBSD
+strawberry
+black currant
+red currant
+cranberry
diff --git a/examples/hello_RBTREE/test.mk b/examples/hello_RBTREE/test.mk
new file mode 100644
index 0000000..5188245
--- /dev/null
+++ b/examples/hello_RBTREE/test.mk
@@ -0,0 +1,8 @@
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/hello_RBTREE < ${.CURDIR}/input.in; \
+ \
+ ${MAKE} ${MAKEFLAGS} distclean > /dev/null
+
+.include <mkc.minitest.mk>
diff --git a/examples/hello_SLIST/Makefile b/examples/hello_SLIST/Makefile
new file mode 100644
index 0000000..313db26
--- /dev/null
+++ b/examples/hello_SLIST/Makefile
@@ -0,0 +1,10 @@
+PROG = hello_SLIST
+
+WARNS = 4
+
+MKC_FEATURES = SLIST
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/hello_SLIST/expect.out b/examples/hello_SLIST/expect.out
new file mode 100644
index 0000000..663f7ca
--- /dev/null
+++ b/examples/hello_SLIST/expect.out
@@ -0,0 +1,7 @@
+red currant
+black currant
+blackberry
+strawberry
+gooseberry
+cranberry
+raspberry
diff --git a/examples/hello_SLIST/hello_SLIST.c b/examples/hello_SLIST/hello_SLIST.c
new file mode 100644
index 0000000..7272f65
--- /dev/null
+++ b/examples/hello_SLIST/hello_SLIST.c
@@ -0,0 +1,66 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <mkc_SLIST.h>
+
+struct berry {
+ SLIST_ENTRY(berry) link;
+ char *berry;
+};
+
+static SLIST_HEAD (berry_head, berry) berries = SLIST_HEAD_INITIALIZER(berry_head);
+
+static void output_berries (void)
+{
+ struct berry *p;
+
+ SLIST_FOREACH (p, &berries, link){
+ puts (p->berry);
+ }
+}
+
+static void destroy_berries (void)
+{
+ struct berry *e;
+ while (!SLIST_EMPTY (&berries)){
+ e = SLIST_FIRST (&berries);
+ free (e->berry);
+ SLIST_REMOVE_HEAD (&berries, link);
+ free (e);
+ }
+}
+
+static void add_berry (char *s)
+{
+ struct berry *b = calloc (1, sizeof (*b));
+
+ b->berry = s;
+
+ SLIST_INSERT_HEAD (&berries, b, link);
+}
+
+int main (int argc, char **argv)
+{
+ char buf [100];
+ size_t len;
+
+ while (fgets (buf, sizeof (buf), stdin)){
+ len = strlen (buf);
+ if (len > 0 && buf [len-1] == '\n')
+ buf [len-1] = 0;
+
+ add_berry (strdup (buf));
+ }
+
+ output_berries ();
+ destroy_berries ();
+
+ return 0;
+}
diff --git a/examples/hello_SLIST/input.in b/examples/hello_SLIST/input.in
new file mode 100644
index 0000000..39fcf95
--- /dev/null
+++ b/examples/hello_SLIST/input.in
@@ -0,0 +1,7 @@
+raspberry
+cranberry
+gooseberry
+strawberry
+blackberry
+black currant
+red currant
diff --git a/examples/hello_SLIST/test.mk b/examples/hello_SLIST/test.mk
new file mode 100644
index 0000000..b7ca05d
--- /dev/null
+++ b/examples/hello_SLIST/test.mk
@@ -0,0 +1,8 @@
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/hello_SLIST < ${.CURDIR}/input.in; \
+ \
+ ${MAKE} ${MAKEFLAGS} distclean > /dev/null
+
+.include <mkc.minitest.mk>
diff --git a/examples/hello_calc2/Makefile b/examples/hello_calc2/Makefile
index c425b22..8005614 100644
--- a/examples/hello_calc2/Makefile
+++ b/examples/hello_calc2/Makefile
@@ -9,14 +9,16 @@ LPREFIX = calc_
MKC_CHECK_BUILTINS = prog_bison prog_flex
-YACC = ${BUILTIN.prog_bison} -y
-LEX = ${BUILTIN.prog_flex}
-LEXLIB = -lfl
+MKC_FEATURES += libm
lex.o: parser.h
.include <mkc.configure.mk>
+YACC = ${"${BUILTIN.prog_bison}" != "":?${BUILTIN.prog_bison} -y:}
+LEX = ${BUILTIN.prog_flex}
+LEXLIB = -lfl
+
.if empty(BUILTIN.prog_flex)
MKC_ERR_MSG += "Cannot find flex, good bye!"
.endif
@@ -25,7 +27,5 @@ MKC_ERR_MSG += "Cannot find flex, good bye!"
MKC_ERR_MSG += "Cannot find bison, good bye!"
.endif
-LDADD += -lm
-
.include "test.mk"
.include <mkc.prog.mk>
diff --git a/examples/hello_calc2/expect.out b/examples/hello_calc2/expect.out
index d98c36f..9c780e8 100644
--- a/examples/hello_calc2/expect.out
+++ b/examples/hello_calc2/expect.out
@@ -14,6 +14,12 @@
/objdir/_mkc_custom_prog_bison.res
/objdir/_mkc_custom_prog_flex.err
/objdir/_mkc_custom_prog_flex.res
+/objdir/_mkc_funclib_sqrt.c
+/objdir/_mkc_funclib_sqrt.err
+/objdir/_mkc_funclib_sqrt.res
+/objdir/_mkc_funclib_sqrt_m.c
+/objdir/_mkc_funclib_sqrt_m.err
+/objdir/_mkc_funclib_sqrt_m.res
/objdir/_mkc_prog_cc.err
/objdir/_mkc_prog_cc.res
/objdir/calc
@@ -41,6 +47,12 @@
/objdir/_mkc_custom_prog_bison.res
/objdir/_mkc_custom_prog_flex.err
/objdir/_mkc_custom_prog_flex.res
+/objdir/_mkc_funclib_sqrt.c
+/objdir/_mkc_funclib_sqrt.err
+/objdir/_mkc_funclib_sqrt.res
+/objdir/_mkc_funclib_sqrt_m.c
+/objdir/_mkc_funclib_sqrt_m.err
+/objdir/_mkc_funclib_sqrt_m.res
/objdir/_mkc_prog_cc.err
/objdir/_mkc_prog_cc.res
/objdir/expect.out
@@ -58,6 +70,12 @@
/objdir/_mkc_custom_prog_bison.res
/objdir/_mkc_custom_prog_flex.err
/objdir/_mkc_custom_prog_flex.res
+/objdir/_mkc_funclib_sqrt.c
+/objdir/_mkc_funclib_sqrt.err
+/objdir/_mkc_funclib_sqrt.res
+/objdir/_mkc_funclib_sqrt_m.c
+/objdir/_mkc_funclib_sqrt_m.err
+/objdir/_mkc_funclib_sqrt_m.res
/objdir/_mkc_prog_cc.err
/objdir/_mkc_prog_cc.res
/objdir/expect.out
diff --git a/examples/hello_calc2/parser.y b/examples/hello_calc2/parser.y
index 67bef50..7837b25 100644
--- a/examples/hello_calc2/parser.y
+++ b/examples/hello_calc2/parser.y
@@ -1,7 +1,7 @@
%{
#include <stdio.h>
-#include <math.h>
+#include <mkc_libm.h>
%}
%union {
diff --git a/examples/hello_customtests/Makefile b/examples/hello_customtests/Makefile
index 169bbad..8bba131 100644
--- a/examples/hello_customtests/Makefile
+++ b/examples/hello_customtests/Makefile
@@ -14,14 +14,14 @@ MKC_CUSTOM_FN.cxx_with_templates = custom_tests/cxx_with_templates.cc
MKC_CUSTOM_FN.true_is_available = custom_tests/true_is_available
MKC_CUSTOM_FN.shtest = custom_tests/shtest
-MKC_CHECK_BUILTINS += endianess
+MKC_CHECK_BUILTINS += endianness
MKC_REQD = 0.12.0
.include <mkc.configure.mk>
-BUILTIN.endianess ?=
-.if ${BUILTIN.endianess} != little && ${BUILTIN.endianess} != big
+BUILTIN.endianness ?=
+.if ${BUILTIN.endianness} != little && ${BUILTIN.endianness} != big
MKC_ERR_MSG = "Do you run PDP-11?"
.endif
diff --git a/examples/hello_customtests/expect.out b/examples/hello_customtests/expect.out
index bcf94d9..5ff71f7 100644
--- a/examples/hello_customtests/expect.out
+++ b/examples/hello_customtests/expect.out
@@ -8,8 +8,8 @@
/objdir/_mkc_custom_alloca_in_stdlib_h.res
/objdir/_mkc_custom_cxx_with_templates.err
/objdir/_mkc_custom_cxx_with_templates.res
-/objdir/_mkc_custom_endianess.err
-/objdir/_mkc_custom_endianess.res
+/objdir/_mkc_custom_endianness.err
+/objdir/_mkc_custom_endianness.res
/objdir/_mkc_custom_shtest.err
/objdir/_mkc_custom_shtest.res
/objdir/_mkc_custom_true_is_available.err
@@ -47,8 +47,8 @@ shtest is good: NO
/objdir/_mkc_custom_alloca_in_stdlib_h.res
/objdir/_mkc_custom_cxx_with_templates.err
/objdir/_mkc_custom_cxx_with_templates.res
-/objdir/_mkc_custom_endianess.err
-/objdir/_mkc_custom_endianess.res
+/objdir/_mkc_custom_endianness.err
+/objdir/_mkc_custom_endianness.res
/objdir/_mkc_custom_shtest.err
/objdir/_mkc_custom_shtest.res
/objdir/_mkc_custom_true_is_available.err
diff --git a/examples/hello_customtests/test.mk b/examples/hello_customtests/test.mk
index adfedf7..ba5e27c 100644
--- a/examples/hello_customtests/test.mk
+++ b/examples/hello_customtests/test.mk
@@ -31,7 +31,9 @@ test_output:
\
echo ======= errorcheck + MAKEOBJDIR ===========; \
mkdir ${.CURDIR}/testdir || true; \
- ${MAKE} ${MAKEFLAGS} errorcheck MAKEOBJDIR=${.CURDIR}/testdir > /dev/null; \
+ ${MAKE} ${MAKEFLAGS} errorcheck \
+ MKC_CACHEDIR=${.CURDIR}/testdir \
+ MAKEOBJDIR=${.CURDIR}/testdir > /dev/null; \
printf 'true_is_available=%s\n' `cat ${.CURDIR}/testdir/_mkc_custom_true_is_available.res`; \
\
echo ======= distclean ==========; \
diff --git a/examples/hello_customtests2/test.mk b/examples/hello_customtests2/test.mk
index b3ce488..3a6bf21 100644
--- a/examples/hello_customtests2/test.mk
+++ b/examples/hello_customtests2/test.mk
@@ -31,7 +31,9 @@ test_output:
\
echo ======= errorcheck + MAKEOBJDIR ===========; \
mkdir ${.CURDIR}/testdir || true; \
- ${MAKE} ${MAKEFLAGS} errorcheck MAKEOBJDIR=${.CURDIR}/testdir > /dev/null; \
+ ${MAKE} ${MAKEFLAGS} errorcheck \
+ MKC_CACHEDIR=${.CURDIR}/testdir \
+ MAKEOBJDIR=${.CURDIR}/testdir > /dev/null; \
printf 'true_is_available=%s\n' `cat ${.CURDIR}/testdir/_mkc_custom_true_is_available.res`; \
\
echo ======= distclean ==========; \
diff --git a/examples/hello_cxxlib/cxxlib/linkme.mk b/examples/hello_cxxlib/cxxlib/linkme.mk
index 8b9206e..85b9277 100644
--- a/examples/hello_cxxlib/cxxlib/linkme.mk
+++ b/examples/hello_cxxlib/cxxlib/linkme.mk
@@ -2,4 +2,4 @@ PATH.cxxlib := ${.PARSEDIR}
CPPFLAGS += -I${PATH.cxxlib}/include
DPLIBDIRS += ${PATH.cxxlib}
-LDADD += -lcxxlib
+LDADD0 += -lcxxlib
diff --git a/examples/hello_dictd/expect.out b/examples/hello_dictd/expect.out
index cbed363..462d425 100644
--- a/examples/hello_dictd/expect.out
+++ b/examples/hello_dictd/expect.out
@@ -656,15 +656,6 @@ obj1 does not exist
/objdir/Makefile.inc
/objdir/_mkc_compiler_type.err
/objdir/_mkc_compiler_type.res
-/objdir/_mkc_funclib_deflate.c
-/objdir/_mkc_funclib_deflate.err
-/objdir/_mkc_funclib_deflate.res
-/objdir/_mkc_funclib_deflate_z.c
-/objdir/_mkc_funclib_deflate_z.err
-/objdir/_mkc_funclib_deflate_z.res
-/objdir/_mkc_header_zlib_h.c
-/objdir/_mkc_header_zlib_h.err
-/objdir/_mkc_header_zlib_h.res
/objdir/_mkc_prog_cc.err
/objdir/_mkc_prog_cc.res
/objdir/dict/Makefile
@@ -698,13 +689,7 @@ obj1 does not exist
/objdir/libcommon/str.o
/objdir/libdz/Makefile
/objdir/libdz/dz.c
-/objdir/libdz/dz.o
-/objdir/libdz/dz.os
/objdir/libdz/export.sym
-/objdir/libdz/libdz.a
-/objdir/libdz/libdz.so
-/objdir/libdz/libdz.so.1
-/objdir/libdz/libdz.so.1.0
/objdir/libdz/linkme.mk
/objdir/libmaa/Makefile
/objdir/libmaa/export.sym
@@ -723,3 +708,145 @@ obj1 does not exist
/objdir/libmaa/set.o
/objdir/libmaa/set.os
/objdir/test.mk
+=========== print_deps ============
+all-libcommon all-dict
+all-libcommon all-dictd
+all-libcommon all-dictzip
+all-libcommon all-dictfmt
+all-libmaa all-dict
+all-libmaa all-dictd
+all-libmaa all-dictzip
+all-libmaa all-dictfmt
+all-libdz all-dictzip
+test-libcommon test-dict
+test-libcommon test-dictd
+test-libcommon test-dictzip
+test-libcommon test-dictfmt
+test-libmaa test-dict
+test-libmaa test-dictd
+test-libmaa test-dictzip
+test-libmaa test-dictfmt
+test-libdz test-dictzip
+all-dict dict
+all-dictd dictd
+all-dictfmt dictfmt
+all-dictzip dictzip
+all-doc doc
+all-libcommon libcommon
+all-libdz libdz
+all-libmaa libmaa
+all-dict all
+all-dictd all
+all-dictzip all
+all-dictfmt all
+all-dict
+all-dictd
+all-dictfmt
+all-dictzip
+all-doc
+all-libcommon
+all-libdz
+all-libmaa
+test-dict
+test-dictd
+test-dictfmt
+test-dictzip
+test-doc
+test-libcommon
+test-libdz
+test-libmaa
+all
+test
+=====
+all-libcommon all-dict
+all-libcommon all-dictd
+all-libmaa all-dict
+all-libmaa all-dictd
+test-libcommon test-dict
+test-libcommon test-dictd
+test-libmaa test-dict
+test-libmaa test-dictd
+all-dict dict
+all-dictd dictd
+all-doc doc
+all-libcommon libcommon
+all-libdz libdz
+all-libmaa libmaa
+all-dict all
+all-dictd all
+all-dict
+all-dictd
+all-doc
+all-libcommon
+all-libdz
+all-libmaa
+test-dict
+test-dictd
+test-doc
+test-libcommon
+test-libdz
+test-libmaa
+all
+test
+=====
+all-libcommon all-dict
+all-libcommon all-dictd
+all-libcommon all-dictzip
+all-libcommon all-dictfmt
+all-libmaa all-dict
+all-libmaa all-dictd
+all-libmaa all-dictzip
+all-libmaa all-dictfmt
+all-libdz all-dictzip
+test-libcommon test-dict
+test-libcommon test-dictd
+test-libcommon test-dictzip
+test-libcommon test-dictfmt
+test-libmaa test-dict
+test-libmaa test-dictd
+test-libmaa test-dictzip
+test-libmaa test-dictfmt
+test-libdz test-dictzip
+all-dict dict
+all-dictd dictd
+all-dictfmt dictfmt
+all-dictzip dictzip
+all-doc doc
+all-libcommon libcommon
+all-libdz libdz
+all-libmaa libmaa
+all-dict all
+all-dictd all
+all-dictzip all
+all-dictfmt all
+test2-dict test2
+test2-dictd test2
+test2-dictzip test2
+test2-dictfmt test2
+all-dict
+all-dictd
+all-dictfmt
+all-dictzip
+all-doc
+all-libcommon
+all-libdz
+all-libmaa
+test-dict
+test-dictd
+test-dictfmt
+test-dictzip
+test-doc
+test-libcommon
+test-libdz
+test-libmaa
+test2-dict
+test2-dictd
+test2-dictfmt
+test2-dictzip
+test2-doc
+test2-libcommon
+test2-libdz
+test2-libmaa
+all
+test
+test2
diff --git a/examples/hello_dictd/libcommon/linkme.mk b/examples/hello_dictd/libcommon/linkme.mk
index d574ea8..84c543c 100644
--- a/examples/hello_dictd/libcommon/linkme.mk
+++ b/examples/hello_dictd/libcommon/linkme.mk
@@ -2,4 +2,4 @@ PATH.common := ${.PARSEDIR}
CPPFLAGS += -I${PATH.common}
DPLIBDIRS += ${PATH.common}
-LDADD += -lcommon
+LDADD0 += -lcommon
diff --git a/examples/hello_dictd/libdz/linkme.mk b/examples/hello_dictd/libdz/linkme.mk
index 44bbeb5..5904614 100644
--- a/examples/hello_dictd/libdz/linkme.mk
+++ b/examples/hello_dictd/libdz/linkme.mk
@@ -2,4 +2,4 @@ PATH.dz := ${.PARSEDIR}
CPPFLAGS += -I${PATH.dz}
DPLIBDIRS += ${PATH.dz}
-LDADD += -ldz
+LDADD0 += -ldz
diff --git a/examples/hello_dictd/libmaa/linkme.mk b/examples/hello_dictd/libmaa/linkme.mk
index f2b6180..9d1456e 100644
--- a/examples/hello_dictd/libmaa/linkme.mk
+++ b/examples/hello_dictd/libmaa/linkme.mk
@@ -2,4 +2,4 @@ PATH.maa := ${.PARSEDIR}
CPPFLAGS += -I${PATH.maa}
DPLIBDIRS += ${PATH.maa}
-LDADD += -lmaa
+LDADD0 += -lmaa
diff --git a/examples/hello_dictd/test.mk b/examples/hello_dictd/test.mk
index 1dd3944..0ccfb4e 100644
--- a/examples/hello_dictd/test.mk
+++ b/examples/hello_dictd/test.mk
@@ -17,12 +17,15 @@ test_output :
\
echo =========== nm ============; \
case ${OPSYS} in \
- *BSD|Linux) \
- ${NM} ${.CURDIR}/libmaa/libmaa*.so | awk '$$2 == "T" {print "libmaa " $$3}'; \
- ${NM} ${.CURDIR}/libdz/libdz*.so | awk '$$2 == "T" {print "libdz " $$3}';; \
- SunOS) \
- ${NM} -P ${.CURDIR}/libmaa/libmaa*.so | awk '$$2 == "T" {print "libmaa " $$1}'; \
- ${NM} -P ${.CURDIR}/libdz/libdz*.so | awk '$$2 == "T" {print "libdz " $$1}';; \
+ OpenBSD) \
+ ${NM} ${.CURDIR}/libmaa/libmaa*.so | awk '$$2=="T" {print "libmaa " $$3}'; \
+ ${NM} ${.CURDIR}/libdz/libdz*.so | awk '$$2=="T" {print "libdz " $$3}';; \
+ *BSD|SunOS|DragonFly) \
+ ${NM} -P ${.CURDIR}/libmaa/libmaa*.so | awk 'NF==4 && $$2=="T" {print "libmaa " $$1}'; \
+ ${NM} -P ${.CURDIR}/libdz/libdz*.so | awk 'NF==4 && $$2=="T" {print "libdz " $$1}';; \
+ Linux) \
+ ${NM} -P ${.CURDIR}/libmaa/libmaa*.so | awk 'NF==4 && $$2 ~ /^[DT]$$/ {print "libmaa " $$1}'; \
+ ${NM} -P ${.CURDIR}/libdz/libdz*.so | awk 'NF==4 && $$2 ~ /^[DT]$$/ {print "libdz " $$1}';; \
*) \
printf 'libmaa fake4\nlibmaa fake5\nlibmaa fake6\nlibdz fake3\n';; \
esac; \
@@ -163,6 +166,16 @@ test_output :
${MAKE} ${MAKEFLAGS} -j4 all > /dev/null; \
find ${.OBJDIR} -type f -o -type l | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ unset NOSUBDIR; \
+ \
+ echo =========== print_deps ============; \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E '^(all|test)'; \
+ echo =====; \
+ NOSUBDIR='dictfmt dictzip' \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E '^(all|test)'; \
+ echo =====; \
+ NODEPS='test2-*:test2-dict*' TARGETS=test2 \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E '^(all|test)'; \
\
true =========== cleandir ============; \
unset NOSUBDIR || true; \
diff --git a/examples/hello_files/test.mk b/examples/hello_files/test.mk
index c354e53..8764c4b 100644
--- a/examples/hello_files/test.mk
+++ b/examples/hello_files/test.mk
@@ -45,7 +45,7 @@ test_output:
\
echo ==== SHRTOUT=yes ====; \
${MAKE} ${MAKEFLAGS} distclean > /dev/null; \
- env MKCATPAGES=no MKHTML=no SHRTOUT=yes ${MAKE} ${MAKEFLAGS} all 2>&1 |\
+ env MKCATPAGES=no MKHTML=no ${MAKE} ${MAKEFLAGS} SHRTOUT=yes all 2>&1 |\
mkc_test_helper2; \
\
true ======= distclean ==========; \
diff --git a/examples/hello_iconv/Makefile b/examples/hello_iconv/Makefile
new file mode 100644
index 0000000..cd00ecf
--- /dev/null
+++ b/examples/hello_iconv/Makefile
@@ -0,0 +1,18 @@
+MKC_CHECK_PROTOTYPES = posix_iconv const_iconv
+
+MKC_PROTOTYPE_FUNC.posix_iconv = \
+ size_t iconv (iconv_t, char **, size_t *, char **, size_t *)
+MKC_PROTOTYPE_FUNC.const_iconv = \
+ size_t iconv (iconv_t, const char **, size_t *, char **, size_t *)
+
+MKC_PROTOTYPE_HEADERS.posix_iconv = iconv.h
+MKC_PROTOTYPE_HEADERS.const_iconv = iconv.h
+
+PROG = hello_iconv
+
+WARNS = 4
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/hello_iconv/expect.out b/examples/hello_iconv/expect.out
new file mode 100644
index 0000000..99878b4
--- /dev/null
+++ b/examples/hello_iconv/expect.out
@@ -0,0 +1 @@
+Your iconv(3) is ok
diff --git a/examples/hello_iconv/hello_iconv.c b/examples/hello_iconv/hello_iconv.c
new file mode 100644
index 0000000..b467c75
--- /dev/null
+++ b/examples/hello_iconv/hello_iconv.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+int main (int argc, char ** argv)
+{
+ static char compat [] =
+#ifdef HAVE_PROTOTYPE_POSIX_ICONV
+ "compatible";
+#elif defined(HAVE_PROTOTYPE_CONST_ICONV)
+ "incompatible";
+#else
+ "???";
+#endif
+
+ printf ("Your iconv(3) is %s with POSIX\n", compat);
+
+#if defined(HAVE_PROTOTYPE_POSIX_ICONV) && defined(HAVE_PROTOTYPE_CONST_ICONV)
+ puts ("Buggy mk-configure!");
+#endif
+
+ return 0;
+}
diff --git a/examples/hello_iconv/test.mk b/examples/hello_iconv/test.mk
new file mode 100644
index 0000000..e796fef
--- /dev/null
+++ b/examples/hello_iconv/test.mk
@@ -0,0 +1,7 @@
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/hello_iconv | sed 's/i*n*compatible.*$$/ok/'; \
+ ${MAKE} ${MAKEFLAGS} cleandir > /dev/null 2>&1
+
+.include <mkc.minitest.mk>
diff --git a/examples/hello_lex/test.mk b/examples/hello_lex/test.mk
index 53acf8e..004c313 100644
--- a/examples/hello_lex/test.mk
+++ b/examples/hello_lex/test.mk
@@ -33,12 +33,12 @@ test_output:
\
echo ==== SHRTOUT=yes depend ====; \
${MAKE} ${MAKEFLAGS} distclean > /dev/null; \
- env SHRTOUT=yes ${MAKE} ${MAKEFLAGS} depend 2>&1 |\
+ env ${MAKE} ${MAKEFLAGS} SHRTOUT=yes depend 2>&1 |\
mkc_test_helper2; \
\
echo ==== SHRTOUT=yes all ====; \
${MAKE} ${MAKEFLAGS} clean > /dev/null; \
- env MKCATPAGES=no MKHTML=no SHRTOUT=yes ${MAKE} ${MAKEFLAGS} all 2>&1 |\
+ env MKCATPAGES=no MKHTML=no ${MAKE} ${MAKEFLAGS} all SHRTOUT=yes 2>&1 |\
mkc_test_helper2; \
find ${.OBJDIR} -type f | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}";\
diff --git a/examples/hello_plugins2/app/Makefile b/examples/hello_plugins2/app/Makefile
index 728d04a..772b965 100644
--- a/examples/hello_plugins2/app/Makefile
+++ b/examples/hello_plugins2/app/Makefile
@@ -1,9 +1,7 @@
-MKC_REQUIRE_FUNCLIBS += dlopen:dl
-
-PROG = app
-
+PROG = app
WARNS = 4
-EXPORT_DYNAMIC = yes
+MKC_FEATURES += libdl
+EXPORT_DYNAMIC = yes
.include <mkc.prog.mk>
diff --git a/examples/hello_plugins2/expect.out b/examples/hello_plugins2/expect.out
index 6ae1873..67dfd9e 100644
--- a/examples/hello_plugins2/expect.out
+++ b/examples/hello_plugins2/expect.out
@@ -4,6 +4,9 @@ Plugin2 sucessfully activated
/objdir/Makefile
/objdir/_mkc_compiler_type.err
/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func2_dlopen_dlfcn_h.c
+/objdir/_mkc_func2_dlopen_dlfcn_h.err
+/objdir/_mkc_func2_dlopen_dlfcn_h.res
/objdir/_mkc_funclib_dlopen.c
/objdir/_mkc_funclib_dlopen.err
/objdir/_mkc_funclib_dlopen.res
@@ -39,6 +42,9 @@ Plugin2 sucessfully activated
/objdir/Makefile
/objdir/_mkc_compiler_type.err
/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func2_dlopen_dlfcn_h.c
+/objdir/_mkc_func2_dlopen_dlfcn_h.err
+/objdir/_mkc_func2_dlopen_dlfcn_h.res
/objdir/_mkc_funclib_dlopen.c
/objdir/_mkc_funclib_dlopen.err
/objdir/_mkc_funclib_dlopen.res
diff --git a/examples/hello_strlcpy/getline.c b/examples/hello_strlcpy/getline.c
index 777f5c4..8e42c75 100644
--- a/examples/hello_strlcpy/getline.c
+++ b/examples/hello_strlcpy/getline.c
@@ -1,13 +1,31 @@
/*
- * Copyright (c) 2007-2013 by Aleksey Cheusov
+ * Copyright (c) 2007-2013 Aleksey Cheusov <vle@gmx.net>
*
- * See LICENSE file in the distribution.
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
-#include "decls.h"
+ssize_t
+getline(char** lineptr, size_t* n, FILE* stream);
ssize_t
getline(char** lineptr, size_t* n, FILE* stream)
@@ -29,11 +47,11 @@ getline(char** lineptr, size_t* n, FILE* stream)
break;
}
- if (ferror (stdin))
+ if (ferror (stream))
return (ssize_t) -1;
if (!sz){
- if (feof (stdin)){
+ if (feof (stream)){
return (ssize_t) -1;
}else if (!*n){
*lineptr = malloc (1);
diff --git a/examples/hello_strlcpy/hello.c b/examples/hello_strlcpy/hello.c
index 177b6b5..1ec6315 100644
--- a/examples/hello_strlcpy/hello.c
+++ b/examples/hello_strlcpy/hello.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#ifndef HAVE_FUNC3_STRLCPY_STRING_H
size_t strlcpy(char *dst, const char *src, size_t siz);
diff --git a/examples/hello_strlcpy2/Makefile b/examples/hello_strlcpy2/Makefile
new file mode 100644
index 0000000..76e332b
--- /dev/null
+++ b/examples/hello_strlcpy2/Makefile
@@ -0,0 +1,13 @@
+MKC_SOURCE_FUNCLIBS = strlcpy getline
+MKC_CHECK_FUNCS3 += strlcpy:string.h getline:stdio.h
+MKC_SOURCE_DIR = ${.CURDIR}/missing
+
+PROG = hello
+SRCS = hello.c
+
+WARNS = 4
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/hello_strlcpy2/expect.out b/examples/hello_strlcpy2/expect.out
new file mode 100644
index 0000000..8ca6686
--- /dev/null
+++ b/examples/hello_strlcpy2/expect.out
@@ -0,0 +1,93 @@
+# Copyrig
+# All rig
+#
+# Redistr
+# modific
+# are met
+# 1. Redi
+# noti
+# 2. Redi
+# noti
+# docu
+#
+# THIS SO
+# ``AS IS
+# TO, THE
+# PURPOSE
+# BE LIAB
+# CONSEQU
+# SUBSTIT
+# INTERRU
+# CONTRAC
+# ARISING
+# POSSIBI
+=========== all ============
+/objdir/Makefile
+/objdir/_mkc_compiler_type.err
+/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func3_getline_stdio_h.c
+/objdir/_mkc_func3_getline_stdio_h.err
+/objdir/_mkc_func3_getline_stdio_h.res
+/objdir/_mkc_func3_strlcpy_string_h.c
+/objdir/_mkc_func3_strlcpy_string_h.err
+/objdir/_mkc_func3_strlcpy_string_h.res
+/objdir/_mkc_funclib_getline.c
+/objdir/_mkc_funclib_getline.err
+/objdir/_mkc_funclib_getline.res
+/objdir/_mkc_funclib_strlcpy.c
+/objdir/_mkc_funclib_strlcpy.err
+/objdir/_mkc_funclib_strlcpy.res
+/objdir/_mkc_prog_cc.err
+/objdir/_mkc_prog_cc.res
+/objdir/expect.out
+/objdir/hello
+/objdir/hello.c
+/objdir/hello.o
+/objdir/hello_strlcpy2.test.out.tmp
+/objdir/input.in
+/objdir/missing/getline.c
+/objdir/missing/strlcpy.c
+/objdir/test.mk
+========= install ==========
+/objdir/prefix
+/objdir/prefix/bin
+/objdir/prefix/bin/hello
+======== uninstall =========
+========== clean ===========
+/objdir/Makefile
+/objdir/_mkc_compiler_type.err
+/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func3_getline_stdio_h.c
+/objdir/_mkc_func3_getline_stdio_h.err
+/objdir/_mkc_func3_getline_stdio_h.res
+/objdir/_mkc_func3_strlcpy_string_h.c
+/objdir/_mkc_func3_strlcpy_string_h.err
+/objdir/_mkc_func3_strlcpy_string_h.res
+/objdir/_mkc_funclib_getline.c
+/objdir/_mkc_funclib_getline.err
+/objdir/_mkc_funclib_getline.res
+/objdir/_mkc_funclib_strlcpy.c
+/objdir/_mkc_funclib_strlcpy.err
+/objdir/_mkc_funclib_strlcpy.res
+/objdir/_mkc_prog_cc.err
+/objdir/_mkc_prog_cc.res
+/objdir/expect.out
+/objdir/hello.c
+/objdir/hello_strlcpy2.test.out.tmp
+/objdir/input.in
+/objdir/missing/getline.c
+/objdir/missing/strlcpy.c
+/objdir/test.mk
+======= distclean ==========
+/objdir/Makefile
+/objdir/expect.out
+/objdir/hello.c
+/objdir/hello_strlcpy2.test.out.tmp
+/objdir/input.in
+/objdir/missing/getline.c
+/objdir/missing/strlcpy.c
+/objdir/test.mk
+======= CLEANFILES ==========
+strlcpy.o
+getline.o
+hello.o
diff --git a/examples/hello_strlcpy2/hello.c b/examples/hello_strlcpy2/hello.c
new file mode 100644
index 0000000..1ec6315
--- /dev/null
+++ b/examples/hello_strlcpy2/hello.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef HAVE_FUNC3_STRLCPY_STRING_H
+size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+#ifndef HAVE_FUNC3_GETLINE_STDIO_H
+ssize_t getline(char** lineptr, size_t* n, FILE* stream);
+#endif
+
+int main (int argc, char ** argv)
+{
+ char *buf = NULL;
+ size_t size = 0;
+ ssize_t len = 0;
+ char small_buf [10];
+
+ while (len = getline (&buf, &size, stdin), len != -1){
+ len = strlen (buf);
+ if (len > 0 && buf [len-1] == '\n')
+ buf [len-1] = 0;
+
+ strlcpy (small_buf, buf, sizeof (small_buf));
+ puts (small_buf);
+ }
+
+ return 0;
+}
diff --git a/examples/hello_strlcpy2/input.in b/examples/hello_strlcpy2/input.in
new file mode 100644
index 0000000..a5a6836
--- /dev/null
+++ b/examples/hello_strlcpy2/input.in
@@ -0,0 +1,23 @@
+# Copyright (c) 2009, Aleksey Cheusov <vle@gmx.net>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
diff --git a/examples/hello_strlcpy2/missing/getline.c b/examples/hello_strlcpy2/missing/getline.c
new file mode 100644
index 0000000..8e42c75
--- /dev/null
+++ b/examples/hello_strlcpy2/missing/getline.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007-2013 Aleksey Cheusov <vle@gmx.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+ssize_t
+getline(char** lineptr, size_t* n, FILE* stream);
+
+ssize_t
+getline(char** lineptr, size_t* n, FILE* stream)
+{
+ int c;
+ size_t sz = 0;
+
+ while (c = getc (stream), c != EOF){
+ if (sz+1 >= *n){
+ /* +2 is for `c' and 0-terminator */
+ *n = *n * 3 / 2 + 2;
+ *lineptr = realloc (*lineptr, *n);
+ if (!*lineptr)
+ return -1;
+ }
+
+ (*lineptr) [sz++] = (char) c;
+ if (c == '\n')
+ break;
+ }
+
+ if (ferror (stream))
+ return (ssize_t) -1;
+
+ if (!sz){
+ if (feof (stream)){
+ return (ssize_t) -1;
+ }else if (!*n){
+ *lineptr = malloc (1);
+ if (!*lineptr)
+ return -1;
+
+ *n = 1;
+ }
+ }
+
+ (*lineptr) [sz] = 0;
+ return sz;
+}
diff --git a/examples/hello_strlcpy2/missing/strlcpy.c b/examples/hello_strlcpy2/missing/strlcpy.c
new file mode 100644
index 0000000..c7f1fbb
--- /dev/null
+++ b/examples/hello_strlcpy2/missing/strlcpy.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+#include <string.h>
+
+size_t
+strlcpy(char *dst, const char *src, size_t siz);
+
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/examples/hello_strlcpy2/test.mk b/examples/hello_strlcpy2/test.mk
new file mode 100644
index 0000000..e0155bb
--- /dev/null
+++ b/examples/hello_strlcpy2/test.mk
@@ -0,0 +1,38 @@
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/hello < ${.CURDIR}/input.in; \
+ rm -rf ${.OBJDIR}${PREFIX}; \
+ MKCATPAGES=yes; export MKCATPAGES; \
+ \
+ echo =========== all ============; \
+ find ${.OBJDIR} -type f | grep -Ev '(strlcpy|getline)[.]o' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ========= install ==========; \
+ ${MAKE} ${MAKEFLAGS} install -j3 DESTDIR=${.OBJDIR} \
+ > /dev/null; \
+ find ${.OBJDIR}${PREFIX} -type f -o -type d | \
+ grep -vE '(strlcpy|getline)[.]o' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======== uninstall =========; \
+ ${MAKE} ${MAKEFLAGS} -j4 uninstall DESTDIR=${.OBJDIR} > /dev/null; \
+ find ${.OBJDIR}${PREFIX} -type f | grep -vE '(strlcpy|getline)[.]o' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ========== clean ===========; \
+ ${MAKE} ${MAKEFLAGS} clean > /dev/null; \
+ find ${.OBJDIR} -type f | grep -vE '(strlcpy|getline)[.]o' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======= distclean ==========; \
+ ${MAKE} ${MAKEFLAGS} distclean > /dev/null; \
+ find ${.OBJDIR} -type f | grep -vE '(strlcpy|getline)[.]o' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======= CLEANFILES ==========; \
+ ${MAKE} ${MAKEFLAGS} print-values VARS='CLEANFILES' MKCHECKS=no | \
+ awk '{for(i=1; i<=NF; ++i) if ($$i ~ /[.]o$$/) print $$i}'
+
+.include <mkc.minitest.mk>
diff --git a/examples/hello_strlcpy3/Makefile b/examples/hello_strlcpy3/Makefile
new file mode 100644
index 0000000..33e80b1
--- /dev/null
+++ b/examples/hello_strlcpy3/Makefile
@@ -0,0 +1,11 @@
+PROG = hello
+SRCS = hello.c
+
+WARNS = 4
+
+MKC_FEATURES = strlcpy strlcat getline
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/hello_strlcpy3/expect.out b/examples/hello_strlcpy3/expect.out
new file mode 100644
index 0000000..3cd8ac5
--- /dev/null
+++ b/examples/hello_strlcpy3/expect.out
@@ -0,0 +1,101 @@
+foo17# Copyrig
+foo17# All rig
+foo17#
+foo17# Redistr
+foo17# modific
+foo17# are met
+foo17# 1. Redi
+foo17# noti
+foo17# 2. Redi
+foo17# noti
+foo17# docu
+foo17#
+foo17# THIS SO
+foo17# ``AS IS
+foo17# TO, THE
+foo17# PURPOSE
+foo17# BE LIAB
+foo17# CONSEQU
+foo17# SUBSTIT
+foo17# INTERRU
+foo17# CONTRAC
+foo17# ARISING
+foo17# POSSIBI
+Theo de Raadt said
+=========== all ============
+/objdir/Makefile
+/objdir/_mkc_compiler_type.err
+/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func3_getline_stdio_h.c
+/objdir/_mkc_func3_getline_stdio_h.err
+/objdir/_mkc_func3_getline_stdio_h.res
+/objdir/_mkc_func3_strlcat_string_h.c
+/objdir/_mkc_func3_strlcat_string_h.err
+/objdir/_mkc_func3_strlcat_string_h.res
+/objdir/_mkc_func3_strlcpy_string_h.c
+/objdir/_mkc_func3_strlcpy_string_h.err
+/objdir/_mkc_func3_strlcpy_string_h.res
+/objdir/_mkc_funclib_getline.c
+/objdir/_mkc_funclib_getline.err
+/objdir/_mkc_funclib_getline.res
+/objdir/_mkc_funclib_strlcat.c
+/objdir/_mkc_funclib_strlcat.err
+/objdir/_mkc_funclib_strlcat.res
+/objdir/_mkc_funclib_strlcpy.c
+/objdir/_mkc_funclib_strlcpy.err
+/objdir/_mkc_funclib_strlcpy.res
+/objdir/_mkc_prog_cc.err
+/objdir/_mkc_prog_cc.res
+/objdir/expect.out
+/objdir/hello
+/objdir/hello.c
+/objdir/hello.o
+/objdir/hello_strlcpy3.test.out.tmp
+/objdir/input.in
+/objdir/test.mk
+========= install ==========
+/objdir/prefix
+/objdir/prefix/bin
+/objdir/prefix/bin/hello
+======== uninstall =========
+========== clean ===========
+/objdir/Makefile
+/objdir/_mkc_compiler_type.err
+/objdir/_mkc_compiler_type.res
+/objdir/_mkc_func3_getline_stdio_h.c
+/objdir/_mkc_func3_getline_stdio_h.err
+/objdir/_mkc_func3_getline_stdio_h.res
+/objdir/_mkc_func3_strlcat_string_h.c
+/objdir/_mkc_func3_strlcat_string_h.err
+/objdir/_mkc_func3_strlcat_string_h.res
+/objdir/_mkc_func3_strlcpy_string_h.c
+/objdir/_mkc_func3_strlcpy_string_h.err
+/objdir/_mkc_func3_strlcpy_string_h.res
+/objdir/_mkc_funclib_getline.c
+/objdir/_mkc_funclib_getline.err
+/objdir/_mkc_funclib_getline.res
+/objdir/_mkc_funclib_strlcat.c
+/objdir/_mkc_funclib_strlcat.err
+/objdir/_mkc_funclib_strlcat.res
+/objdir/_mkc_funclib_strlcpy.c
+/objdir/_mkc_funclib_strlcpy.err
+/objdir/_mkc_funclib_strlcpy.res
+/objdir/_mkc_prog_cc.err
+/objdir/_mkc_prog_cc.res
+/objdir/expect.out
+/objdir/hello.c
+/objdir/hello_strlcpy3.test.out.tmp
+/objdir/input.in
+/objdir/test.mk
+======= distclean ==========
+/objdir/Makefile
+/objdir/expect.out
+/objdir/hello.c
+/objdir/hello_strlcpy3.test.out.tmp
+/objdir/input.in
+/objdir/test.mk
+======= CLEANFILES ==========
+strlcpy.o
+strlcat.o
+getline.o
+hello.o
diff --git a/examples/hello_strlcpy3/hello.c b/examples/hello_strlcpy3/hello.c
new file mode 100644
index 0000000..2993cc5
--- /dev/null
+++ b/examples/hello_strlcpy3/hello.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <mkc_strlcpy.h>
+#include <mkc_strlcat.h>
+#include <mkc_getline.h>
+
+static const char message [] = "Theo de Raadt said: \"The strlcpy() and strlcat() functions provide a consistent, unambiguous API to help the programmer write more bullet-proof code.\"";
+
+int main (int argc, char ** argv)
+{
+ char *buf = NULL;
+ size_t size = 0;
+ ssize_t len = 0;
+ char small_buf [15];
+ char said [19];
+
+ while (len = getline (&buf, &size, stdin), len != -1){
+ len = strlen (buf);
+ if (len > 0 && buf [len-1] == '\n')
+ buf [len-1] = 0;
+
+ strlcpy (small_buf, "foo17", sizeof (small_buf));
+ strlcat (small_buf, buf, sizeof (small_buf));
+ puts (small_buf);
+ }
+
+ strlcpy (said, message, sizeof (said));
+ puts (said);
+
+ return 0;
+}
diff --git a/examples/hello_strlcpy3/input.in b/examples/hello_strlcpy3/input.in
new file mode 100644
index 0000000..a5a6836
--- /dev/null
+++ b/examples/hello_strlcpy3/input.in
@@ -0,0 +1,23 @@
+# Copyright (c) 2009, Aleksey Cheusov <vle@gmx.net>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
diff --git a/examples/hello_strlcpy3/test.mk b/examples/hello_strlcpy3/test.mk
new file mode 100644
index 0000000..a123816
--- /dev/null
+++ b/examples/hello_strlcpy3/test.mk
@@ -0,0 +1,40 @@
+FUNCS_RE=(strlcat|strlcpy|getline)[.]o
+
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/hello < ${.CURDIR}/input.in; \
+ rm -rf ${.OBJDIR}${PREFIX}; \
+ MKCATPAGES=yes; export MKCATPAGES; \
+ \
+ echo =========== all ============; \
+ find ${.OBJDIR} -type f | grep -Ev '${FUNCS_RE}' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ========= install ==========; \
+ ${MAKE} ${MAKEFLAGS} install -j3 DESTDIR=${.OBJDIR} \
+ > /dev/null; \
+ find ${.OBJDIR}${PREFIX} -type f -o -type d | \
+ grep -vE '${FUNCS_RE}' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======== uninstall =========; \
+ ${MAKE} ${MAKEFLAGS} -j4 uninstall DESTDIR=${.OBJDIR} > /dev/null; \
+ find ${.OBJDIR}${PREFIX} -type f | grep -vE '${FUNCS_RE}' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ========== clean ===========; \
+ ${MAKE} ${MAKEFLAGS} clean > /dev/null; \
+ find ${.OBJDIR} -type f | grep -vE '${FUNCS_RE}' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======= distclean ==========; \
+ ${MAKE} ${MAKEFLAGS} distclean > /dev/null; \
+ find ${.OBJDIR} -type f | grep -vE '${FUNCS_RE}' | \
+ mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
+ \
+ echo ======= CLEANFILES ==========; \
+ ${MAKE} ${MAKEFLAGS} print-values VARS='CLEANFILES' MKCHECKS=no | \
+ awk '{for(i=1; i<=NF; ++i) if ($$i ~ /[.]o$$/) print $$i}'
+
+.include <mkc.minitest.mk>
diff --git a/examples/hello_subdirs/Makefile.inc b/examples/hello_subdirs/Makefile.inc
deleted file mode 100644
index 01b5f23..0000000
--- a/examples/hello_subdirs/Makefile.inc
+++ /dev/null
@@ -1 +0,0 @@
-.include "../Makefile.inc"
diff --git a/examples/hello_subdirs/prog1/expect.out b/examples/hello_subdirs/prog1/expect.out
index fe11252..4930183 100644
--- a/examples/hello_subdirs/prog1/expect.out
+++ b/examples/hello_subdirs/prog1/expect.out
@@ -3,6 +3,8 @@ Hello World1-2
Hello World1-3
OBJDIR_prog1=/path/to/prog1
OBJDIR_prog2=/path/to/prog2
+SRCDIR_prog1=hello_subdirs/prog1
+SRCDIR_prog2=hello_subdirs/prog2
=========== all ============
/objdir/Makefile
/objdir/expect.out
diff --git a/examples/hello_subdirs/prog1/test.mk b/examples/hello_subdirs/prog1/test.mk
index d62c501..4de6167 100644
--- a/examples/hello_subdirs/prog1/test.mk
+++ b/examples/hello_subdirs/prog1/test.mk
@@ -9,6 +9,9 @@ test_output:
echo OBJDIR_prog1=${OBJDIR_prog1} | mkc_test_helper_paths; \
echo OBJDIR_prog2=${OBJDIR_prog2} | mkc_test_helper_paths; \
\
+ echo SRCDIR_prog1=${SRCDIR_prog1} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_prog2=${SRCDIR_prog2} | sed 's,=.*examples/,=,'; \
+ \
echo =========== all ============; \
find ${.OBJDIR} -type f -o -type l | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
diff --git a/examples/hello_subdirs/prog2/expect.out b/examples/hello_subdirs/prog2/expect.out
index 8730e19..ab42434 100644
--- a/examples/hello_subdirs/prog2/expect.out
+++ b/examples/hello_subdirs/prog2/expect.out
@@ -1,6 +1,8 @@
Hello World2
OBJDIR_prog1=/path/to/prog1
OBJDIR_prog2=/path/to/prog2
+SRCDIR_prog1=hello_subdirs/prog1
+SRCDIR_prog2=hello_subdirs/prog2
=========== all ============
/objdir/Makefile
/objdir/expect.out
diff --git a/examples/hello_subdirs/prog2/test.mk b/examples/hello_subdirs/prog2/test.mk
index e86aa9c..24910dc 100644
--- a/examples/hello_subdirs/prog2/test.mk
+++ b/examples/hello_subdirs/prog2/test.mk
@@ -7,6 +7,9 @@ test_output:
echo OBJDIR_prog1=${OBJDIR_prog1} | mkc_test_helper_paths; \
echo OBJDIR_prog2=${OBJDIR_prog2} | mkc_test_helper_paths; \
\
+ echo SRCDIR_prog1=${SRCDIR_prog1} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_prog2=${SRCDIR_prog2} | sed 's,=.*examples/,=,'; \
+ \
echo =========== all ============; \
find ${.OBJDIR} -type f -o -type l | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
diff --git a/examples/hello_yacc/test.mk b/examples/hello_yacc/test.mk
index 71840f8..6ba98f6 100644
--- a/examples/hello_yacc/test.mk
+++ b/examples/hello_yacc/test.mk
@@ -33,7 +33,7 @@ test_output:
\
echo ==== SHRTOUT=yes ====; \
${MAKE} ${MAKEFLAGS} distclean > /dev/null; \
- env MKCATPAGES=no MKHTML=no SHRTOUT=yes ${MAKE} ${MAKEFLAGS} \
+ env MKCATPAGES=no MKHTML=no ${MAKE} ${MAKEFLAGS} SHRTOUT=yes \
all 2>/dev/null | mkc_test_helper2; \
\
echo ======= distclean ==========; \
diff --git a/examples/pkgconfig3/Makefile b/examples/pkgconfig3/Makefile
new file mode 100644
index 0000000..6ba35f8
--- /dev/null
+++ b/examples/pkgconfig3/Makefile
@@ -0,0 +1,8 @@
+PROG = pkgconfig3
+
+MKC_CHECK_PKGCONFIG = zzzz>=2.1
+
+MKC_REQD = 0.26.0
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/examples/pkgconfig3/expect.out b/examples/pkgconfig3/expect.out
new file mode 100644
index 0000000..7f4cc7d
--- /dev/null
+++ b/examples/pkgconfig3/expect.out
@@ -0,0 +1 @@
+pkg-config module 'zzz' was not found
diff --git a/examples/pkgconfig3/pkgconfig3.c b/examples/pkgconfig3/pkgconfig3.c
new file mode 100644
index 0000000..954b353
--- /dev/null
+++ b/examples/pkgconfig3/pkgconfig3.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int main (int argc, char** argv)
+{
+#if HAVE_PKGCONFIG_ZZZ
+ abort (); /* this should not happen */
+#else
+ puts ("pkg-config module 'zzz' was not found");
+#endif
+
+ return 0;
+}
diff --git a/examples/pkgconfig3/test.mk b/examples/pkgconfig3/test.mk
new file mode 100644
index 0000000..8d7ac0c
--- /dev/null
+++ b/examples/pkgconfig3/test.mk
@@ -0,0 +1,7 @@
+.PHONY : test_output
+test_output:
+ @set -e; \
+ ${.OBJDIR}/pkgconfig3; \
+ ${MAKE} ${MAKEFLAGS} distclean DESTDIR=${.OBJDIR} > /dev/null
+
+.include <mkc.minitest.mk>
diff --git a/examples/subprojects/Makefile b/examples/subprojects/Makefile
index 68c291e..10c642c 100644
--- a/examples/subprojects/Makefile
+++ b/examples/subprojects/Makefile
@@ -10,6 +10,52 @@ MKC_REQD = 0.11.0
_THISDIR_ =
.export _THISDIR_
+# A simpliest way to build debug and release version is to specify
+# appropriate targets like the following.
+.PHONY: debug release
+debug:
+ set -e; \
+ COPTS='${COPTS} -O0 -g'; LDFLAGS='${LDFLAGS} -g'; \
+ MAKEOBJDIR=${.CURDIR}/debug; MKRELOBJDIR=yes; \
+ export COPTS LDFLAGS MAKEOBJDIR MKRELOBJDIR; \
+ mkdir -p $$MAKEOBJDIR;\
+ ${MAKE} ${MAKEFLAGS} all
+release:
+ set -e; \
+ COPTS='${COPTS} -O'; \
+ MAKEOBJDIR=${.CURDIR}/release; MKRELOBJDIR=yes; \
+ export COPTS MAKEOBJDIR MKRELOBJDIR; \
+ mkdir -p $$MAKEOBJDIR;\
+ ${MAKE} ${MAKEFLAGS} all
+.if make(debug) || make(release)
+MKCHECKS = no
+.endif
+
+# Alternatively (and better!) one can introduce special variable for
+# this purpose like the following
+.include <mkc.init.mk> # we need ${MKDIR}
+
+.if defined(BM) # BuildMode
+. if ${BM} == "release"
+COPTS += -O
+MAKEOBJDIR = ${.CURDIR}/obj/release
+. elif ${BM} == "debug"
+COPTS += -O0 -g
+LDFLAGS += -g
+MAKEOBJDIR = ${.CURDIR}/obj/debug
+. elif ${BM} == "profile"
+COPTS += -O0 -g -pg
+LDFLAGS += -pg
+MAKEOBJDIR = ${.CURDIR}/obj/profile
+. else
+.error "Unsupported value of BM"
+. endif
+.OBJDIR = ${MAKEOBJDIR}
+MKRELOBJDIR = yes
+fake != ${MKDIR} -p ${MAKEOBJDIR}; echo # ${MAKEOBJDIR} must exist
+.export COPTS LDFLAGS
+.endif # defined(BM)
+
#
.include "test.mk"
.include "version.mk"
diff --git a/examples/subprojects/expect.out b/examples/subprojects/expect.out
index d26c974..b42cb16 100644
--- a/examples/subprojects/expect.out
+++ b/examples/subprojects/expect.out
@@ -248,6 +248,57 @@ GEN: hello_subprojects2
/objdir/subprojects.test.out.tmp
/objdir/test.mk
/objdir/version.mk
+======= debug/release =======
+/objdir/debug/hello/hello_subprojects
+/objdir/debug/hello/hello_subprojects.1
+/objdir/debug/hello/hello_subprojects.cat1
+/objdir/debug/hello/hello_subprojects.o
+/objdir/debug/hello/hello_subprojects2
+/objdir/debug/libhello1/hello1.o
+/objdir/debug/libhello1/hello1.os
+/objdir/debug/libhello1/libhello1.a
+/objdir/debug/libhello1/libhello1.so.1.0
+/objdir/debug/libhello2/hello2.cat3
+/objdir/debug/libhello2/hello2.o
+/objdir/debug/libhello2/libhello2.a
+/objdir/release/hello/hello_subprojects
+/objdir/release/hello/hello_subprojects.1
+/objdir/release/hello/hello_subprojects.cat1
+/objdir/release/hello/hello_subprojects.o
+/objdir/release/hello/hello_subprojects2
+/objdir/release/libhello1/hello1.o
+/objdir/release/libhello1/hello1.os
+/objdir/release/libhello1/libhello1.a
+/objdir/release/libhello1/libhello1.so.1.0
+/objdir/release/libhello2/hello2.cat3
+/objdir/release/libhello2/hello2.o
+/objdir/release/libhello2/libhello2.a
+======= drp =======
+/objdir/obj/debug/hello/hello_subprojects
+/objdir/obj/debug/hello/hello_subprojects.1
+/objdir/obj/debug/hello/hello_subprojects.cat1
+/objdir/obj/debug/hello/hello_subprojects.o
+/objdir/obj/debug/hello/hello_subprojects2
+/objdir/obj/debug/libhello1/hello1.o
+/objdir/obj/debug/libhello1/hello1.os
+/objdir/obj/debug/libhello1/libhello1.a
+/objdir/obj/debug/libhello1/libhello1.so.1.0
+/objdir/obj/debug/libhello2/hello2.cat3
+/objdir/obj/debug/libhello2/hello2.o
+/objdir/obj/debug/libhello2/libhello2.a
+=======
+/objdir/obj/release/hello/hello_subprojects
+/objdir/obj/release/hello/hello_subprojects.1
+/objdir/obj/release/hello/hello_subprojects.cat1
+/objdir/obj/release/hello/hello_subprojects.o
+/objdir/obj/release/hello/hello_subprojects2
+/objdir/obj/release/libhello1/hello1.o
+/objdir/obj/release/libhello1/hello1.os
+/objdir/obj/release/libhello1/libhello1.a
+/objdir/obj/release/libhello1/libhello1.so.1.0
+/objdir/obj/release/libhello2/hello2.cat3
+/objdir/obj/release/libhello2/hello2.o
+/objdir/obj/release/libhello2/libhello2.a
======= library dependencies =======
Hello1
Hello v.1.2.3
diff --git a/examples/subprojects/libhello1/linkme.mk b/examples/subprojects/libhello1/linkme.mk
index b585dd2..731ac90 100644
--- a/examples/subprojects/libhello1/linkme.mk
+++ b/examples/subprojects/libhello1/linkme.mk
@@ -2,4 +2,4 @@ PATH.hello1 := ${.PARSEDIR}
CPPFLAGS += -I${PATH.hello1}
DPLIBDIRS += ${PATH.hello1}
-LDADD += -lhello1
+LDADD0 += -lhello1
diff --git a/examples/subprojects/libhello2/linkme.mk b/examples/subprojects/libhello2/linkme.mk
index a7d2da7..135ad9e 100644
--- a/examples/subprojects/libhello2/linkme.mk
+++ b/examples/subprojects/libhello2/linkme.mk
@@ -2,4 +2,4 @@ PATH.hello2 := ${.PARSEDIR}
CPPFLAGS += -I${PATH.hello2}/include
DPLIBDIRS += ${PATH.hello2}
-LDADD += -lhello2
+LDADD0 += -lhello2
diff --git a/examples/subprojects/test.mk b/examples/subprojects/test.mk
index d3b88cc..46ac375 100644
--- a/examples/subprojects/test.mk
+++ b/examples/subprojects/test.mk
@@ -1,3 +1,5 @@
+next_level != expr ${.MAKE.LEVEL} + 1
+
.PHONY : test_output
test_output :
@set -e; \
@@ -18,8 +20,7 @@ test_output :
\
echo ===== all SHRTOUT=yes ======; \
${MAKE} ${MAKEFLAGS} clean > /dev/null; \
- env SHRTOUT=YES \
- ${MAKE} ${MAKEFLAGS} all 2>&1 | \
+ ${MAKE} ${MAKEFLAGS} all SHRTOUT=YES 2>&1 | \
mkc_test_helper_paths; \
\
echo ========= installdirs ==========; \
@@ -72,6 +73,27 @@ test_output :
\
${MAKE} ${MAKEFLAGS} distclean DESTDIR=${.OBJDIR} > /dev/null; \
\
+ echo ======= debug/release =======; \
+ ${MAKE} ${MAKEFLAGS} cleandir > /dev/null; \
+ env init_make_level=${next_level} ${MAKE} ${MAKEFLAGS} -j3 debug 1>&2; \
+ env init_make_level=${next_level} ${MAKE} ${MAKEFLAGS} -j3 release 1>&2; \
+ find ${.CURDIR}/release ${.CURDIR}/debug -type f | \
+ mkc_test_helper "${PREFIX}" "${.CURDIR}"; \
+ rm -rf ${.CURDIR}/release ${.CURDIR}/debug; \
+ \
+ echo ======= drp =======; \
+ env BM=debug init_make_level=${next_level} \
+ ${MAKE} ${MAKEFLAGS} -j3 all 1>&2; \
+ find ${.CURDIR}/obj -type f | \
+ mkc_test_helper "${PREFIX}" "${.CURDIR}"; \
+ rm -rf ${.CURDIR}/obj; \
+ echo =======; \
+ env BM=release init_make_level=${next_level} \
+ ${MAKE} ${MAKEFLAGS} -j3 all 1>&2; \
+ find ${.CURDIR}/obj -type f | \
+ mkc_test_helper "${PREFIX}" "${.CURDIR}"; \
+ rm -rf ${.CURDIR}/obj; \
+ \
echo ======= library dependencies =======; \
PREFIX=${.CURDIR}/usr; export PREFIX; \
${MAKE} ${MAKEFLAGS} all installdirs install -j3 >&2; \
diff --git a/examples/tools/expect.out b/examples/tools/expect.out
index deaa7e3..df742fd 100644
--- a/examples/tools/expect.out
+++ b/examples/tools/expect.out
@@ -12,6 +12,14 @@ OBJDIR_libs_foo=/path/to/foo
OBJDIR_libs_bar=/path/to/bar
OBJDIR_prog3=/path/to/prog3
OBJDIR_bar=/path/to/bar
+SRCDIR_tools_prog1=tools/tools/prog1
+SRCDIR_tools_prog2=tools/tools/prog2
+SRCDIR_tools_prog3=tools/tools/prog3
+SRCDIR_tools_prog4=tools/tools/prog4
+SRCDIR_libs_foo=tools/libs/foo
+SRCDIR_libs_bar=tools/libs/bar
+SRCDIR_prog3=tools/tools/prog3
+SRCDIR_bar=tools/libs/bar
=========== check ============
==================================================
check ===> tools/prog1
@@ -416,3 +424,97 @@ LD: prog4
/objdir/tools/prog4/prog4
/objdir/tools/prog4/prog4.c
/objdir/tools/prog4/prog4.o
+=========== print_deps ============
+all-libs/foo all-tools/prog1
+all-libs/bar all-tools/prog2
+all-libs/foo all-tools/prog3
+all-libs/bar all-tools/prog3
+all-libs/qux all-tools/prog4
+all-libs/bar bar
+all-libs/bar libs/bar
+all-libs/foo foo
+all-libs/foo libs/foo
+all-libs/qux qux
+all-libs/qux libs/qux
+all-tools/prog1 prog1
+all-tools/prog1 tools/prog1
+all-tools/prog2 prog2
+all-tools/prog2 tools/prog2
+all-tools/prog3 prog3
+all-tools/prog3 tools/prog3
+all-tools/prog4 prog4
+all-tools/prog4 tools/prog4
+all-libs/bar all
+all-libs/foo all
+all-libs/qux all
+all-tools/prog1 all
+all-tools/prog2 all
+all-tools/prog3 all
+all-tools/prog4 all
+all-libs/bar
+all-bar
+all-libs/bar all-bar
+all-libs/foo
+all-foo
+all-libs/foo all-foo
+all-libs/qux
+all-qux
+all-libs/qux all-qux
+all-tools/prog1
+all-prog1
+all-tools/prog1 all-prog1
+all-tools/prog2
+all-prog2
+all-tools/prog2 all-prog2
+all-tools/prog3
+all-prog3
+all-tools/prog3 all-prog3
+all-tools/prog4
+all-prog4
+all-tools/prog4 all-prog4
+bar
+foo
+qux
+prog1
+prog2
+prog3
+prog4
+all
+check
+clean
+cleandir
+depend
+errorcheck
+filelist
+install
+installdirs
+obj
+test
+uninstall
+=====
+check-tools/prog1 check
+check-tools/prog2 check
+check-tools/prog3 check
+check-tools/prog4 check
+check-libs/bar
+check-bar
+check-libs/bar check-bar
+check-libs/foo
+check-foo
+check-libs/foo check-foo
+check-libs/qux
+check-qux
+check-libs/qux check-qux
+check-tools/prog1
+check-prog1
+check-tools/prog1 check-prog1
+check-tools/prog2
+check-prog2
+check-tools/prog2 check-prog2
+check-tools/prog3
+check-prog3
+check-tools/prog3 check-prog3
+check-tools/prog4
+check-prog4
+check-tools/prog4 check-prog4
+check
diff --git a/examples/tools/libs/bar/linkme.mk b/examples/tools/libs/bar/linkme.mk
index 8df82aa..6d6ad74 100644
--- a/examples/tools/libs/bar/linkme.mk
+++ b/examples/tools/libs/bar/linkme.mk
@@ -2,4 +2,4 @@ PATH.bar := ${.PARSEDIR}
CPPFLAGS += -I${PATH.bar}
DPLIBDIRS += ${PATH.bar}
-LDADD += -lbar
+LDADD0 += -lbar
diff --git a/examples/tools/libs/foo/linkme.mk b/examples/tools/libs/foo/linkme.mk
index 00b5b42..841ff33 100644
--- a/examples/tools/libs/foo/linkme.mk
+++ b/examples/tools/libs/foo/linkme.mk
@@ -2,4 +2,4 @@ PATH.foo := ${.PARSEDIR}
CPPFLAGS += -I${PATH.foo}
DPLIBDIRS += ${PATH.foo}
-LDADD += -lfoo
+LDADD0 += -lfoo
diff --git a/examples/tools/libs/qux/linkme.mk b/examples/tools/libs/qux/linkme.mk
index e81f93b..ebf405e 100644
--- a/examples/tools/libs/qux/linkme.mk
+++ b/examples/tools/libs/qux/linkme.mk
@@ -2,4 +2,4 @@ PATH.qux := ${.PARSEDIR}
CPPFLAGS += -I${PATH.qux}
DPLIBDIRS += ${PATH.qux}
-LDADD += -lqux
+LDADD0 += -lqux
diff --git a/examples/tools/test.mk b/examples/tools/test.mk
index b65b319..fadfedc 100644
--- a/examples/tools/test.mk
+++ b/examples/tools/test.mk
@@ -20,6 +20,14 @@ test_output :
echo OBJDIR_libs_bar=${OBJDIR_libs_bar} | mkc_test_helper_paths; \
echo OBJDIR_prog3=${OBJDIR_prog3} | mkc_test_helper_paths; \
echo OBJDIR_bar=${OBJDIR_bar} | mkc_test_helper_paths; \
+ echo SRCDIR_tools_prog1=${SRCDIR_tools_prog1} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog2=${SRCDIR_tools_prog2} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog3=${SRCDIR_tools_prog3} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog4=${SRCDIR_tools_prog4} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_libs_foo=${SRCDIR_libs_foo} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_libs_bar=${SRCDIR_libs_bar} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_prog3=${SRCDIR_prog3} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_bar=${SRCDIR_bar} | sed 's,=.*examples/,=,'; \
\
echo =========== check ============; \
${MAKE} ${MAKEFLAGS} check 2>&1; \
@@ -109,6 +117,11 @@ test_output :
find ${.OBJDIR} -type f -o -type l | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
\
+ echo =========== print_deps ============; \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E '^(all|[^-/ ]+$$)'; \
+ echo =====; \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E ^check; \
+ \
${MAKE} ${MAKEFLAGS} cleandir > /dev/null; \
.include <mkc.minitest.mk>
diff --git a/examples/tools2/Makefile b/examples/tools2/Makefile
index c370807..fd00e1a 100644
--- a/examples/tools2/Makefile
+++ b/examples/tools2/Makefile
@@ -15,9 +15,10 @@ NODEPS += check-*/*:check-*/* \
# target "check" is used for testing because "test" is used by mk-configure
TARGETS = check
-SHORTPRJNAME = no
+SHORTPRJNAME = no
# for regression test only
+MKC_CACHEDIR = ${.OBJDIR}
_THISDIR_ =
.export _THISDIR_
diff --git a/examples/tools2/expect.out b/examples/tools2/expect.out
index 9d2783a..735c615 100644
--- a/examples/tools2/expect.out
+++ b/examples/tools2/expect.out
@@ -12,6 +12,14 @@ OBJDIR_libs_foo=/path/to/foo
OBJDIR_libs_bar=/path/to/bar
OBJDIR_prog3=
OBJDIR_bar=
+SRCDIR_tools_prog1=tools2/tools/prog1
+SRCDIR_tools_prog2=tools2/tools/prog2
+SRCDIR_tools_prog3=tools2/tools/prog3
+SRCDIR_tools_prog4=tools2/tools/prog4
+SRCDIR_libs_foo=tools2/libs/foo
+SRCDIR_libs_bar=tools2/libs/bar
+SRCDIR_prog3=
+SRCDIR_bar=
=========== check ============
==================================================
check ===> tests/prog1
@@ -446,3 +454,44 @@ obj/tools/prog3/prog3
obj/tools/prog3/prog3.o
obj/tools/prog4/prog4
obj/tools/prog4/prog4.o
+=========== print_deps ============
+all-libs/foo all-tools/prog1
+all-libs/bar all-tools/prog2
+all-libs/foo all-tools/prog3
+all-libs/bar all-tools/prog3
+all-libs/qux all-tools/prog4
+all-tools/prog1 all-tests/prog1
+all-tools/prog2 all-tests/prog2
+all-tools/prog3 all-tests/prog3
+all-tools/prog4 all-tests/prog4
+all-libs/bar libs/bar
+all-libs/foo libs/foo
+all-libs/qux libs/qux
+all-tests/prog1 tests/prog1
+all-tests/prog2 tests/prog2
+all-tests/prog3 tests/prog3
+all-tests/prog4 tests/prog4
+all-tools/prog1 tools/prog1
+all-tools/prog2 tools/prog2
+all-tools/prog3 tools/prog3
+all-tools/prog4 tools/prog4
+all-libs/bar all
+all-libs/foo all
+all-libs/qux all
+all-tools/prog1 all
+all-tools/prog2 all
+all-tools/prog3 all
+all-tools/prog4 all
+all-libs/bar
+all-libs/foo
+all-libs/qux
+all-tests/prog1
+all-tests/prog2
+all-tests/prog3
+all-tests/prog4
+all-tools/prog1
+all-tools/prog2
+all-tools/prog3
+all-tools/prog4
+all
+=====
diff --git a/examples/tools2/libs/bar/linkme.mk b/examples/tools2/libs/bar/linkme.mk
index 4eea0a9..10a6279 100644
--- a/examples/tools2/libs/bar/linkme.mk
+++ b/examples/tools2/libs/bar/linkme.mk
@@ -2,4 +2,4 @@ PATH.bar := ${.PARSEDIR}
CPPFLAGS += -I${PATH.bar}
DPLIBDIRS += libs/${PATH.bar:T}
-LDADD += -lbar
+LDADD0 += -lbar
diff --git a/examples/tools2/libs/foo/linkme.mk b/examples/tools2/libs/foo/linkme.mk
index ad42ee4..b1da09b 100644
--- a/examples/tools2/libs/foo/linkme.mk
+++ b/examples/tools2/libs/foo/linkme.mk
@@ -2,4 +2,4 @@ PATH.foo := ${.PARSEDIR}
CPPFLAGS += -I${PATH.foo}
DPLIBDIRS += libs/${PATH.foo:T}
-LDADD += -lfoo
+LDADD0 += -lfoo
diff --git a/examples/tools2/libs/qux/linkme.mk b/examples/tools2/libs/qux/linkme.mk
index 82f5dd6..ec0e23a 100644
--- a/examples/tools2/libs/qux/linkme.mk
+++ b/examples/tools2/libs/qux/linkme.mk
@@ -2,4 +2,4 @@ PATH.qux := ${.PARSEDIR}
CPPFLAGS += -I${OBJDIR_libs_qux}
DPLIBDIRS += libs/${PATH.qux:T}
-LDADD += -lqux
+LDADD0 += -lqux
diff --git a/examples/tools2/test.mk b/examples/tools2/test.mk
index 1c630f0..e04a04b 100644
--- a/examples/tools2/test.mk
+++ b/examples/tools2/test.mk
@@ -21,6 +21,14 @@ test_output :
echo OBJDIR_libs_bar=${OBJDIR_libs_bar} | mkc_test_helper_paths; \
echo OBJDIR_prog3=${OBJDIR_prog3} | mkc_test_helper_paths; \
echo OBJDIR_bar=${OBJDIR_bar} | mkc_test_helper_paths; \
+ echo SRCDIR_tools_prog1=${SRCDIR_tools_prog1} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog2=${SRCDIR_tools_prog2} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog3=${SRCDIR_tools_prog3} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_tools_prog4=${SRCDIR_tools_prog4} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_libs_foo=${SRCDIR_libs_foo} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_libs_bar=${SRCDIR_libs_bar} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_prog3=${SRCDIR_prog3} | sed 's,=.*examples/,=,'; \
+ echo SRCDIR_bar=${SRCDIR_bar} | sed 's,=.*examples/,=,'; \
\
echo =========== check ============; \
${MAKE} ${MAKEFLAGS} check 2>&1; \
@@ -110,6 +118,10 @@ test_output :
find obj -type f -o -type l | sort; \
rm -rf obj; \
\
+ echo =========== print_deps ============; \
+ ${MAKE} ${MAKEFLAGS} print_deps | grep -E '^all'; \
+ echo =====; \
+ \
${MAKE} ${MAKEFLAGS} cleandir > /dev/null; \
.include <mkc.minitest.mk>
diff --git a/features/Makefile b/features/Makefile
new file mode 100644
index 0000000..662178b
--- /dev/null
+++ b/features/Makefile
@@ -0,0 +1,37 @@
+.for f in strlcat strlcpy getline
+FILES += mkc_${f}.h mkc_imp.f_${f}.mk ${f}/${f}.c
+FILESDIR_mkc_imp.f_${f}.mk = ${MKFILESDIR}
+FILESDIR_mkc_${f}.h = ${FEATURESDIR}
+FILESDIR_${f}/${f}.c = ${FEATURESDIR}/${f}
+.endfor
+
+.for f in libm libdl SLIST RB
+FILES += mkc_${f}.h mkc_imp.f_${f}.mk
+FILESDIR_mkc_imp.f_${f}.mk = ${MKFILESDIR}
+FILESDIR_mkc_${f}.h = ${FEATURESDIR}
+.endfor
+
+.for f in netbsd_sys_queue.h netbsd_sys_tree.h
+FILES += ${f}
+FILESDIR_${f} = ${FEATURESDIR}
+.endfor
+
+LINKS += ${MKFILESDIR}/mkc_imp.f_RB.mk ${MKFILESDIR}/mkc_imp.f_SPLAY.mk
+
+LINKS += ${FEATURESDIR}/mkc_RB.h ${FEATURESDIR}/mkc_SPLAY.h
+
+.for i in SIMPLEQ STAILQ LIST TAILQ CIRCLEQ
+LINKS += ${MKFILESDIR}/mkc_imp.f_SLIST.mk ${MKFILESDIR}/mkc_imp.f_${i}.mk
+LINKS += ${FEATURESDIR}/mkc_SLIST.h ${FEATURESDIR}/mkc_${i}.h
+
+# the following section is for tests/sys_queue regression test
+all: mkc_imp.f_${i}.mk mkc_${i}.h
+mkc_imp.f_${i}.mk: mkc_imp.f_SLIST.mk
+ cp mkc_imp.f_SLIST.mk ${.TARGET}
+mkc_${i}.h: mkc_SLIST.h
+ cp mkc_SLIST.h ${.TARGET}
+CLEANFILES += mkc_${i}.h mkc_imp.f_${i}.mk
+.endfor
+
+#
+.include <mkc.files.mk>
diff --git a/features/getline/getline.c b/features/getline/getline.c
new file mode 100644
index 0000000..93836b0
--- /dev/null
+++ b/features/getline/getline.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007-2014 by Aleksey Cheusov
+ * See LICENSE file in the distribution.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+ssize_t
+getline(char** lineptr, size_t* n, FILE* stream);
+
+ssize_t
+getline(char** lineptr, size_t* n, FILE* stream)
+{
+ int c;
+ size_t sz = 0;
+
+ while (c = getc (stream), c != EOF){
+ if (sz+1 >= *n){
+ /* +2 is for `c' and 0-terminator */
+ *n = *n * 3 / 2 + 2;
+ *lineptr = realloc (*lineptr, *n);
+ if (!*lineptr)
+ return -1;
+ }
+
+ (*lineptr) [sz++] = (char) c;
+ if (c == '\n')
+ break;
+ }
+
+ if (ferror (stream))
+ return (ssize_t) -1;
+
+ if (!sz){
+ if (feof (stream)){
+ return (ssize_t) -1;
+ }else if (!*n){
+ *lineptr = malloc (1);
+ if (!*lineptr)
+ return -1;
+
+ *n = 1;
+ }
+ }
+
+ (*lineptr) [sz] = 0;
+ return sz;
+}
diff --git a/features/mkc_RB.h b/features/mkc_RB.h
new file mode 100644
index 0000000..f1039d2
--- /dev/null
+++ b/features/mkc_RB.h
@@ -0,0 +1,16 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_SYS_TREE_H_
+#define _MKC_SYS_TREE_H_
+
+#if defined(HAVE_DEFINE_RB_ENTRY_SYS_TREE_H) && defined(HAVE_DEFINE_SPLAY_ENTRY_SYS_TREE_H)
+#include <sys/tree.h>
+#else
+#include "netbsd_sys_tree.h"
+#endif
+
+#endif // _MKC_SYS_TREE_H_
diff --git a/features/mkc_SLIST.h b/features/mkc_SLIST.h
new file mode 100644
index 0000000..0c72646
--- /dev/null
+++ b/features/mkc_SLIST.h
@@ -0,0 +1,16 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_SYS_QUEUE_H_
+#define _MKC_SYS_QUEUE_H_
+
+#ifdef MKC_SYS_QUEUE_IS_FINE
+#include <sys/queue.h>
+#else
+#include "netbsd_sys_queue.h"
+#endif
+
+#endif // _MKC_SYS_QUEUE_H_
diff --git a/features/mkc_getline.h b/features/mkc_getline.h
new file mode 100644
index 0000000..728eecb
--- /dev/null
+++ b/features/mkc_getline.h
@@ -0,0 +1,17 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_GETLINE_H_
+#define _MKC_GETLINE_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef HAVE_FUNC3_GETLINE_STDIO_H
+ssize_t getline(char** lineptr, size_t* n, FILE* stream);
+#endif
+
+#endif // _MKC_GETLINE_H_
diff --git a/features/mkc_imp.f_RB.mk b/features/mkc_imp.f_RB.mk
new file mode 100644
index 0000000..57839ed
--- /dev/null
+++ b/features/mkc_imp.f_RB.mk
@@ -0,0 +1,7 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+############################################################
+
+MKC_CHECK_DEFINES += RB_ENTRY:sys/tree.h
+MKC_CHECK_DEFINES += SPLAY_ENTRY:sys/tree.h
diff --git a/features/mkc_imp.f_SLIST.mk b/features/mkc_imp.f_SLIST.mk
new file mode 100644
index 0000000..de7d2af
--- /dev/null
+++ b/features/mkc_imp.f_SLIST.mk
@@ -0,0 +1,30 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+############################################################
+_macro = SLIST SIMPLEQ STAILQ LIST TAILQ TAILQ
+
+.for m in ${_macro}
+MKC_CHECK_DEFINES += ${m}_ENTRY:sys/queue.h
+_macro.${m} = 1
+.endfor
+
+MKC_NOAUTO=1
+
+.include <mkc.configure.mk>
+
+.for f in ${MKC_FEATURES}
+.if defined(_macro.${f}) && !${HAVE_DEFINE.${m}_ENTRY.sys/queue.h:U0}
+bad=1
+.endif
+.endfor
+
+.ifndef bad
+CFLAGS+= -DMKC_SYS_QUEUE_IS_FINE=1
+.endif
+
+.undef bad
+
+.for m in ${_macro}
+.undef _macro.${m}
+.endfor
diff --git a/features/mkc_imp.f_getline.mk b/features/mkc_imp.f_getline.mk
new file mode 100644
index 0000000..50b3710
--- /dev/null
+++ b/features/mkc_imp.f_getline.mk
@@ -0,0 +1,7 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+
+MKC_SOURCE_FUNCLIBS += getline
+MKC_SOURCE_DIR.getline.c = ${FEATURESDIR}/getline
+MKC_CHECK_FUNCS3 += getline:stdio.h
diff --git a/features/mkc_imp.f_libdl.mk b/features/mkc_imp.f_libdl.mk
new file mode 100644
index 0000000..88833d9
--- /dev/null
+++ b/features/mkc_imp.f_libdl.mk
@@ -0,0 +1,8 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+
+MKC_COMMON_DEFINES += -D_GNU_SOURCE
+
+MKC_REQUIRE_FUNCLIBS += dlopen:dl
+MKC_REQUIRE_FUNCS2 += dlopen:dlfcn.h
diff --git a/features/mkc_imp.f_libm.mk b/features/mkc_imp.f_libm.mk
new file mode 100644
index 0000000..e7d9d0e
--- /dev/null
+++ b/features/mkc_imp.f_libm.mk
@@ -0,0 +1,5 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+
+MKC_CHECK_FUNCLIBS += sqrt:m
diff --git a/features/mkc_imp.f_strlcat.mk b/features/mkc_imp.f_strlcat.mk
new file mode 100644
index 0000000..9f6afc5
--- /dev/null
+++ b/features/mkc_imp.f_strlcat.mk
@@ -0,0 +1,7 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+
+MKC_SOURCE_FUNCLIBS += strlcat
+MKC_SOURCE_DIR.strlcat.c = ${FEATURESDIR}/strlcat
+MKC_CHECK_FUNCS3 += strlcat:string.h
diff --git a/features/mkc_imp.f_strlcpy.mk b/features/mkc_imp.f_strlcpy.mk
new file mode 100644
index 0000000..5c41db6
--- /dev/null
+++ b/features/mkc_imp.f_strlcpy.mk
@@ -0,0 +1,7 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+
+MKC_SOURCE_FUNCLIBS += strlcpy
+MKC_SOURCE_DIR.strlcpy.c = ${FEATURESDIR}/strlcpy
+MKC_CHECK_FUNCS3 += strlcpy:string.h
diff --git a/features/mkc_libdl.h b/features/mkc_libdl.h
new file mode 100644
index 0000000..046dade
--- /dev/null
+++ b/features/mkc_libdl.h
@@ -0,0 +1,18 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_LIBDL_H_
+#define _MKC_LIBDL_H_
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+# include <dlfcn.h>
+# undef _GNU_SOURCE
+#else
+# include <dlfcn.h>
+#endif
+
+#endif // _MKC_LIBDL_H_
diff --git a/features/mkc_libm.h b/features/mkc_libm.h
new file mode 100644
index 0000000..44919e1
--- /dev/null
+++ b/features/mkc_libm.h
@@ -0,0 +1,12 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_LIBM_H_
+#define _MKC_LIBM_H_
+
+#include <math.h>
+
+#endif // _MKC_LIBM_H_
diff --git a/features/mkc_strlcat.h b/features/mkc_strlcat.h
new file mode 100644
index 0000000..8ea0f1c
--- /dev/null
+++ b/features/mkc_strlcat.h
@@ -0,0 +1,16 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_STRLCAT_H_
+#define _MKC_STRLCAT_H_
+
+#include <string.h>
+
+#if !HAVE_FUNC3_STRLCAT_STRING_H
+size_t strlcat(char *dst, const char *src, size_t size);
+#endif
+
+#endif // _MKC_STRLCAT_H_
diff --git a/features/mkc_strlcpy.h b/features/mkc_strlcpy.h
new file mode 100644
index 0000000..1826e3f
--- /dev/null
+++ b/features/mkc_strlcpy.h
@@ -0,0 +1,16 @@
+/********************************************************************\
+ Copyright (c) 2014 by Aleksey Cheusov
+
+ See LICENSE file in the distribution.
+\********************************************************************/
+
+#ifndef _MKC_STRLCPY_H_
+#define _MKC_STRLCPY_H_
+
+#include <string.h>
+
+#if !HAVE_FUNC3_STRLCPY_STRING_H
+size_t strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#endif // _MKC_STRLCPY_H_
diff --git a/features/netbsd_sys_queue.h b/features/netbsd_sys_queue.h
new file mode 100644
index 0000000..9189c6c
--- /dev/null
+++ b/features/netbsd_sys_queue.h
@@ -0,0 +1,743 @@
+/* $NetBSD: queue.h,v 1.53 2011/11/19 22:51:31 tls Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#include <stdlib.h>
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list. Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction. Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
+ if ((head)->lh_first && \
+ (head)->lh_first->field.le_prev != &(head)->lh_first) \
+ panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_OP(elm, field) \
+ if ((elm)->field.le_next && \
+ (elm)->field.le_next->field.le_prev != \
+ &(elm)->field.le_next) \
+ panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
+ if (*(elm)->field.le_prev != (elm)) \
+ panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
+ (elm)->field.le_next = (void *)1L; \
+ (elm)->field.le_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_LIST_OP(elm, field)
+#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
+#endif
+
+#define LIST_INIT(head) do { \
+ (head)->lh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_LIST_OP((listelm), field) \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (/*CONSTCOND*/0)
+
+#define LIST_REMOVE(elm, field) do { \
+ QUEUEDEBUG_LIST_OP((elm), field) \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = ((head)->lh_first); \
+ (var); \
+ (var) = ((var)->field.le_next))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+/*
+ * List access methods.
+ */
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) do { \
+ (head)->slh_first = NULL; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while(curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_REMOVE_AFTER(slistelm, field) do { \
+ (slistelm)->field.sle_next = \
+ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \
+} while (/*CONSTCOND*/0)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ (head)->stqh_first = NULL; \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (head)->stqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.stqe_next = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+ (head)->stqh_last = &(elm)->field.stqe_next; \
+ (listelm)->field.stqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(head)->stqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->stqh_first == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (curelm->field.stqe_next != (elm)) \
+ curelm = curelm->field.stqe_next; \
+ if ((curelm->field.stqe_next = \
+ curelm->field.stqe_next->field.stqe_next) == NULL) \
+ (head)->stqh_last = &(curelm)->field.stqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->stqh_first); \
+ (var); \
+ (var) = ((var)->field.stqe_next))
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
+ if ((head)->sqh_first == (elm)) { \
+ SIMPLEQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->sqh_first; \
+ while (curelm->field.sqe_next != (elm)) \
+ curelm = curelm->field.sqe_next; \
+ if ((curelm->field.sqe_next = \
+ curelm->field.sqe_next->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(curelm)->field.sqe_next; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->sqh_first); \
+ (var); \
+ (var) = ((var)->field.sqe_next))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->sqh_first); \
+ (var) && ((next = ((var)->field.sqe_next)), 1); \
+ (var) = (next))
+
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SIMPLEQ_LAST(head, type, field) \
+ (SIMPLEQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->sqh_last) - offsetof(struct type, field))))
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define _TAILQ_HEAD(name, type, qual) \
+struct name { \
+ qual type *tqh_first; /* first element */ \
+ qual type *qual *tqh_last; /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define _TAILQ_ENTRY(type, qual) \
+struct { \
+ qual type *tqe_next; /* next element */ \
+ qual type *qual *tqe_prev; /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
+ if ((head)->tqh_first && \
+ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
+ panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
+ if (*(head)->tqh_last != NULL) \
+ panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_OP(elm, field) \
+ if ((elm)->field.tqe_next && \
+ (elm)->field.tqe_next->field.tqe_prev != \
+ &(elm)->field.tqe_next) \
+ panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
+ if (*(elm)->field.tqe_prev != (elm)) \
+ panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
+ if ((elm)->field.tqe_next == NULL && \
+ (head)->tqh_last != &(elm)->field.tqe_next) \
+ panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \
+ (head), (elm), __FILE__, __LINE__);
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
+ (elm)->field.tqe_next = (void *)1L; \
+ (elm)->field.tqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
+#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
+#define QUEUEDEBUG_TAILQ_OP(elm, field)
+#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
+#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
+#endif
+
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QUEUEDEBUG_TAILQ_OP((listelm), field) \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
+ QUEUEDEBUG_TAILQ_OP((elm), field) \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
+} while (/*CONSTCOND*/0)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->tqh_first); \
+ (var); \
+ (var) = ((var)->field.tqe_next))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, next) \
+ for ((var) = ((head)->tqh_first); \
+ (var) != NULL && ((next) = TAILQ_NEXT(var, field), 1); \
+ (var) = (next))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
+ (var); \
+ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((prev) = TAILQ_PREV((var), headname, field), 1);\
+ (var) = (prev))
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#if defined(_KERNEL) && defined(QUEUEDEBUG)
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
+ if ((head)->cqh_first != (void *)(head) && \
+ (head)->cqh_first->field.cqe_prev != (void *)(head)) \
+ panic("CIRCLEQ head forw %p %s:%d", (head), \
+ __FILE__, __LINE__); \
+ if ((head)->cqh_last != (void *)(head) && \
+ (head)->cqh_last->field.cqe_next != (void *)(head)) \
+ panic("CIRCLEQ head back %p %s:%d", (head), \
+ __FILE__, __LINE__);
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
+ if ((elm)->field.cqe_next == (void *)(head)) { \
+ if ((head)->cqh_last != (elm)) \
+ panic("CIRCLEQ elm last %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
+ panic("CIRCLEQ elm forw %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ } \
+ if ((elm)->field.cqe_prev == (void *)(head)) { \
+ if ((head)->cqh_first != (elm)) \
+ panic("CIRCLEQ elm first %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ } else { \
+ if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
+ panic("CIRCLEQ elm prev %p %s:%d", (elm), \
+ __FILE__, __LINE__); \
+ }
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
+ (elm)->field.cqe_next = (void *)1L; \
+ (elm)->field.cqe_prev = (void *)1L;
+#else
+#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
+#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
+#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
+#endif
+
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { (void *)&head, (void *)&head }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
+ QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+ QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
+} while (/*CONSTCOND*/0)
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for ((var) = ((head)->cqh_first); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_next))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for ((var) = ((head)->cqh_last); \
+ (var) != (const void *)(head); \
+ (var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
+ (((elm)->field.cqe_next == (void *)(head)) \
+ ? ((head)->cqh_first) \
+ : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field) \
+ (((elm)->field.cqe_prev == (void *)(head)) \
+ ? ((head)->cqh_last) \
+ : (elm->field.cqe_prev))
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/features/netbsd_sys_tree.h b/features/netbsd_sys_tree.h
new file mode 100644
index 0000000..d044f98
--- /dev/null
+++ b/features/netbsd_sys_tree.h
@@ -0,0 +1,741 @@
+/* $NetBSD: tree.h,v 1.16 2008/03/21 13:07:15 ad Exp $ */
+/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * 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 AUTHOR ``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 AUTHOR 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 _SYS_TREE_H_
+#define _SYS_TREE_H_
+
+/*
+ * This file defines data structures for different types of trees:
+ * splay trees and red-black trees.
+ *
+ * A splay tree is a self-organizing data structure. Every operation
+ * on the tree causes a splay to happen. The splay moves the requested
+ * node to the root of the tree and partly rebalances it.
+ *
+ * This has the benefit that request locality causes faster lookups as
+ * the requested nodes move to the top of the tree. On the other hand,
+ * every lookup causes memory writes.
+ *
+ * The Balance Theorem bounds the total access time for m operations
+ * and n inserts on an initially empty tree as O((m + n)lg n). The
+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
+ *
+ * A red-black tree is a binary search tree with the node color as an
+ * extra attribute. It fulfills a set of conditions:
+ * - every search path from the root to a leaf consists of the
+ * same number of black nodes,
+ * - each red node (except for the root) has a black parent,
+ * - each leaf node is black.
+ *
+ * Every operation on a red-black tree is bounded as O(lg n).
+ * The maximum height of a red-black tree is 2lg (n+1).
+ */
+
+#define SPLAY_HEAD(name, type) \
+struct name { \
+ struct type *sph_root; /* root of the tree */ \
+}
+
+#define SPLAY_INITIALIZER(root) \
+ { NULL }
+
+#define SPLAY_INIT(root) do { \
+ (root)->sph_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ENTRY(type) \
+struct { \
+ struct type *spe_left; /* left element */ \
+ struct type *spe_right; /* right element */ \
+}
+
+#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
+#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
+#define SPLAY_ROOT(head) (head)->sph_root
+#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
+
+/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
+#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKLEFT(head, tmp, field) do { \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKRIGHT(head, tmp, field) do { \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
+ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
+ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+
+#define SPLAY_PROTOTYPE(name, type, field, cmp) \
+void name##_SPLAY(struct name *, struct type *); \
+void name##_SPLAY_MINMAX(struct name *, int); \
+struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
+struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
+ \
+/* Finds the node with the same key as elm */ \
+static __inline struct type * \
+name##_SPLAY_FIND(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) \
+ return(NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) \
+ return (head->sph_root); \
+ return (NULL); \
+} \
+ \
+static __inline struct type * \
+name##_SPLAY_NEXT(struct name *head, struct type *elm) \
+{ \
+ name##_SPLAY(head, elm); \
+ if (SPLAY_RIGHT(elm, field) != NULL) { \
+ elm = SPLAY_RIGHT(elm, field); \
+ while (SPLAY_LEFT(elm, field) != NULL) { \
+ elm = SPLAY_LEFT(elm, field); \
+ } \
+ } else \
+ elm = NULL; \
+ return (elm); \
+} \
+ \
+static __inline struct type * \
+name##_SPLAY_MIN_MAX(struct name *head, int val) \
+{ \
+ name##_SPLAY_MINMAX(head, val); \
+ return (SPLAY_ROOT(head)); \
+}
+
+/* Main splay operation.
+ * Moves node close to the key of elm to top
+ */
+#define SPLAY_GENERATE(name, type, field, cmp) \
+struct type * \
+name##_SPLAY_INSERT(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) { \
+ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
+ } else { \
+ int __comp; \
+ name##_SPLAY(head, elm); \
+ __comp = (cmp)(elm, (head)->sph_root); \
+ if(__comp < 0) { \
+ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
+ SPLAY_RIGHT(elm, field) = (head)->sph_root; \
+ SPLAY_LEFT((head)->sph_root, field) = NULL; \
+ } else if (__comp > 0) { \
+ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT(elm, field) = (head)->sph_root; \
+ SPLAY_RIGHT((head)->sph_root, field) = NULL; \
+ } else \
+ return ((head)->sph_root); \
+ } \
+ (head)->sph_root = (elm); \
+ return (NULL); \
+} \
+ \
+struct type * \
+name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *__tmp; \
+ if (SPLAY_EMPTY(head)) \
+ return (NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) { \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
+ } else { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
+ name##_SPLAY(head, elm); \
+ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
+ } \
+ return (elm); \
+ } \
+ return (NULL); \
+} \
+ \
+void \
+name##_SPLAY(struct name *head, struct type *elm) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+ int __comp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) > 0){ \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+} \
+ \
+/* Splay with either the minimum or the maximum element \
+ * Used to find minimum or maximum element in tree. \
+ */ \
+void name##_SPLAY_MINMAX(struct name *head, int __comp) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while (1) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp > 0) { \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+}
+
+#define SPLAY_NEGINF -1
+#define SPLAY_INF 1
+
+#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
+#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
+#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
+#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
+#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
+#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
+
+#define SPLAY_FOREACH(x, name, head) \
+ for ((x) = SPLAY_MIN(name, head); \
+ (x) != NULL; \
+ (x) = SPLAY_NEXT(name, head, x))
+
+/* Macros that define a red-black tree */
+#define RB_HEAD(name, type) \
+struct name { \
+ struct type *rbh_root; /* root of the tree */ \
+}
+
+#define RB_INITIALIZER(root) \
+ { NULL }
+
+#define RB_INIT(root) do { \
+ (root)->rbh_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_BLACK 0
+#define RB_RED 1
+#define RB_ENTRY(type) \
+struct { \
+ struct type *rbe_left; /* left element */ \
+ struct type *rbe_right; /* right element */ \
+ struct type *rbe_parent; /* parent element */ \
+ int rbe_color; /* node color */ \
+}
+
+#define RB_LEFT(elm, field) (elm)->field.rbe_left
+#define RB_RIGHT(elm, field) (elm)->field.rbe_right
+#define RB_PARENT(elm, field) (elm)->field.rbe_parent
+#define RB_COLOR(elm, field) (elm)->field.rbe_color
+#define RB_ROOT(head) (head)->rbh_root
+#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
+
+#define RB_SET(elm, parent, field) do { \
+ RB_PARENT(elm, field) = parent; \
+ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
+ RB_COLOR(elm, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_SET_BLACKRED(black, red, field) do { \
+ RB_COLOR(black, field) = RB_BLACK; \
+ RB_COLOR(red, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#ifndef RB_AUGMENT
+#define RB_AUGMENT(x) (void)(x)
+#endif
+
+#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
+ (tmp) = RB_RIGHT(elm, field); \
+ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_LEFT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
+ (tmp) = RB_LEFT(elm, field); \
+ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_RIGHT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
+attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
+attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
+attr struct type *name##_RB_INSERT(struct name *, struct type *); \
+attr struct type *name##_RB_FIND(struct name *, struct type *); \
+attr struct type *name##_RB_NFIND(struct name *, struct type *); \
+attr struct type *name##_RB_NEXT(struct type *); \
+attr struct type *name##_RB_PREV(struct type *); \
+attr struct type *name##_RB_MINMAX(struct name *, int); \
+ \
+
+/* Main rb operation.
+ * Moves node close to the key of elm to top
+ */
+#define RB_GENERATE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+attr void \
+name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
+{ \
+ struct type *parent, *gparent, *tmp; \
+ while ((parent = RB_PARENT(elm, field)) != NULL && \
+ RB_COLOR(parent, field) == RB_RED) { \
+ gparent = RB_PARENT(parent, field); \
+ if (parent == RB_LEFT(gparent, field)) { \
+ tmp = RB_RIGHT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_RIGHT(parent, field) == elm) { \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_RIGHT(head, gparent, tmp, field); \
+ } else { \
+ tmp = RB_LEFT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_LEFT(parent, field) == elm) { \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_LEFT(head, gparent, tmp, field); \
+ } \
+ } \
+ RB_COLOR(head->rbh_root, field) = RB_BLACK; \
+} \
+ \
+attr void \
+name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
+{ \
+ struct type *tmp; \
+ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
+ elm != RB_ROOT(head)) { \
+ if (RB_LEFT(parent, field) == elm) { \
+ tmp = RB_RIGHT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
+ struct type *oleft; \
+ if ((oleft = RB_LEFT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oleft, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_RIGHT(head, tmp, oleft, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_RIGHT(tmp, field)) \
+ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } else { \
+ tmp = RB_LEFT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
+ struct type *oright; \
+ if ((oright = RB_RIGHT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oright, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_LEFT(head, tmp, oright, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_LEFT(tmp, field)) \
+ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } \
+ } \
+ if (elm) \
+ RB_COLOR(elm, field) = RB_BLACK; \
+} \
+ \
+attr struct type * \
+name##_RB_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *child, *parent, *old = elm; \
+ int color; \
+ if (RB_LEFT(elm, field) == NULL) \
+ child = RB_RIGHT(elm, field); \
+ else if (RB_RIGHT(elm, field) == NULL) \
+ child = RB_LEFT(elm, field); \
+ else { \
+ struct type *left; \
+ elm = RB_RIGHT(elm, field); \
+ while ((left = RB_LEFT(elm, field)) != NULL) \
+ elm = left; \
+ child = RB_RIGHT(elm, field); \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+ if (RB_PARENT(elm, field) == old) \
+ parent = elm; \
+ (elm)->field = (old)->field; \
+ if (RB_PARENT(old, field)) { \
+ if (RB_LEFT(RB_PARENT(old, field), field) == old)\
+ RB_LEFT(RB_PARENT(old, field), field) = elm;\
+ else \
+ RB_RIGHT(RB_PARENT(old, field), field) = elm;\
+ RB_AUGMENT(RB_PARENT(old, field)); \
+ } else \
+ RB_ROOT(head) = elm; \
+ RB_PARENT(RB_LEFT(old, field), field) = elm; \
+ if (RB_RIGHT(old, field)) \
+ RB_PARENT(RB_RIGHT(old, field), field) = elm; \
+ if (parent) { \
+ left = parent; \
+ do { \
+ RB_AUGMENT(left); \
+ } while ((left = RB_PARENT(left, field)) != NULL); \
+ } \
+ goto color; \
+ } \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+color: \
+ if (color == RB_BLACK) \
+ name##_RB_REMOVE_COLOR(head, parent, child); \
+ return (old); \
+} \
+ \
+/* Inserts a node into the RB tree */ \
+attr struct type * \
+name##_RB_INSERT(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp; \
+ struct type *parent = NULL; \
+ int comp = 0; \
+ tmp = RB_ROOT(head); \
+ while (tmp) { \
+ parent = tmp; \
+ comp = (cmp)(elm, parent); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ RB_SET(elm, parent, field); \
+ if (parent != NULL) { \
+ if (comp < 0) \
+ RB_LEFT(parent, field) = elm; \
+ else \
+ RB_RIGHT(parent, field) = elm; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = elm; \
+ name##_RB_INSERT_COLOR(head, elm); \
+ return (NULL); \
+} \
+ \
+/* Finds the node with the same key as elm */ \
+attr struct type * \
+name##_RB_FIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (NULL); \
+} \
+ \
+/* Finds the first node greater than or equal to the search key */ \
+attr struct type * \
+name##_RB_NFIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_NEXT(struct type *elm) \
+{ \
+ if (RB_RIGHT(elm, field)) { \
+ elm = RB_RIGHT(elm, field); \
+ while (RB_LEFT(elm, field)) \
+ elm = RB_LEFT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_PREV(struct type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+attr struct type * \
+name##_RB_MINMAX(struct name *head, int val) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *parent = NULL; \
+ while (tmp) { \
+ parent = tmp; \
+ if (val < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else \
+ tmp = RB_RIGHT(tmp, field); \
+ } \
+ return (parent); \
+}
+
+#define RB_NEGINF -1
+#define RB_INF 1
+
+#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
+#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
+#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
+#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
+#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
+#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+
+#define RB_FOREACH(x, name, head) \
+ for ((x) = RB_MIN(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_NEXT(x))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#endif /* _SYS_TREE_H_ */
diff --git a/features/strlcat/strlcat.c b/features/strlcat/strlcat.c
new file mode 100644
index 0000000..4d6c29a
--- /dev/null
+++ b/features/strlcat/strlcat.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat (char *dst, const char *src, size_t siz);
+
+size_t
+strlcat (char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ assert (dst != NULL);
+ assert (src != NULL);
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return (dlen + strlen(s));
+
+ while (*s != '\0'){
+ if (n != 1){
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return (dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/features/strlcpy/strlcpy.c b/features/strlcpy/strlcpy.c
new file mode 100644
index 0000000..4fca883
--- /dev/null
+++ b/features/strlcpy/strlcpy.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz);
+
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ assert (dst != NULL);
+ assert (src != NULL);
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0){
+ do{
+ if ((*d++ = *s++) == 0)
+ break;
+ }while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0){
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return (s - src - 1); /* count does not include NUL */
+}
diff --git a/main.mk b/main.mk
index 80d6c0e..d2bafee 100644
--- a/main.mk
+++ b/main.mk
@@ -1,8 +1,29 @@
.sinclude "cheusov_local_settings.mk" # for debugging
##################################################
-SUBPRJ_DFLT = custom helpers mk scripts
-SUBPRJ = examples tests doc presentation ${SUBPRJ_DFLT}
+SUBPRJ_DFLT = custom helpers mk scripts features
+SUBPRJ = examples doc presentation ${SUBPRJ_DFLT}
+
+tests = configure_test mkinstall mkshlib mkstaticlib mkpiclib \
+ mkprofilelib mkdll pkg_config_0 pkg_config_1 pkg_config_1_1 pkg_config_2 \
+ lua_dirs rec_makefiles reqd reqd2 reqd3 reqd4 reqd_clean_cache \
+ intexts_cleantrg require_prototype test_subprj_dash test_mkc_vs_PROG \
+ test_mkc_vs_LIB test_mkc_vs_SUBDIR test_mkc_vs_SUBPRJ endianess \
+ create_cachedir sys_queue
+.for t in ${tests}
+SUBPRJ += tests/${t}:tests
+.endfor
+
+examples = hello_world hello_scripts hello_files hello_sizeof hello_lex \
+ hello_yacc hello_calc2 subprojects hello_compilers hello_plugins \
+ hello_plugins2 hello_glib2 hello_subdirs hello_strlcpy hello_strlcpy2 \
+ hello_strlcpy3 hello_customtests hello_customtests2 hello_requirements \
+ hello_iconv hello_cxx hello_cxxlib hello_dictd hello_lua hello_lua2 \
+ hello_lua3 hello_superfs hello_xxzip hello_progs hello_progs2 tools \
+ tools2 pkgconfig3 hello_SLIST hello_RBTREE # hello_require_tools
+.for t in ${examples}
+SUBPRJ += examples/${t}:tests
+.endfor
##################################################
SHRTOUT = yes
diff --git a/mk/Makefile b/mk/Makefile
index 5e2b695..e3ba4e2 100644
--- a/mk/Makefile
+++ b/mk/Makefile
@@ -3,14 +3,14 @@ FILES = sys.mk mkc.configure.mk configure.mk mkc.mk \
mkc.minitest.mk mkc_imp.pkg-config.mk \
mkc_imp.files.mk mkc_imp.inc.mk mkc_imp.info.mk mkc_imp.lib.mk \
mkc_imp.links.mk mkc_imp.man.mk mkc_imp.prog.mk \
- mkc_imp.subprj.mk \
- mkc_imp.final.mk mkc_imp.scripts.mk \
+ mkc_imp.subprj.mk mkc_imp.conf-final.mk mkc_imp.rules.mk \
+ mkc_imp.final.mk mkc_imp.scripts.mk mkc_imp.checkprogs.mk \
mkc_imp.platform.sys.mk mkc_imp.dep.mk mkc_imp.lua.mk \
mkc_imp.arch.mk mkc_imp.pod.mk mkc_imp.preinit.mk \
mkc.prog.mk mkc.files.mk mkc.lib.mk mkc.subdir.mk mkc.subprj.mk \
mkc_imp.objdir.mk mkc_imp.obj.mk ${INFILES}
-FILESDIR = ${MKFILESDIR}
+FILESDIR = ${MKFILESDIR}
INFILES += mkc_imp.vars.mk
@@ -43,6 +43,7 @@ makedepend_cmd ?= makedepend
INTEXTS_REPLS += mkdep_cmd ${mkdep_cmd}
INTEXTS_REPLS += makedepend_cmd ${makedepend_cmd}
INTEXTS_REPLS += mkdep_type ${mkdep_type}
+INTEXTS_REPLS += featuresdir ${FEATURESDIR}
#################################################
.include <mkc.mk>
diff --git a/mk/configure.mk b/mk/configure.mk
index 8d7571c..fe1ed48 100644
--- a/mk/configure.mk
+++ b/mk/configure.mk
@@ -33,6 +33,7 @@ MKC_CACHEDIR ?= ${.OBJDIR} # directory for cache and intermediate files
MKC_COMMON_HEADERS ?= # list of headers always #included
MKC_NOCACHE ?= # 1 or yes for disabling cache
MKC_CUSTOM_DIR ?=${.CURDIR} # directory with custom tests.c
+MKC_SOURCE_DIR ?=${.CURDIR} # directory with missing strlcat.c etc.
#
MKC_SOURCE_FUNCLIBS ?=
@@ -43,11 +44,6 @@ _MKC_SOURCE_FUNCS = ${MKC_SOURCE_FUNCLIBS:C/:.*//}
HAVE_FUNCLIB.main ?= 1
-#
-.undef MKC_SRCS
-.undef MKC_LDADD
-.undef MKC_CFLAGS
-
.if defined(MKC_COMMON_DEFINES.${TARGET_OPSYS})
CPPFLAGS += ${MKC_COMMON_DEFINES.${TARGET_OPSYS}}
.endif
@@ -68,7 +64,7 @@ mkc.environ=CC='${CC}' CXX='${CXX}' FC='${FC}' CPPFLAGS='${_MKC_CPPFLAGS}' CFLAG
######################################################
# checking for builtin checks
.for i in ${MKC_CHECK_BUILTINS} ${MKC_REQUIRE_BUILTINS}
-MKC_CUSTOM_FN.${i} ?= ${BUILTINSDIR}/${i}
+MKC_CUSTOM_FN.${i} ?= ${BUILTINSDIR}/${i:S/endianess/endianness/}
MKC_CHECK_CUSTOM += ${i}
MKC_REQUIRE_CUSTOM += ${MKC_REQUIRE_BUILTINS:M${i}}
.endfor
@@ -107,7 +103,7 @@ MKC_LDADD += -l${f:C/^.*://}
.endif
.endif
.if !${HAVE_FUNCLIB.${f:S/:/./g}} && !${HAVE_FUNCLIB.${f:C/:.*//}} && !empty(_MKC_SOURCE_FUNCS:M${f:C/:.*//})
-MKC_SRCS += ${f:C/:.*//}.c
+MKC_SRCS += ${MKC_SOURCE_DIR.${f:C/:.*//}.c:U${MKC_SOURCE_DIR}}/${f:C/:.*//}.c
.endif
.endfor # f
@@ -249,6 +245,9 @@ MKC_ERR_MSG += "ERROR: cannot find declaration of function ${d}"
.endif
.endfor # d
+MKC_CHECK_FUNCS${n} := # workaround for buggy bmake-20110606
+MKC_REQUIRE_FUNCS${n} := # workaround for buggy bmake-20110606
+
.undef MKC_CHECK_FUNCS${n}
.undef MKC_REQUIRE_FUNCS${n}
@@ -264,6 +263,9 @@ MKC_CUSTOM_FN.${c} = ${c}.c
.if empty(MKC_CUSTOM_FN.${c}:M/*)
MKC_CUSTOM_FN.${c} := ${MKC_CUSTOM_DIR}/${MKC_CUSTOM_FN.${c}}
.endif
+.if ${c} == "endianess"
+.warning "endianess test deprecated; use endianness instead"
+.endif
CUSTOM.${c} != env ${mkc.environ} mkc_check_custom ${MKC_CUSTOM_FN.${c}}
.endif
.if !empty(CUSTOM.${c}) && ${CUSTOM.${c}} != 0
@@ -316,18 +318,27 @@ MKC_ERR_MSG += "ERROR: cannot find program ${p}"
.undef MKC_REQUIRE_CUSTOM
######################################################
+# prototype checks
+.for p in ${MKC_CHECK_PROTOTYPES} ${MKC_REQUIRE_PROTOTYPES}
+.if !defined(HAVE_PROTOTYPE.${p})
+HAVE_PROTOTYPE.${p} != env ${mkc.environ} mkc_check_decl prototype \
+ ${MKC_PROTOTYPE_FUNC.${p}:Q} ${MKC_PROTOTYPE_HEADERS.${p}}
+.endif # !defined(HAVE_PROTOTYPE.${p})
+.if ${HAVE_PROTOTYPE.${p}}
+MKC_CFLAGS += -DHAVE_PROTOTYPE_${p:tu}=1
+.elif !empty(MKC_REQUIRE_PROTOTYPES:U:M${p})
+_fake != env ${mkc.environ} mkc_check_decl -d prototype \
+ ${MKC_PROTOTYPE_FUNC.${p}:Q} ${MKC_PROTOTYPE_HEADERS.${p}}; echo
+MKC_ERR_MSG += "ERROR: prototype test ${p} failed"
+.endif # ${PROTOTYPE.${p}}
+.endfor # p
+
+.undef MKC_CHECK_PROTOTYPES
+.undef MKC_REQUIRE_PROTOTYPES
+
+######################################################
# final assignment
-.if !${MKC_NOAUTO:U0}
-.for i in ${MKC_CFLAGS}
-CFLAGS += ${i}
-.endfor
-.for i in ${MKC_LDADD}
-LDADD += ${i}
-.endfor
-.for i in ${MKC_SRCS}
-SRCS += ${i}
-.endfor
-.endif # .if MKC_AUTO
+.include <mkc_imp.conf-final.mk>
.endif # MKCHECKS == yes
diff --git a/mk/mkc.init.mk b/mk/mkc.init.mk
index 218f57e..3196242 100644
--- a/mk/mkc.init.mk
+++ b/mk/mkc.init.mk
@@ -3,7 +3,7 @@
# Copyright (c) 1988, 1989, 1993 The Regents of the University of California
# Copyright (c) 1988, 1989 by Adam de Boor
# Copyright (c) 1989 by Berkeley Softworks
-# Copyright (c) 2009-2010 by Aleksey Cheusov
+# Copyright (c) 2009-2014 by Aleksey Cheusov
#
# See LICENSE file in the distribution.
############################################################
@@ -26,9 +26,9 @@ DPLIBDIRS.${_dir} = ${OBJDIR_${_dir:T}}
DPLIBDIRS.${_dir} = ${OBJDIR_${_dir:S,/,_,g}}
.endif
.if ${TARGET_OPSYS} == "HP-UX"
-LDFLAGS += ${CFLAGS.cctold}+b ${CFLAGS.cctold}${LIBDIR}
+LDFLAGS0 += ${CFLAGS.cctold}+b ${CFLAGS.cctold}${LIBDIR}
.endif
-LDFLAGS += -L${DPLIBDIRS.${_dir}}
+LDFLAGS0 += -L${DPLIBDIRS.${_dir}}
.endif
.endfor
@@ -107,15 +107,13 @@ init_make_level ?= 0 # for mkc.configure.mk
.if ${.MAKE.LEVEL} == ${init_make_level}
SRCTOP ?= ${.CURDIR}
OBJTOP ?= ${.OBJDIR}
+.export SRCTOP OBJTOP
.endif
###########
-.if exists(${.CURDIR}/Makefile.rec)
-REC_MAKEFILES += ${.CURDIR}/Makefile.rec
+.if exists(${SRCTOP}/Makefile.common)
+.include "${SRCTOP}/Makefile.common"
.endif
-.for dir in ${REC_MAKEFILES}
-.include "${dir}"
-.endfor
.if ${SRCTOP:U} != ${.CURDIR} && exists(${.CURDIR}/../Makefile.inc)
.include "${.CURDIR}/../Makefile.inc"
@@ -175,21 +173,21 @@ SHLIBMODE.OSF1 = ${BINMODE}
SHLIBMODE.Interix = ${BINMODE}
SHLIBMODE ?= ${SHLIBMODE.${TARGET_OPSYS}:U${NONBINMODE}}
-ROOT_GROUP.NetBSD = wheel
-ROOT_GROUP.OpenBSD = wheel
-ROOT_GROUP.FreeBSD = wheel
-ROOT_GROUP.Darwin = wheel
-ROOT_GROUP.DragonFly = wheel
-ROOT_GROUP.MirBSD = wheel
-ROOT_GROUP.HP-UX = bin
-ROOT_GROUP.OSF1 = bin
-ROOT_GROUP.Interix = +Administrators
-ROOR_GROUP.Haiku = root
-
-ROOT_USER.HP-UX = bin
-ROOT_USER.OSF1 = bin
-ROOT_USER.Interix = Administrator
-ROOT_USER.Haiku = user
+ROOT_GROUP.NetBSD = wheel
+ROOT_GROUP.OpenBSD = wheel
+ROOT_GROUP.FreeBSD = wheel
+ROOT_GROUP.Darwin = wheel
+ROOT_GROUP.DragonFly = wheel
+ROOT_GROUP.MirBSD = wheel
+ROOT_GROUP.HP-UX = bin
+ROOT_GROUP.OSF1 = bin
+ROOT_GROUP.Interix = +Administrators
+ROOR_GROUP.Haiku = root
+
+ROOT_USER.HP-UX = bin
+ROOT_USER.OSF1 = bin
+ROOT_USER.Interix = Administrator
+ROOT_USER.Haiku = user
ROOT_USER ?= ${ROOT_USER.${OPSYS}:Uroot}
ROOT_GROUP ?= ${ROOT_GROUP.${OPSYS}:Uroot}
@@ -274,7 +272,7 @@ MKPROFILELIB ?= no
MKINSTALLDIRS ?= yes
-EXPORT_VARNAMES += MKC_CACHEDIR REC_MAKEFILES TARGETS SHORTPRJNAME SRCTOP OBJTOP
+EXPORT_VARNAMES += MKC_CACHEDIR TARGETS SHORTPRJNAME
EXPORT_DYNAMIC ?= no
@@ -283,10 +281,6 @@ DISTCLEANFILES += ${MKC_CACHEDIR}/_mkc_*
.include <mkc_imp.platform.sys.mk>
######
-.SUFFIXES: .a .o .op .os .s .S .c .cc .cpp .cxx .C .F .f .r .m .y .l .cl .p .h
-
-.LIBS: .a
-
.if ${MKPIE:U:tl} == "yes"
LDFLAGS.prog += ${LDFLAGS.pie}
CFLAGS += ${CFLAGS.pie}
@@ -304,6 +298,7 @@ LDFLAGS.prog += ${LDFLAGS.relro}
.if ${USE_FORT:U:tl} == "yes"
CPPFLAGS += -D_FORTIFY_SOURCE=2
+CFLAGS += -O
.endif
SHRTOUT ?= no
@@ -326,25 +321,21 @@ MESSAGE.ar ?= @${_MESSAGE} "AR: ${.TARGET}"
AS ?= as
AFLAGS ?=
COMPILE.s ?= ${_V} ${CC_PREFIX} ${CC} ${AFLAGS} -c
-LINK.s ?= ${_V} ${CC} ${AFLAGS} ${LDFLAGS}
MESSAGE.s ?= @${_MESSAGE} "AS: ${.IMPSRC}"
CC ?= cc
CFLAGS ?=
COMPILE.c ?= ${_V} ${CC_PREFIX} ${CC} ${CFLAGS} ${CPPFLAGS} ${CFLAGS.warnerr} -c
-LINK.c ?= ${_V} ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} ${LDFLAGS.prog}
MESSAGE.c ?= @${_MESSAGE} "CC: ${.IMPSRC}"
CXX ?= c++
CXXFLAGS += ${CFLAGS}
COMPILE.cc ?= ${_V} ${CXX_PREFIX} ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${CFLAGS.warnerr} -c
-LINK.cc ?= ${_V} ${CXX} ${CXXFLAGS} ${CPPFLAGS} ${LDFLAGS} ${LDFLAGS.prog}
MESSAGE.cc ?= @${_MESSAGE} "CXX: ${.IMPSRC}"
OBJC ?= ${CC}
OBJCFLAGS ?= ${CFLAGS}
COMPILE.m ?= ${_V} ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c
-LINK.m ?= ${_V} ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} ${LDFLAGS}
MESSAGE.m ?= @${_MESSAGE} "OBJC: ${.IMPSRC}"
CPP ?= cpp
@@ -354,13 +345,10 @@ FC ?= f77
FFLAGS ?= -O
RFLAGS ?=
COMPILE.f ?= ${_V} ${FC} ${FFLAGS} -c
-LINK.f ?= ${_V} ${FC} ${FFLAGS} ${LDFLAGS}
MESSAGE.f ?= @${_MESSAGE} "FC: ${.IMPSRC}"
COMPILE.F ?= ${_V} ${FC} ${FFLAGS} ${CPPFLAGS} -c
-LINK.F ?= ${_V} ${FC} ${FFLAGS} ${CPPFLAGS} ${LDFLAGS}
MESSAGE.F ?= ${MESSAGE.f}
COMPILE.r ?= ${_V} ${FC} ${FFLAGS} ${RFLAGS} -c
-LINK.r ?= ${_V} ${FC} ${FFLAGS} ${RFLAGS} ${LDFLAGS}
MESSAGE.r ?= ${MESSAGE.f}
MESSAGE.ld ?= @${_MESSAGE} "LD: ${.TARGET}"
@@ -393,7 +381,6 @@ MKDIR ?= mkdir
PC ?= pc
PFLAGS ?=
COMPILE.p ?= ${_V} ${PC} ${PFLAGS} ${CPPFLAGS} -c
-LINK.p ?= ${_V} ${PC} ${PFLAGS} ${CPPFLAGS} ${LDFLAGS}
MESSAGE.p ?= @${_MESSAGE} "PC: ${.IMPSRC}"
SHELL ?= sh
@@ -424,84 +411,7 @@ RM ?= rm
#READELF ?= readelf
#STRINGS ?= strings
-# C
_PN = ${PROJECTNAME} # short synonym
-
-.c.o:
- ${MESSAGE.c}
- ${COMPILE.c} ${CPPFLAGS_${_PN}} ${CFLAGS_${_PN}} \
- ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.c.op:
- ${MESSAGE.c}
- ${COMPILE.c} -pg ${CPPFLAGS_${_PN}} ${CFLAGS_${_PN}} \
- ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.c.os:
- ${MESSAGE.c}
- ${COMPILE.c} ${CFLAGS.pic} ${CPPFLAGS_${_PN}} \
- ${CFLAGS_${_PN}} ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-
-# C++
-.cc.o .cpp.o .cxx.o .C.o:
- ${MESSAGE.cc}
- ${COMPILE.cc} ${CPPFLAGS_${_PN}} ${CXXFLAGS_${_PN}} \
- ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.cc.op .C.op .cpp.op:
- ${MESSAGE.cc}
- ${COMPILE.cc} -pg ${CPPFLAGS_${_PN}} ${CXXFLAGS_${_PN}} \
- ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.cc.os .C.os .cpp.os:
- ${MESSAGE.cc}
- ${COMPILE.cc} ${CXXFLAGS.pic} ${CPPFLAGS_${_PN}} \
- ${CXXFLAGS_${_PN}} ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-
-# Fortran/Ratfor
-.f.o:
- ${MESSAGE.f}
- ${COMPILE.f} ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.f.op:
- ${MESSAGE.f}
- ${COMPILE.f} -pg ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-.f.os:
- ${MESSAGE.f}
- ${COMPILE.f} ${FFLAGS.pic} ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
-
-#.F:
-.F.o:
- ${MESSAGE.F}
- ${COMPILE.F} -o ${.TARGET} ${.IMPSRC}
-
-#.r:
-.r.o:
- ${MESSAGE.r}
- ${COMPILE.r} -o ${.TARGET} ${.IMPSRC}
-
-# Pascal
-.p.o:
- ${MESSAGE.p}
- ${COMPILE.p} -o ${.TARGET} ${.IMPSRC}
-
-# Assembly
-.S.o .s.o:
- ${MESSAGE.s}
- ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
-.S.op .s.op:
- ${MESSAGE.s}
- ${COMPILE.s} -o ${.TARGET} -pg ${.IMPSRC}
-.S.os .s.os:
- ${MESSAGE.s}
- ${COMPILE.s} ${CAFLAGS.pic} -o ${.TARGET} ${.IMPSRC}
-
-# Objective-C
-.m.o:
- ${MESSAGE.m}
- ${COMPILE.m} ${.IMPSRC}
-.m.op:
- ${MESSAGE.m}
- ${COMPILE.m} -pg -o ${.TARGET} ${.IMPSRC}
-.m.os:
- ${MESSAGE.m}
- ${COMPILE.m} ${CMFLAGS.pic} -o ${.TARGET} ${.IMPSRC}
-
# Lex
LPREFIX ?= yy
.if ${LPREFIX} != "yy"
@@ -509,87 +419,9 @@ LFLAGS += -P${LPREFIX}
.endif
LEXLIB ?= -ll
-.l.c:
- ${MESSAGE.l}
- ${LEX.l} -t ${.IMPSRC} > ${.TARGET}
-
# Yacc
YFLAGS += ${YPREFIX:D-p${YPREFIX}} ${YHEADER:D-d}
-.y.h: ${.TARGET:R}.c
-.y.c:
- ${MESSAGE.y}
- ${YACC.y} ${.IMPSRC}
- ${_V}mv y.tab.c ${.TARGET}
-.ifdef YHEADER
- ${_V}mv y.tab.h ${.TARGET:R}.h
-.endif
-
-###########
-.include <mkc_imp.obj.mk>
-
-###########
-.if !empty(_srcsall:U:M*.y)
-MKC_REQUIRE_PROGS += ${YACC:[1]}
-MKC_PROG.id.${YACC:[1]:S/+/x/g} = yacc
-.endif
-
-.if !empty(_srcsall:U:M*.l)
-MKC_REQUIRE_PROGS += ${LEX:[1]}
-MKC_PROG.id.${LEX:[1]:S/+/x/g} = lex
-.endif
-
-.if !empty(_srcsall:U:M*.c) || !empty(_srcsall:U:M*.l) || !empty(_srcsall:U:M*.y)
-MKC_REQUIRE_PROGS += ${CC:[1]}
-MKC_PROG.id.${CC:[1]:S|+|x|g} = cc
-.endif
-
-.if !empty(_srcsall:U:M*.cc) || !empty(_srcsall:U:M*.C) || !empty(_srcsall:U:M*.cxx) || !empty(_srcsall:U:M*.cpp)
-MKC_REQUIRE_PROGS += ${CXX:[1]}
-MKC_PROG.id.${CXX:[1]:S/+/x/g} = cxx
-.endif
-
-.if !empty(_srcsall:U:M*.f)
-MKC_REQUIRE_PROGS += ${FC:[1]}
-MKC_PROG.id.${FC:[1]:S/+/x/g} = fc
-.endif
-
-.if !empty(_srcsall:U:M*.p)
-MKC_REQUIRE_PROGS += ${PC:[1]}
-MKC_PROG.id.${PC:[1]:S/+/x/g} = pc
-.endif
-
-###########
-.PHONY : print-values
-print-values :
-.for v in ${VARS}
- @printf "%s=%s\n" ${v} ${${v}:Q}
-.endfor
-
-.PHONY : print-values2
-print-values2 :
-.for v in ${VARS}
- @printf "%s\n" ${${v}:Q}
-.endfor
-
-###########
-.PHONY: realall realerrorcheck
-
-__errorcheck: .USE
- @if test -n '${MKC_ERR_MSG}'; then \
- for msg in '' ${MKC_ERR_MSG}; do \
- fn=`printf '%s\n' "$$msg" | sed -n 's/^%%%: //p'`; \
- if test -n "$$fn"; then \
- awk '{print "ERROR: " $$0}' "$$fn"; ex=1; \
- elif test -n "$$msg"; then printf '%s\n' "$$msg"; ex=1; \
- fi; \
- done; \
- exit $$ex; \
- fi
-
-realall : realerrorcheck
-realerrorcheck: __errorcheck
-
###########
.if defined(MKC_REQD) && defined(MKC_VERSION)
@@ -602,73 +434,10 @@ MKCHECKS = no
###########
-LDLIBS = ${LDFLAGS} ${LDADD}
-
-###########
-# skip uninstalling files and creating destination dirs for mkc.subprj.mk
-.if !defined(SUBPRJ)
-
-uninstall:
- -${UNINSTALL} ${UNINSTALLFILES}
-
-installdirs:
- for d in _ ${INSTALLDIRS:O:u:S|/.$||}; do \
- test "$$d" = _ || ${INSTALL} -d -m ${DIRMODE} "$$d"; \
- done
-
-filelist:
- @for d in ${UNINSTALLFILES:O:u}; do \
- echo $$d; \
- done
-
-test:
-
-.endif # SUBPRJ
-
-TARGETS += all all install clean cleandir depend test \
+TARGETS += all install clean cleandir depend test \
installdirs uninstall errorcheck filelist obj
-TARGETS := ${TARGETS:O:u}
-
-# Make sure all of the standard targets are defined, even if they do nothing.
-.PHONY: ${TARGETS} realinstall realinstall2 realall
-${TARGETS} realinstall realinstall2 realall:
-
-distclean: cleandir
-
-all: realall
-
-.if ${MKINSTALLDIRS:tl} == "yes"
-install: installdirs .WAIT realinstall .WAIT realinstall2
-.else
-install: realinstall .WAIT realinstall2
-.endif
-
-
-###########
+TARGETS := ${TARGETS:O:u}
VERBOSE_ECHO ?= echo
-### for mkc.subdir.mk and mkc.subprj.mk
-__recurse: .USE
- @targ=${.TARGET:S/^nodeps-//:C/-.*$//}; \
- dir=${.TARGET:S/^nodeps-//:C/^[^-]*-//}; \
- if ! test -f ${.CURDIR}/$$dir/Makefile; then exit 0; fi; \
- test "$${targ}_${MKINSTALL:tl}" = 'install_no' && exit 0; \
- test "$${targ}_${MKINSTALL:tl}" = 'installdirs_no' && exit 0; \
- ${export_cmd} \
- set -e; \
- ${VERBOSE_ECHO} ================================================== 1>&2;\
- case "$$dir" in /*) \
- ${VERBOSE_ECHO} "$$targ ===> $$dir" 1>&2; \
- cd "$$dir"; \
- env "_THISDIR_=$$dir/" ${MAKE} ${MAKEFLAGS} $$targ; \
- ;; \
- *) \
- ${VERBOSE_ECHO} "$$targ ===> ${_THISDIR_}$$dir" 1>&2; \
- cd "${.CURDIR}/$$dir"; \
- env "_THISDIR_=${_THISDIR_}$$dir/" ${MAKE} ${MAKEFLAGS} $$targ; \
- ;; \
- esac
-
-###########
.endif # __initialized__
diff --git a/mk/mkc_imp.checkprogs.mk b/mk/mkc_imp.checkprogs.mk
new file mode 100644
index 0000000..da5c168
--- /dev/null
+++ b/mk/mkc_imp.checkprogs.mk
@@ -0,0 +1,29 @@
+.if !empty(_srcsall:U:M*.y) && !empty(YACC)
+MKC_REQUIRE_PROGS += ${YACC:[1]}
+MKC_PROG.id.${YACC:[1]:S/+/x/g} = yacc
+.endif
+
+.if !empty(_srcsall:U:M*.l) && !empty(LEX)
+MKC_REQUIRE_PROGS += ${LEX:[1]}
+MKC_PROG.id.${LEX:[1]:S/+/x/g} = lex
+.endif
+
+.if !empty(_srcsall:U:M*.c) || !empty(_srcsall:U:M*.l) || !empty(_srcsall:U:M*.y) && !empty(CC)
+MKC_REQUIRE_PROGS += ${CC:[1]}
+MKC_PROG.id.${CC:[1]:S|+|x|g} = cc
+.endif
+
+.if !empty(_srcsall:U:M*.cc) || !empty(_srcsall:U:M*.C) || !empty(_srcsall:U:M*.cxx) || !empty(_srcsall:U:M*.cpp) && !empty(CXX)
+MKC_REQUIRE_PROGS += ${CXX:[1]}
+MKC_PROG.id.${CXX:[1]:S/+/x/g} = cxx
+.endif
+
+.if !empty(_srcsall:U:M*.f) && !empty(FC)
+MKC_REQUIRE_PROGS += ${FC:[1]}
+MKC_PROG.id.${FC:[1]:S/+/x/g} = fc
+.endif
+
+.if !empty(_srcsall:U:M*.p) && !empty(PC)
+MKC_REQUIRE_PROGS += ${PC:[1]}
+MKC_PROG.id.${PC:[1]:S/+/x/g} = pc
+.endif
diff --git a/mk/mkc_imp.conf-final.mk b/mk/mkc_imp.conf-final.mk
new file mode 100644
index 0000000..eeff5b1
--- /dev/null
+++ b/mk/mkc_imp.conf-final.mk
@@ -0,0 +1,49 @@
+# Copyright (c) 2014, Aleksey Cheusov <vle@gmx.net>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# MKC_AUTO_* variables are for debugging purposes only
+MKC_AUTO_CPPFLAGS := ${MKC_AUTO_CPPFLAGS} ${MKC_CPPFLAGS}
+MKC_AUTO_CFLAGS := ${MKC_AUTO_CFLAGS} ${MKC_CFLAGS}
+MKC_AUTO_LDADD := ${MKC_AUTO_LDADD} ${MKC_LDADD}
+MKC_AUTO_SRCS := ${MKC_AUTO_SRCS} ${MKC_SRCS}
+
+.if !${MKC_NOAUTO:U0}
+.for i in ${MKC_CPPFLAGS}
+CPPFLAGS += ${i}
+.endfor
+.for i in ${MKC_CFLAGS}
+CFLAGS += ${i}
+.endfor
+.for i in ${MKC_LDADD}
+LDADD += ${i}
+.endfor
+.for i in ${MKC_SRCS}
+SRCS += ${i}
+.endfor
+.endif # .if MKC_AUTO
+
+.undef MKC_CPPFLAGS
+.undef MKC_CFLAGS
+.undef MKC_LDADD
+.undef MKC_SRCS
diff --git a/mk/mkc_imp.final.mk b/mk/mkc_imp.final.mk
index e7fdb49..1b96da3 100644
--- a/mk/mkc_imp.final.mk
+++ b/mk/mkc_imp.final.mk
@@ -6,6 +6,8 @@
.ifndef MKC_IMP.FINAL.MK
MKC_IMP.FINAL.MK = 1
+.PATH: ${SRC_PATHADD}
+
LDADD += ${DPLIBS} # DPLIBS is deprecated (2012-08-13)
LDADD += ${LDADD_${PROJECTNAME}}
diff --git a/mk/mkc_imp.lib.mk b/mk/mkc_imp.lib.mk
index b7977f6..2ff6ab4 100644
--- a/mk/mkc_imp.lib.mk
+++ b/mk/mkc_imp.lib.mk
@@ -40,6 +40,10 @@ OBJS += ${SRCS:N*.h:N*.sh:T:R:S/$/.o/g}
SOBJS = ${OBJS:.o=.os}
POBJS = ${OBJS:.o=.op}
+.if !empty(SRCS:N*.h:N*.sh:M*/*:H)
+SRC_PATHADD += ${SRCS:N*.h:N*.sh:M*/*:H}
+.endif
+
.if ${MKSTATICLIB:tl} != "no"
_LIBS += lib${LIB}.a
.endif
@@ -98,7 +102,7 @@ ${SHLIBFN}: ${SOBJS} ${DPADD}
@${RM} -f ${.TARGET}
@${_MESSAGE} "LD: ${.TARGET}"
${_V} $(LDREAL) ${LDFLAGS.shlib} -o ${.TARGET} \
- ${SOBJS} ${LDFLAGS} ${LDADD}
+ ${SOBJS} ${LDFLAGS0} ${LDADD0} ${LDFLAGS} ${LDADD}
.if ${OBJECT_FMT} == "ELF" && ${MKDLL:tl} == "no"
@${LN_S} -f ${SHLIBFN} lib${LIB}${SHLIB_EXT}
@${LN_S} -f ${SHLIBFN} lib${LIB}${SHLIB_EXT1}
diff --git a/mk/mkc_imp.mk b/mk/mkc_imp.mk
index eee09fd..1979748 100644
--- a/mk/mkc_imp.mk
+++ b/mk/mkc_imp.mk
@@ -22,8 +22,83 @@ _use_prog := 1
.endif # _use_prog || LIB
.include <mkc.init.mk>
+.include <mkc_imp.rules.mk>
+.include <mkc_imp.obj.mk>
+# Make sure all of the standard targets are defined, even if they do nothing.
+.PHONY: ${TARGETS} realinstall realinstall2 realall
+${TARGETS} realinstall realinstall2 realall:
+
+distclean: cleandir
+
+all: realall
+
+.if ${MKINSTALLDIRS:tl} == "yes"
+install: installdirs .WAIT realinstall .WAIT realinstall2
+.else
+install: realinstall .WAIT realinstall2
+.endif
+
+# skip uninstalling files and creating destination dirs for mkc.subprj.mk
+.if !defined(SUBPRJ)
+
+uninstall:
+ -${UNINSTALL} ${UNINSTALLFILES}
+
+installdirs:
+ for d in _ ${INSTALLDIRS:O:u:S|/.$||}; do \
+ test "$$d" = _ || ${INSTALL} -d -m ${DIRMODE} "$$d"; \
+ done
+
+filelist:
+ @for d in ${UNINSTALLFILES:O:u}; do \
+ echo $$d; \
+ done
+
+test:
+
+.endif # SUBPRJ
+
+###########
+.PHONY : print-values
+print-values :
+.for v in ${VARS}
+ @printf "%s=%s\n" ${v} ${${v}:Q}
+.endfor
+
+.PHONY : print-values2
+print-values2 :
+.for v in ${VARS}
+ @printf "%s\n" ${${v}:Q}
+.endfor
+
+###########
+.PHONY: realall realerrorcheck
+
+__errorcheck: .USE
+ @if test -n '${MKC_ERR_MSG}'; then \
+ for msg in '' ${MKC_ERR_MSG}; do \
+ fn=`printf '%s\n' "$$msg" | sed -n 's/^%%%: //p'`; \
+ if test -n "$$fn"; then \
+ awk '{print "ERROR: " $$0}' "$$fn"; ex=1; \
+ elif test -n "$$msg"; then printf '%s\n' "$$msg"; ex=1; \
+ fi; \
+ done; \
+ exit $$ex; \
+ fi
+
+realall : realerrorcheck
+realerrorcheck: __errorcheck
+
+.include <mkc_imp.checkprogs.mk>
+.include <configure.mk>
+
+# features
+.for f in ${MKC_FEATURES}
+.include <mkc_imp.f_${f}.mk>
+.endfor
.include <configure.mk>
+CFLAGS += ${MKC_FEATURES:D-I${FEATURESDIR}}
.if !defined(MKC_ERR_MSG) || make(clean) || make(cleandir) || make(distclean)
diff --git a/mk/mkc_imp.objdir.mk b/mk/mkc_imp.objdir.mk
index 98c8039..37ebf5c 100644
--- a/mk/mkc_imp.objdir.mk
+++ b/mk/mkc_imp.objdir.mk
@@ -5,7 +5,6 @@
.if !defined(_MKC_IMP_OBJDIR_MK)
_MKC_IMP_OBJDIR_MK := 1
-
.if ${:!if test -d ${.CURDIR}/obj.${MACHINE}; then echo 1; else echo 0; fi!}
_OBJ_MACHINE_DIR := 1
.elif ${:!if test -d ${.CURDIR}/obj; then echo 1; else echo 0; fi!}
diff --git a/mk/mkc_imp.pkg-config.mk b/mk/mkc_imp.pkg-config.mk
index 60190b9..a77073a 100644
--- a/mk/mkc_imp.pkg-config.mk
+++ b/mk/mkc_imp.pkg-config.mk
@@ -1,33 +1,25 @@
-# Copyright (c) 2009-2010 by Aleksey Cheusov
+# Copyright (c) 2009-2014 by Aleksey Cheusov
#
# See LICENSE file in the distribution.
############################################################
-#
-# Sample of Makefile:
-# PKG_CONFIG_DEPS = glib-2.0>=2.22
-#
-# PROG = main
-#
-# CFLAGS+= -DG_DISABLE_DEPRECATED=1
-# CFLAGS+= -DG_DISABLE_SINGLE_INCLUDES
-#
-# .include <mkc.prog.mk>
-#
-
-############################################################
-
-# .endif for the next line is in the end of file
-.if defined(PKG_CONFIG_DEPS) && !make(clean) && !make(cleandir) && !make(distclean)
+.if defined(PKG_CONFIG_DEPS) # PKG_CONFIG_DEPS -- deprecated 2014.01.15
+MKC_REQUIRE_PKGCONFIG += ${PKG_CONFIG_DEPS}
+.endif
+.if defined(MKC_REQUIRE_PKGCONFIG)
+MKC_CHECK_PKGCONFIG += ${MKC_REQUIRE_PKGCONFIG}
+.endif
+.if defined(MKC_CHECK_PKGCONFIG) && !make(clean) && !make(cleandir) && !make(distclean)
MKC_REQUIRE_PROGS+= pkg-config
.include <configure.mk>
.if ${HAVE_PROG.pkg-config}
-.for l in ${PKG_CONFIG_DEPS}
+.for l in ${MKC_CHECK_PKGCONFIG:O:u}
_lpair = ${l:C/(>=|<=|=|>|<)/ & /g}
-_pcname = ${PCNAME.${_lpair:[1]:S/-/_/g:S/+/p/g:S/./_/g}:U${_lpair:[1]}}
+_id = ${_lpair:[1]}
+_pcname = ${PCNAME.${_id:S/-/_/g:S/+/p/g:S/./_/g}:U${_id}}
_lp := ${_pcname} ${_lpair:[2]} ${_lpair:[3]}
_ln = ${l:S/>=/_ge_/:S/>/_gt_/:S/<=/_le_/:S/</_lt_/:S/=/_eq_/}
@@ -35,10 +27,7 @@ PKG_CONFIG.exists.${_ln} != env ${mkc.environ} mkc_check_custom \
-p pkgconfig -s -n '${_ln}' -m '[pkg-config] ${_lp}' \
${PROG.pkg-config} --print-errors --exists "${_lp}"
-.if !${PKG_CONFIG.exists.${_ln}}
-MKC_ERR_MSG := ${MKC_ERR_MSG} "%%%: ${MKC_CACHEDIR}/_mkc_pkgconfig_${_ln}.err"
-.else
-
+.if ${PKG_CONFIG.exists.${_ln}}
# --cflags and --libs
.if defined(PROGS) || defined(LIB)
.if !defined(CPPFLAGS.pkg-config.${_ln})
@@ -53,8 +42,8 @@ LDADD.pkg-config.${_ln} != env ${mkc.environ} mkc_check_custom \
${PROG.pkg-config} --libs "${_lp}"
.endif # LDADD.pkg-config.${l}
-CPPFLAGS := ${CPPFLAGS} ${CPPFLAGS.pkg-config.${_ln}}
-LDADD := ${LDADD} ${LDADD.pkg-config.${_ln}}
+MKC_CPPFLAGS += ${CPPFLAGS.pkg-config.${_ln}}
+MKC_LDADD += ${LDADD.pkg-config.${_ln}}
.endif # PROGS || LIB
.for i in ${PKG_CONFIG_VARS.${_ln}}
@@ -65,15 +54,26 @@ PKG_CONFIG.var.${_ln}.${i} != env ${mkc.environ} mkc_check_custom \
.endif # PKG_CONFIG.var.${_ln}.${i}
.endfor # i
+MKC_CFLAGS += -DHAVE_PKCONFIG_${_id:S/-/_/g:S/+/P/g:S/./_/g}=1
+
+.elif !empty(MKC_REQUIRE_PKGCONFIG:M${l})
+MKC_ERR_MSG := ${MKC_ERR_MSG} "%%%: ${MKC_CACHEDIR}/_mkc_pkgconfig_${_ln}.err"
.endif # PKG-CONFIG.exists
-.endfor # .for l in PKG_CONFIG_DEPS
+.endfor # .for l in MKC_CHECK_PKGCONFIG
+
+######################################################
+.include <mkc_imp.conf-final.mk>
+
.undef PKG_CONFIG_DEPS
+.undef MKC_CHECK_PKGCONFIG
+.undef MKC_REQUIRE_PKGCONFIG
-.undef _ln
-.undef _lp
-.undef _pcname
.undef _lpair
+.undef _id
+.undef _pcname
+.undef _lp
+.undef _ln
.endif # HAVE_PROG.pkg-config
diff --git a/mk/mkc_imp.platform.sys.mk b/mk/mkc_imp.platform.sys.mk
index 0fb511f..bbf5aac 100644
--- a/mk/mkc_imp.platform.sys.mk
+++ b/mk/mkc_imp.platform.sys.mk
@@ -16,7 +16,7 @@ _MKC_PLATFORM_MK := 1
CFLAGS.sysroot ?= --sysroot=${SYSROOT}
LDFLAGS.sysroot ?= --sysroot=${SYSROOT}
CFLAGS += ${CFLAGS.sysroot}
-LDFLAGS += ${LDFLAGS.sysroot}
+LDFLAGS0 += ${LDFLAGS.sysroot}
TOOLCHAIN_PREFIX ?= ${MACHINE_GNU_PLATFORM}-
TOOLCHAIN_DIR ?= ${TOOLDIR}/bin
@@ -63,29 +63,8 @@ INSTALL ?= ${INSTALL.${TARGET_OPSYS}:Umkc_install}
####################
-.if !defined(CC.SunOS)
-.if exists(/usr/ccs/bin/cc)
-CC.SunOS = /usr/ccs/bin/cc
-.elif exists(/opt/SUNWspro/bin/cc)
-CC.SunOS = /opt/SUNWspro/bin/cc
-.elif exists(/usr/sfw/bin/gcc)
-CC.SunOS = /usr/sfw/bin/gcc
-.else
CC.SunOS = cc
-.endif # exists...
-.endif # defined(CC.SunOS)
-
-.if !defined(CXX.SunOS)
-.if exists(/usr/ccs/bin/CC)
-CXX.SunOS = /usr/ccs/bin/CC
-.elif exists(/opt/SUNWspro/bin/CC)
-CXX.SunOS = /opt/SUNWspro/bin/CC
-.elif exists(/usr/sfw/bin/g++)
-CXX.SunOS = /usr/sfw/bin/g++
-.else
-CXX.SunOS = c++
-.endif # exists...
-.endif # defined(CC.SunOS)
+CXX.SunOS = CC
CPP.SunOS = ${CC} -E
diff --git a/mk/mkc_imp.prog.mk b/mk/mkc_imp.prog.mk
index 65db125..fc4f952 100644
--- a/mk/mkc_imp.prog.mk
+++ b/mk/mkc_imp.prog.mk
@@ -32,14 +32,19 @@ CLEANFILES += ${SRCS.${p}:M*.y:.y=.h}
OBJS.${p} = ${SRCS.${p}:N*.h:N*.sh:N*.fth:T:R:S/$/.o/g}
+.if !empty(SRCS.${p}:N*.h:N*.sh:M*/*:H)
+SRC_PATHADD += ${SRCS:N*.h:N*.sh:M*/*:H}
+.endif
+
.if defined(OBJS.${p}) && !empty(OBJS.${p})
.NOPATH: ${OBJS.${p}}
${p}: ${LIBCRT0} ${DPSRCS.${p}} ${OBJS.${p}} ${LIBC} ${LIBCRTBEGIN} ${LIBCRTEND} ${DPADD}
.if !commands(${p})
${MESSAGE.ld}
- ${_V}${LDREAL} ${LDFLAGS} ${LDFLAGS.prog} ${LDSTATIC} \
- -o ${.TARGET} ${OBJS.${p}} ${LDADD}
+ ${_V}${LDREAL} -o ${.TARGET} ${OBJS.${p}} \
+ ${LDFLAGS0} ${LDADD0} \
+ ${LDFLAGS} ${LDFLAGS.prog} ${LDADD}
.endif # !commands(...)
.endif # defined(OBJS.${p}) && !empty(OBJS.${p})
diff --git a/mk/mkc_imp.rules.mk b/mk/mkc_imp.rules.mk
new file mode 100644
index 0000000..6e5e0cc
--- /dev/null
+++ b/mk/mkc_imp.rules.mk
@@ -0,0 +1,99 @@
+# Copyright (c) 2014 by Aleksey Cheusov
+#
+# See LICENSE file in the distribution.
+############################################################
+.SUFFIXES: .a .o .op .os .s .S .c .cc .cpp .cxx .C .F .f .r .m .y .l .cl .p .h
+
+.LIBS: .a
+
+# C
+
+.c.o:
+ ${MESSAGE.c}
+ ${COMPILE.c} ${CPPFLAGS_${_PN}} ${CFLAGS_${_PN}} \
+ ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.c.op:
+ ${MESSAGE.c}
+ ${COMPILE.c} -pg ${CPPFLAGS_${_PN}} ${CFLAGS_${_PN}} \
+ ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.c.os:
+ ${MESSAGE.c}
+ ${COMPILE.c} ${CFLAGS.pic} ${CPPFLAGS_${_PN}} \
+ ${CFLAGS_${_PN}} ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+
+# C++
+.cc.o .cpp.o .cxx.o .C.o:
+ ${MESSAGE.cc}
+ ${COMPILE.cc} ${CPPFLAGS_${_PN}} ${CXXFLAGS_${_PN}} \
+ ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.cc.op .C.op .cpp.op:
+ ${MESSAGE.cc}
+ ${COMPILE.cc} -pg ${CPPFLAGS_${_PN}} ${CXXFLAGS_${_PN}} \
+ ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.cc.os .C.os .cpp.os:
+ ${MESSAGE.cc}
+ ${COMPILE.cc} ${CXXFLAGS.pic} ${CPPFLAGS_${_PN}} \
+ ${CXXFLAGS_${_PN}} ${COPTS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+
+# Fortran/Ratfor
+.f.o:
+ ${MESSAGE.f}
+ ${COMPILE.f} ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.f.op:
+ ${MESSAGE.f}
+ ${COMPILE.f} -pg ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+.f.os:
+ ${MESSAGE.f}
+ ${COMPILE.f} ${FFLAGS.pic} ${FFLAGS_${_PN}} -o ${.TARGET} ${.IMPSRC}
+
+#.F:
+.F.o:
+ ${MESSAGE.F}
+ ${COMPILE.F} -o ${.TARGET} ${.IMPSRC}
+
+#.r:
+.r.o:
+ ${MESSAGE.r}
+ ${COMPILE.r} -o ${.TARGET} ${.IMPSRC}
+
+# Pascal
+.p.o:
+ ${MESSAGE.p}
+ ${COMPILE.p} -o ${.TARGET} ${.IMPSRC}
+
+# Assembly
+.S.o .s.o:
+ ${MESSAGE.s}
+ ${COMPILE.s} -o ${.TARGET} ${.IMPSRC}
+.S.op .s.op:
+ ${MESSAGE.s}
+ ${COMPILE.s} -o ${.TARGET} -pg ${.IMPSRC}
+.S.os .s.os:
+ ${MESSAGE.s}
+ ${COMPILE.s} ${CAFLAGS.pic} -o ${.TARGET} ${.IMPSRC}
+
+# Objective-C
+.m.o:
+ ${MESSAGE.m}
+ ${COMPILE.m} ${.IMPSRC}
+.m.op:
+ ${MESSAGE.m}
+ ${COMPILE.m} -pg -o ${.TARGET} ${.IMPSRC}
+.m.os:
+ ${MESSAGE.m}
+ ${COMPILE.m} ${CMFLAGS.pic} -o ${.TARGET} ${.IMPSRC}
+
+# Lex
+.l.c:
+ ${MESSAGE.l}
+ ${LEX.l} -t ${.IMPSRC} > ${.TARGET}
+
+# Yacc
+.y.h: ${.TARGET:R}.c
+.y.c:
+ ${MESSAGE.y}
+ ${YACC.y} ${.IMPSRC}
+ ${_V}mv y.tab.c ${.TARGET}
+.ifdef YHEADER
+ ${_V}mv y.tab.h ${.TARGET:R}.h
+.endif
diff --git a/mk/mkc_imp.subprj.mk b/mk/mkc_imp.subprj.mk
index df94d6d..d4beee3 100644
--- a/mk/mkc_imp.subprj.mk
+++ b/mk/mkc_imp.subprj.mk
@@ -16,6 +16,10 @@ __REALSUBPRJ += ${dir}
.endif
.endfor
+.for dir in ${NOSUBDIR}
+NODEPS += *-${dir}:* *:*-${dir} *-*/${dir}:* *:*-*/${dir}
+.endfor
+
.ifndef SUBDIR
__REALSUBPRJ := ${__REALSUBPRJ:O:u}
.endif
@@ -28,15 +32,18 @@ SUBPRJ_DFLT ?= ${__REALSUBPRJ}
.for targ in ${TARGETS}
.for dir in ${__REALSUBPRJ:N.WAIT}
+_ALLTARGDEPS3 += ${targ}-${dir}
.PHONY: nodeps-${targ}-${dir} subdir-${targ}-${dir} ${targ}-${dir}
nodeps-${targ}-${dir}: .MAKE __recurse
${targ}-${dir}: .MAKE __recurse
subdir-${targ}-${dir}: .MAKE __recurse
.if ${SHORTPRJNAME:tl} == "yes" && ${dir} != ${dir:T}
+_ALLTARGDEPS3 += ${targ}-${dir:T}
.PHONY: nodeps-${targ}-${dir:T} subdir-${targ}-${dir:T} ${targ}-${dir:T}
nodeps-${targ}-${dir:T}: nodeps-${targ}-${dir}
${targ}-${dir:T}: ${targ}-${dir}
subdir-${targ}-${dir:T}: subdir-${targ}-${dir}
+_ALLTARGDEPS3 += ${targ}-${dir}:${targ}-${dir:T}
.endif
.endfor # dir
@@ -58,14 +65,22 @@ ${targ}: ${_SUBDIR_${targ}:S/:${targ}$//}
.for dep prj in ${SUBPRJ:M*\:*:S/:/ /}
_ALLTARGDEPS += ${targ}-${dep}:${targ}-${prj}
-.endfor
+.endfor # dep prj
.endfor # targ
.for dir in ${__REALSUBPRJ}
.if ${SHORTPRJNAME:tl} == "yes" && ${dir:T} != ${dir}
-_ALLTARGDEPS += all-${dir}:${dir:T}
-.endif
+SRCDIR_${dir:T} = ${.CURDIR}/${dir}
+EXPORT_VARNAMES += SRCDIR_${dir:T}
+_ALLTARGDEPS += all-${dir}:${dir:T}
+_ALLTARGDEPS3 += ${dir:T}
+.endif # .if ${SHORTPRJNAME:tl} == "yes" ...
+j:=${dir:S,/,_,g}
+.if empty(j:M*[.]*)
+SRCDIR_${j} = ${.CURDIR}/${dir}
+EXPORT_VARNAMES += SRCDIR_${dir:S,/,_,g}
+.endif # .if dir contains .
_ALLTARGDEPS += all-${dir}:${dir}
.endfor # dir
@@ -81,12 +96,35 @@ ${prjtarg}: ${deptarg}
# Make sure all of the standard targets are defined, even if they do nothing.
${TARGETS}:
-.PHONY: output_deps
-output_deps:
-.for i in ${_ALLTARGDEPS} ${_ALLTARGDEPS2}
- @echo ${i}
+.PHONY: print_deps
+print_deps:
+.for i in ${_ALLTARGDEPS} ${_ALLTARGDEPS2} ${_ALLTARGDEPS3} ${TARGETS}
+ @echo ${i:S/:/ /}
.endfor
+__recurse: .USE
+ @targ=${.TARGET:S/^nodeps-//:C/-.*$//}; \
+ dir=${.TARGET:S/^nodeps-//:C/^[^-]*-//}; \
+ if ! test -f ${.CURDIR}/$$dir/Makefile; then exit 0; fi; \
+ test "$${targ}_${MKINSTALL:tl}" = 'install_no' && exit 0; \
+ test "$${targ}_${MKINSTALL:tl}" = 'installdirs_no' && exit 0; \
+ ${export_cmd} \
+ set -e; \
+ ${VERBOSE_ECHO} ================================================== 1>&2;\
+ case "$$dir" in /*) \
+ ${VERBOSE_ECHO} "$$targ ===> $$dir" 1>&2; \
+ cd "$$dir"; \
+ env "_THISDIR_=$$dir/" ${MAKE} ${MAKEFLAGS} $$targ; \
+ ;; \
+ *) \
+ ${VERBOSE_ECHO} "$$targ ===> ${_THISDIR_}$$dir" 1>&2; \
+ cd "${.CURDIR}/$$dir"; \
+ env "_THISDIR_=${_THISDIR_}$$dir/" ${MAKE} ${MAKEFLAGS} $$targ; \
+ ;; \
+ esac
+
+###########
+
.include <mkc_imp.objdir.mk>
.endif # _MKC_IMP_SUBPRJ_MK
diff --git a/mk/mkc_imp.vars.mk.in b/mk/mkc_imp.vars.mk.in
index 2e642e3..2d8c60f 100644
--- a/mk/mkc_imp.vars.mk.in
+++ b/mk/mkc_imp.vars.mk.in
@@ -1,5 +1,6 @@
MKC_VERSION = @version@
BUILTINSDIR ?= @syscustomdir@
+FEATURESDIR ?= @featuresdir@
MKC_LIBEXECDIR = @libexecdir@
MKC_SYSCONFDIR = @sysconfdir@
MKDEP = @mkdep_cmd@
diff --git a/presentation/_mkc_prog_dot.err b/presentation/_mkc_prog_dot.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/presentation/_mkc_prog_dot.err
diff --git a/presentation/_mkc_prog_dot.res b/presentation/_mkc_prog_dot.res
new file mode 100644
index 0000000..f99bbc3
--- /dev/null
+++ b/presentation/_mkc_prog_dot.res
@@ -0,0 +1 @@
+/usr/pkg/bin/dot
diff --git a/presentation/_mkc_prog_dvips.err b/presentation/_mkc_prog_dvips.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/presentation/_mkc_prog_dvips.err
diff --git a/presentation/_mkc_prog_dvips.res b/presentation/_mkc_prog_dvips.res
new file mode 100644
index 0000000..47aba39
--- /dev/null
+++ b/presentation/_mkc_prog_dvips.res
@@ -0,0 +1 @@
+/usr/pkg/bin/dvips
diff --git a/presentation/_mkc_prog_latex.err b/presentation/_mkc_prog_latex.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/presentation/_mkc_prog_latex.err
diff --git a/presentation/_mkc_prog_latex.res b/presentation/_mkc_prog_latex.res
new file mode 100644
index 0000000..591631a
--- /dev/null
+++ b/presentation/_mkc_prog_latex.res
@@ -0,0 +1 @@
+/usr/pkg/bin/latex
diff --git a/presentation/_mkc_prog_ps2pdf.err b/presentation/_mkc_prog_ps2pdf.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/presentation/_mkc_prog_ps2pdf.err
diff --git a/presentation/_mkc_prog_ps2pdf.res b/presentation/_mkc_prog_ps2pdf.res
new file mode 100644
index 0000000..57c9f89
--- /dev/null
+++ b/presentation/_mkc_prog_ps2pdf.res
@@ -0,0 +1 @@
+/usr/pkg/bin/ps2pdf
diff --git a/presentation/presentation.pdf b/presentation/presentation.pdf
new file mode 100644
index 0000000..194fe85
--- /dev/null
+++ b/presentation/presentation.pdf
Binary files differ
diff --git a/presentation/presentation.tex b/presentation/presentation.tex
index f28356b..0a388f3 100644
--- a/presentation/presentation.tex
+++ b/presentation/presentation.tex
@@ -1099,7 +1099,7 @@ hello: ELF 64-bit MSB executable, SPARC V9, relaxed
(MKC\_\{CHECK,REQUIRE\}\_FUNCLIBS and MKC\_SOURCE\_FUNCLIBS)
\item \h{checks for programs} (MKC\_\{CHECK,REQUIRE\}\_PROGS)
\item \h{user's custom checks} (MKC\_\{CHECK,REQUIRE\}\_CUSTOM)
- \item \h{built-in checks} (MKC\_CHECK\_BUILTINS), e.g. endianess,
+ \item \h{built-in checks} (MKC\_CHECK\_BUILTINS), e.g. endianness,
prog\_flex, prog\_bison, prog\_gawk or prog\_gm4)
\end{itemize}
\end{enumerate}
diff --git a/scripts/mk-configure.7.in b/scripts/mk-configure.7.in
index 7b0e4bc..316d6ae 100644
--- a/scripts/mk-configure.7.in
+++ b/scripts/mk-configure.7.in
@@ -2,7 +2,7 @@
.\"
.\" This file contains parts of NetBSD's bsd.README file
.\"
-.\" Copyright (c) 2009-2010 by Aleksey Cheusov (vle@gmx.net)
+.\" Copyright (c) 2009-2014 by Aleksey Cheusov (vle@gmx.net)
.\" Absolutely no warranty.
.\"
.\" ------------------------------------------------------------------
@@ -31,7 +31,9 @@ To get system-specific configuration parameters, mkc.*.mk include
files try to include the file specified by the "MAKECONF"
variable. If MAKECONF is not set, or no such file exists, the system
make configuration file, @sysconfdir@/mk.conf or /etc/mk.conf, is
-included. Unless SRCTOP variable is set, "../Makefile.inc"
+included. If "${SRCTOP}/Makefile.common" file exists it is also included
+by all subprojects.
+Unless SRCTOP variable is set, "../Makefile.inc"
is also included if exists.
These files may define any of the variables described
below. Below in square brackets the default value for variables are specified.
@@ -54,7 +56,7 @@ include files provide the following targets:
.IP all
build everything.
.IP clean
-clean temporary files and directories created while building with a help of
+clean temporary files and directories with a help of
${CLEANFILES_CMD} and ${CLEANDIRS_CMD} commands.
.IP cleandir
remove all of the files removed by the target clean, as
@@ -92,32 +94,6 @@ The target
.I bin_deb
expects debian control files in DEBIAN subdirectory, see examples/hello_files
for the sample.
-.IP "<subdir> and <subdir:T>"
-<subdir> is a subdirectory listed in SUBDIR or SUBPRJ.
-This target is equivalent to all-<subdir> and is provided by
-.BR mkc.subdir.mk " and " mkc.subprj.mk
-only. For details see
-.BR mkc.subdir.mk " or " mkc.subprj.mk
-sections below. <subdir:T> means the last component of the directory.
-This target is created if ${SHORTPRJNAME} is "yes".
-.IP <target>-<subdir>
-runs the specified <target> for the specified <subdir>.
-This target is provided by
-.BR mkc.subdir.mk " and " mkc.subprj.mk
-only. For details see
-.BR mkc.subdir.mk " or " mkc.subprj.mk
-sections below. The target <target>-<subdir:T> is also provided
-if ${SHORTPRJNAME} is "yes".
-.IP "subdir-<target>-<subdir> and nodeps-<target>-<subdir>"
-runs the specified <target> for the specified <subdir> without dependencies.
-These targets are provided by
-.BR mkc.subprj.mk
-only. For details see
-.BR mkc.subprj.mk
-section below.
-Targets subdir-<target>-<subdir:T>
-and nodeps-<target>-<subdir:T> are also provided
-if ${SHORTPRJNAME} is "yes".
.P
.B NOTE:
Commands associated with targets
@@ -294,6 +270,11 @@ rm(1) tool.
List section sizes and total size.
.RI < Iu >
.RI [ size ]
+.IP SRC_PATHADD
+List of directories added to
+.IR .PATH .
+.RI < Im >
+.RI [ "" ]
.IP STRIP
Discard symbols from object files.
.RI < Iu >
@@ -710,6 +691,9 @@ libraries, use:
.RI < "U" >
.IP LDADD_<project>
Similar to LDADD but for project ${PROJECTNAME}.
+.IP LDADD0
+The same as LDADD but LDFLAGS0 and LDADD0 are passed to the linker before LDFLAGS and LDADD.
+.RI < "M" >
.IP LDFLAGS
Additional linker flags. Often used for specifying library directories.
.VS
@@ -718,6 +702,11 @@ Additional linker flags. Often used for specifying library directories.
.RI < "Mu I" >
.IP LDFLAGS_<project>
Similar to LDFLAGS but for project ${PROJECTNAME}.
+.IP LDFLAGS0
+The same as LDFLAGS but LDFLAGS0 and LDADD0 are passed to the linker before LDFLAGS and LDADD.
+Normally LDFLAGS0 and LDADD0 should be modified in makefiles and should not
+be set from environment by user.
+.RI < "M" >
.IP "BINDIR, BINMODE, BINOWN and BINGRP"
See
.IR "Common variables " and " mkc.files.mk"
@@ -923,6 +912,9 @@ and all its dependencies while
See
.I examples/hello_dictd
subdirectory for the sample of use.
+.P
+.B mkc.subprj.mk
+provides the following variables:
.IP SUBPRJ
List of subprojects (subdirectories) and dependencies. If the
subdirectory doesn't exist the subproject becomes "virtual" and may be
@@ -934,8 +926,6 @@ The default is all projects listed in SUBPRJ.
.RI < "IMu" >
.IP EXPORT_VARNAMES
List of variables to export before running make for subdirectories.
-By default MKC_CACHEDIR variable is exported. As a result cache files
-for subprojects are created in a top-level directory.
.RI < "Mu" >
.RI [ MKC_CACHEDIR ]
.IP NOEXPORT_VARNAMES
@@ -962,6 +952,12 @@ Value of ${.OBJDIR} inside
subdirectory. Slash symbols inside <dir> are replaced with underlines.
In addition, OBJDIR_<dir:T> variable is set to ${OBJDIR_<dir>}
if ${SHORTPRJNAME} is "yes".
+.IP SRCDIR_<dir>
+Value of ${.CURDIR} inside
+.I dir
+subdirectory. Slash symbols inside <dir> are replaced with underlines.
+In addition, SRCDIR_<dir:T> variable is set to ${SRCDIR_<dir>}
+if ${SHORTPRJNAME} is "yes".
.IP TARGETS
List of recursive targets supported by the project and all its subprojects.
.RI < "Im" >
@@ -980,6 +976,26 @@ are used. Unlike MAKEOBJDIRPREFIX object directories do not contain
top-level ${.CURDIR} in paths.
.RI < "Iu" >
.RI [ no ]
+.P
+.B mkc.subprj.mk
+provides the following targets:
+.IP "<subdir> and <subdir:T>"
+<subdir> is a subdirectory listed in SUBDIR or SUBPRJ.
+This target is equivalent to all-<subdir>.
+<subdir:T> means the last component of the directory
+and is created if ${SHORTPRJNAME} is "yes".
+.IP <target>-<subdir>
+Runs the specified <target> for the specified <subdir>.
+The target <target>-<subdir:T> is provided
+if ${SHORTPRJNAME} is "yes".
+.IP "subdir-<target>-<subdir> and nodeps-<target>-<subdir>"
+Runs the specified <target> for the specified <subdir> without dependencies.
+Targets subdir-<target>-<subdir:T>
+and nodeps-<target>-<subdir:T> are provided
+if ${SHORTPRJNAME} is "yes".
+.IP print_deps
+Outputs the dependency graph on targets in tsort(1) format
+taking NODEPS and NOSUBDIR variables into account.
.SS "mkc.subdir.mk"
The include file
.B mkc.subdir.mk
@@ -1097,6 +1113,15 @@ added to SRCS unless MKC_NOAUTO=1.
Res: SRCS+= getline.c
HAVE_FUNCLIB.getline= 0
.VE
+.IP "MKC_SOURCE_DIR, MKC_SOURCE_DIR.<source>"
+Directory with sources for MKC_SOURCE_FUNCLIBS. If MKC_SOURCE_DIR.<source> is unset,
+MKC_SOURCE_DIR is used that defaults to ${.CURDIR}.
+.VS
+ Ex: MKC_SOURCE_FUNCLIBS += getline
+ MKC_SOURCE_DIR.getline.c = ${.CURDIR}/../missing
+ Res: SRCS+= ${.CURDIR}/../missing/getline.c
+ HAVE_FUNCLIB.getline= 0
+.VE
.IP MKC_CHECK_DEFINES
List of define:header to check. <header> part is optional.
@@ -1215,7 +1240,7 @@ treated as a fatal error (See
target.
.IP MKC_CHECK_FUNCS<N>
List of <func>:<header> to be check. <header> part is optional.
-
+Here <N> means the number of arguments.
As a result of the check bmake's variable
HAVE_FUNC<N>.<func>.<header> (or HAVE_FUNC<N>.<func>)
is set to either 0 or 1.
@@ -1248,7 +1273,6 @@ MKC_CUSTOM_FN.<custom_check_name> is a
for your custom check,
e.g., filename.c, filename.cc, subdir/filename.cxx, filename.C,
filename.cpp, mychecks/filename.f or subdir/executable_script.
-
.B mk-configure
tries to compile or run the specified file and sets
CUSTOM.<custom_check_name> variable to 1, 0 or other value.
@@ -1306,8 +1330,8 @@ as
.BR prog_mkdep ", " prog_nbmkdep
Find traditional BSD mkdep(1) or recent NetBSD version of it respectively.
.TP
-.B endianess
-BUILTIN.endianess variable is set to either
+.B endianness
+BUILTIN.endianness variable is set to either
.IR little ", " big " or " unknown
depending on a hardware.
.RE
@@ -1366,6 +1390,33 @@ unless MKC_NOAUTO is set to 1
-DSIZEOF_LONG_LONG=4 \\
-DSIZEOF_OFF_T_SYS_TYPES_H=8
.VE
+.IP MKC_CHECK_PROTOTYPES
+A list of checks (list of names) for C function prototypes.
+MKC_PROTOTYPE_FUNC.<name> is a C function prototype.
+MKC_PROTOTYPE_HEADERS.<name> is a list of headers to #include.
+mk-configure verifies that the specified prototype is correct and if
+so, HAVE_PROTOTYPE.<name> bmake variable is set to 1 and
+-DHAVE_PROTOTYPE_<NAME>=1 is added to CFLAGS unless MKC_NOAUTO is set to 1.
+Otherwise, HAVE_PROTOTYPE.<name> variable is set to 0.
+.VS
+Ex.
+ MKC_CHECK_PROTOTYPES = posix_iconv const_iconv
+ MKC_PROTOTYPE_FUNC.posix_iconv = \
+ size_t iconv(iconv_t,char**,size_t*,char**,size_t*)
+ MKC_PROTOTYPE_FUNC.const_iconv = \
+ size_t iconv(iconv_t,const char**,size_t*,char**,size_t*)
+ MKC_PROTOTYPE_HEADERS.posix_iconv = iconv.h
+ MKC_PROTOTYPE_HEADERS.const_iconv = iconv.h
+Res.
+ HAVE_PROTOTYPE.posix_iconv=0
+ HAVE_PROTOTYPE.const_iconv=1
+ CFLAGS += -DHAVE_PROTOTYPE_CONST_ICONV=1
+.VE
+.IP MKC_REQUIRE_PROTOTYPES
+The same as MKC_CHECK_PROTOTYPES, but incorrect prototype is
+treated as a fatal error (See
+.B errorcheck
+target.
.IP MKC_NOAUTO_FUNCLIBS
See MKC_CHECK_FUNCLIBS
.IP MKC_NOAUTO
@@ -1394,11 +1445,10 @@ The same as MKC_COMMON_DEFINES but only for OPSYS (uname -s).
.IP MKC_CACHEDIR
Directory where intermediate and cache files are created.
It defaults to ${.OBJDIR}.
-.\" Setting this variable to something common for huge amount of
-.\" projects can save lots of time/energy wasted on unnecessary
-.\" rechecking. Idea: to use hash from options passed to compiler
-.\" for calculating the cache directory
-.\" ( remove -Wxxx etc. + sort + uniq + crc32/md5/...).
+By default MKC_CACHEDIR variable is exported for subprojects.
+As a result cache files
+for subprojects are created in the top-level directory.
+If cache directory doesn't exist, it is created automatically.
.IP MKC_SHOW_CACHED
Setting it to 0 will hide
.VS
@@ -1410,8 +1460,66 @@ If set to 1, temporary files are removed.
.IP MKC_NOCACHE
All results are cached unless MKC_NOCACHE variable is set
non-empty value
-.SS "mkc_imp.scripts.mk"
-.B mkc_imp.scripts.mk
+.IP MKC_FEATURES
+This is a list of "features" required by project. In general, a feature
+is something that has problems with portability. This may be a
+function name or header missing on some platforms, for example.
+What developer
+needs to do is to add FEATURENAME to MKC_FEATURES variable and add
+#include <mkc_FEATURENAME.h> where it is needed. Internally, system
+requiremets are checked in the automatically included
+mkc_imp.f_FEATURENAME.mk
+file and all required actions (includes, define checks etc.)
+are made in mkc_FEATURENAME.h header file.
+Currently the following features are provided:
+.RS
+.TP
+.B strlcat
+This feature corresponds to strlcat(3) function available on almost
+all systems except glibc-based Linux-es. mkc_imp.f_strlcat.mk checks
+whether strlcat declaration is available in string.h and
+implementation is available in libc. If not, strlcat.c provided by
+mk-configure is added to SRCS and declaration is provided in
+mkc_strlcat.h header.
+.TP
+.B strlcpy
+The same as strlcat.
+.TP
+.B getline
+This feature corresponds to getline(3) function which is a part of POSIX2008
+unavailable on some
+systems. mkc_imp.f_getline.mk checks
+whether getline declaration is available in stdio.h and
+implementation is available in libc. If not, getline.c provided by
+mk-configure is added to SRCS and declaration is provided in
+mkc_getline.h header.
+.TP
+.B libm
+This feature checks whether libm is available and if yes, adds -lm to
+LDADD. Most UNIX-like systems have libm but Haiku, for example, does
+not. mkc_imp.f_libm.mk checks whether libm library is available and if yes,
+-lm is added to LDADD.
+.TP
+.B libdl
+This feature checks whether libdl library is available and dlopen(3)
+is declared in dlfcn.h. If yes, -ldl is added to LDADD. mkc_libdl.h
+provides declarations for dlopen(3), dlsym(3), dlclose(3) etc.
+.TP
+.B "RB SPLAY"
+BSD systems provide sys/tree.h header where RB_* and SPLAY_* macroses
+are defined for red-black tree and splay. These features check whether
+sys/tree.h and appropriate macroses are available. If yes, mkc_RB.h
+and mkc_SPLAY.h include system-wide sys/tree.h, otherwise NetBSD
+version of sys/tree.h provided by mk-configure is included.
+.TP
+.B "SLIST SIMPLEQ STAILQ LIST TAILQ CIRCLEQ"
+BSD systems provide sys/queue.h header where SLIST_* etc. macroses are
+defined for lists and queues. These features check whether sys/queue.h
+and appropriate macroses are available. If yes, mkc_SLIST.h and others
+include system-wide sys/queue.h, otherwise NetBSD version of
+sys/queue.h provided by mk-configure is included.
+.RE
+.SS mkc_imp.scripts.mk
is internal include file which is included from
.BR mkc.prog.mk ", " mkc.lib.mk " and " mkc.files.mk .
Do not use it directly!
@@ -1526,15 +1634,15 @@ expanding the following @@ patterns:
.VS
Pattern Result
----------------------
-@prefix@ ${PREFIX}
-@bindir@ ${BINDIR}
-@mandir@ ${MANDIR}
-@sbindir@ ${SBINDIR}
-@libdir@ ${LIBDIR}
-@libexecdir@ ${LIBEXECDIR}
-@datadir@ ${DATADIR}
-@sysconfdir@ ${SYSCONFDIR}
-@incsdir@ ${INCSDIR}
+.RI @ "" "prefix@ ${PREFIX}"
+.RI @ "" "bindir@ ${BINDIR}"
+.RI @ "" "mandir@ ${MANDIR}"
+.RI @ "" "sbindir@ ${SBINDIR}"
+.RI @ "" "libdir@ ${LIBDIR}"
+.RI @ "" "libexecdir@ ${LIBEXECDIR}"
+.RI @ "" "datadir@ ${DATADIR}"
+.RI @ "" "sysconfdir@ ${SYSCONFDIR}"
+.RI @ "" "incsdir@ ${INCSDIR}"
.VE
The following variables are provided:
.IP INFILES
@@ -1692,9 +1800,22 @@ This module supports dependencies controlled by
program. As a result CPPFLAGS and LDADD variables are modified according
to "pkg-config --cflags ..." and "pkg-config --libs ...".
The following variables are provided:
-.IP PKG_CONFIG_DEPS
-List of dependency libraries. Spaces around <=, >=, =, < and > are not allowed.
+.IP MKC_CHECK_PKGCONFIG
+List of libraries to check, for example, glib-2.0>=2.1.
+Spaces around <=, >=, =, < and > are not allowed.
+As a result of the check bmake's variable
+PKG_CONFIG.exists.<lib> is set to 1 for success or 0 for failure.
+Unless MKC_NOAUTO is set to 1 -DHAVE_PKGCONFIG_<LIB>=1
+is also added to CFLAGS if <lib> was found. <LIB> is tr/a-z+.-/A-ZP__/ of <lib>.
+.RI < "M" >
+.IP MKC_REQUIRE_PKGCONFIG
+The same as MKC_REQUIRE_PKGCONFIG, but absense of library is
+treated as a fatal error (See
+.B errorcheck
+target.
.RI < "M" >
+.IP PKG_CONFIG_DEPS
+Synonym for MKC_REQUIRE_PKGCONFIG. Deprecated.
.IP PKG_CONFIG.exists.<lib>
If "1", <lib> exists, "0" otherwise.
Inside <lib> <=, >=, =, < and > and replaced with
@@ -1759,7 +1880,11 @@ and
List of source files which are needed for generating
dependencies, but are not needed in ${SRCS}.
.SH "CROSS COMPILATION"
-The following variables are used for compiling software using cross-rools.
+The following variables are used for compiling software using cross-tools.
+.IP MACHINE_GNU_PLATFORM
+See TOOLCHAIN_PREFIX.
+.IP OPSYS_TARGET
+OPSYS for target OS.
.IP SYSROOT
Root directory for headers and libraries.
If set, the following variables
@@ -1767,6 +1892,8 @@ are set to ${TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}<toolname>: AR, AS, CXX, CPP, CC,
INSTALL, LD, NM, OBJCOPY, OBJDUMP, RANLIB, SIZE and STRIP.
.RI < "U" >
.RI [ "" ].
+.IP TOOLDIR
+See TOOLCHAIN_DIR.
.IP TOOLCHAIN_DIR
Directory that contains cross-toolchain.
.RI < "U" >
diff --git a/scripts/mkc_check_common.sh b/scripts/mkc_check_common.sh
index 8daff04..1196446 100644
--- a/scripts/mkc_check_common.sh
+++ b/scripts/mkc_check_common.sh
@@ -1,4 +1,4 @@
-# Copyright (c) 2009-2010 by Aleksey Cheusov
+# Copyright (c) 2009-2014 by Aleksey Cheusov
#
# See LICENSE file in the distribution.
############################################################
@@ -14,6 +14,12 @@ fi
MKC_CACHEDIR=${MKC_CACHEDIR:-.}
CC=${CC:-cc}
+if test -x "$MKC_CACHEDIR"; then
+ :
+else
+ mkdir -p "$MKC_CACHEDIR"
+fi
+
tmpc=$MKC_CACHEDIR/_mkc_${pathpart}${MKC_NOCACHE}.c
tmpo=$MKC_CACHEDIR/_mkc_${pathpart}${MKC_NOCACHE}.o
tmperr=$MKC_CACHEDIR/_mkc_${pathpart}${MKC_NOCACHE}.err
diff --git a/scripts/mkc_check_custom b/scripts/mkc_check_custom
index 5213d29..46f751c 100755
--- a/scripts/mkc_check_custom
+++ b/scripts/mkc_check_custom
@@ -27,10 +27,10 @@ Usage:
OPTIONS:
-h display this help
-r build application and run it
- -p a part of cache filename, defaults to "custom"
- -n a part of cache filename, defaults to
+ -p text prefix for cache filename, defaults to "custom"
+ -n text a part of cache filename, defaults to
`basename <source_file>` without extension
- -m A part of verbose message, defaults to -n args
+ -m text A part of verbose message, defaults to -n args
-s exit status of executable will be check
-d delete cache files
Examples:
diff --git a/scripts/mkc_check_custom.1 b/scripts/mkc_check_custom.1
index 6ea2845..8655577 100644
--- a/scripts/mkc_check_custom.1
+++ b/scripts/mkc_check_custom.1
@@ -18,27 +18,24 @@
.SH NAME
mkc_check_custom \- run user's custom checks.
.SH SYNOPSIS
-.BI mkc_check_custom " [-r] <file>"
+.BI mkc_check_custom " [-r] sourcefile"
+.br
+.BI mkc_check_custom " cmd [args...]"
.br
.BI mkc_check_custom " -h"
.SH DESCRIPTION
-.B mkc_check_custom
-takes a
-.I file
-and tries to compile or runs it. If
-.I file
-is an executable file,
-.B mkc_check_custom
-runs it and outputs 1 if it succeeded or 0 otherwise.
If
-.I file
-is not executable,
+.I cmd
+is executable
.B mkc_check_custom
-tries to compile and (if
-.I -r
-applied ) run a generated executable. Again, if compilation/run succeeded,
-1 is output, otherwise -- 0. What type of compiler to use depend on
-.I file
+runs
+.IR "cmd args" .
+Otherwise it tries to compile
+.IR sourcefile
+and output 1 if compilation succeeded and 0 otherwise.
+If -r option was applied it runs a compiled program.
+What type of compiler to use depends on
+.I sourcefile
extension. '.c' corresponds to
.I ${CC}
(C language), '.cc', '.cxx', '.C' and '.cpp' correspond to
@@ -49,7 +46,34 @@ extension. '.c' corresponds to
.SH OPTIONS
.TP
.B "-h"
-display help message
+Display help message.
+.TP
+.B "-r"
+Run executable compiled from
+.IR sourcefile .
+.TP
+.BI "-p " text
+Prefix of the generated cache file. The default is "custom".
+.TP
+.BI "-n " text
+Name part of the generated cache file.
+.br
+The default is `basename <sourcefile>`.
+.TP
+.BI "-m " text
+Message
+.B mkc_check_custom
+outputs.
+.br
+The default is "custom test sourcefile_or_cmd".
+.TP
+.BI -s
+.B mkc_check_custom
+outputs an exit status of
+.IR "cmd args" .
+.TP
+.BI -d
+Delete cache files.
.SH ENVIRONMENT
.TP
.B CC
diff --git a/scripts/mkc_check_decl b/scripts/mkc_check_decl
index e0cb8ea..ea2a962 100755
--- a/scripts/mkc_check_decl
+++ b/scripts/mkc_check_decl
@@ -1,7 +1,7 @@
#!/bin/sh
############################################################
-# Copyright (c) 2009-2010 by Aleksey Cheusov
+# Copyright (c) 2009-2014 by Aleksey Cheusov
#
# See LICENSE file in the distribution.
############################################################
@@ -27,7 +27,7 @@ in system header files by compiling a test program.
Usage:
mkc_check_decl [OPTIONS] <CHECKTYPE> <what> [includes...]
where CHECKTYPE is either of the following: "define", "variable",
-"func[0-9]", "type" or "member"
+"func[0-9]", "type", "member" or "prototype".
OPTIONS:
-h display this help
@@ -44,6 +44,8 @@ Examples:
mkc_check_decl type long-long
mkc_check_decl member tm.tm_isdst time.h
mkc_check_decl member ifreq.ifr_addr.sa_len net/if.h
+ mkc_check_decl prototype 'int connect(int __fd, const struct sockaddr * __addr, socklen_t __len)' sys/socket.h
+ mkc_check_decl prototype 'int connect(int __fd, struct sockaddr * __addr, socklen_t __len)' sys/socket.h
EOF
}
@@ -63,18 +65,26 @@ fi
##################################################
# initializing
-decltype=`echo $1 | sed -e 's/[0-9]//g'`
-argscnt=`echo $1 | sed 's/[^0-9]//g'`
+decltype=`echo "$1" | sed -e 's/[0-9]//g'`
+argscnt=`echo "$1" | sed 's/[^0-9]//g'`
shift
-declwhat=`echo $1 | sed 's/-/ /'`
+declwhat=`echo "$1" | awk '{gsub(/-/, " "); gsub(/ +[(]/, "("); $1=$1; print}'`
shift
-if test "$decltype" = type; then
- pathpart=`echo ${decltype}_${declwhat}_$* | tr '/. ' '__~'`
-else
- pathpart=`echo $decltype$argscnt $declwhat $* | tr '/. ' '___'`
-fi
+typemsg="$decltype $declwhat"
+case "$decltype" in
+ type)
+ pathpart=`echo "${decltype}_${declwhat}_$*" | tr '/. ' '__~'`
+ ;;
+ prototype)
+ pathpart=`echo "${decltype}_${declwhat}_$*" | tr '/(). *' '____~8'`
+ funcname=`echo "$declwhat" | sed 's,^.* \([^ ]*\)[(].*$,\1,'`
+ ;;
+ *)
+ pathpart=`echo "$decltype$argscnt $declwhat" $* | tr '/. ' '___'`
+ ;;
+esac
. mkc_check_common.sh
@@ -108,7 +118,7 @@ int main ()
return 0;
}
#else
-.error "$declwhat is not a define"
+#error "$declwhat is not a define"
#endif
EOF
@@ -179,6 +189,23 @@ BEGIN {
}
##############################
+is_prototype (){
+ get_includes "$@" > "$tmpc"
+
+ cat >> "$tmpc" <<EOF
+${declwhat};
+void func (void)
+{
+ if (${funcname}) return;
+}
+EOF
+
+ #
+ compile
+}
+
+
+##############################
is_member (){
get_includes "$@" > "$tmpc"
@@ -200,12 +227,8 @@ EOF
##################################################
# test
-for i in "$@"; do
- incs_msg="$incs_msg $i"
-done
-
-if test -n "$incs_msg"; then
- incs_msg=" ($incs_msg )"
+if test $# -gt 0; then
+ incs_msg=" ( $* )"
fi
check_itself (){
@@ -217,7 +240,7 @@ check_itself (){
fi
}
-check_and_cache "checking for $decltype ${declwhat}${incs_msg}" "$cache" "$@"
+check_and_cache "checking for ${typemsg}${incs_msg}" "$cache" "$@"
##################################################
# clean-ups
diff --git a/scripts/mkc_check_decl.1 b/scripts/mkc_check_decl.1
index bc1866e..f3434bb 100644
--- a/scripts/mkc_check_decl.1
+++ b/scripts/mkc_check_decl.1
@@ -16,7 +16,8 @@
.\" ------------------------------------------------------------------
.TH MKC_CHECK_DECL 1 "Mar 15, 2009" "" ""
.SH NAME
-mkc_check_decl \- checks for define, function, variable or type.
+mkc_check_decl \- checks for define, function, variable, type or
+function prototype.
.SH SYNOPSIS
.BI mkc_check_decl " <check_type> <what> [includes...]"
.br
@@ -24,7 +25,8 @@ mkc_check_decl \- checks for define, function, variable or type.
.SH DESCRIPTION
.I check_type
is either
-.IR " define" , " variable" , " func[0-9]" , " type " or " member" .
+.IR " define" , " variable" , " func[0-9]" , " type" , " member " or
+.IR " prototype" .
Depending on its value
.B mkc_check_decl
checks for define, variable, function with specified number
@@ -80,6 +82,8 @@ If set to 1, temporary files are removed.
mkc_check_decl type long-long
mkc_check_decl member tm.tm_isdst time.h
mkc_check_decl member ifreq.ifr_addr.sa_len net/if.h
+ mkc_check_decl prototype 'int connect(int __fd, const struct sockaddr * __addr, socklen_t __len)' sys/socket.h
+ mkc_check_decl prototype 'int connect(int __fd, struct sockaddr * __addr, socklen_t __len)' sys/socket.h
.VE
.SH AUTHOR
Aleksey Cheusov <vle@gmx.net>
diff --git a/scripts/mkc_check_funclib b/scripts/mkc_check_funclib
index 6b3ba4b..0bfd771 100755
--- a/scripts/mkc_check_funclib
+++ b/scripts/mkc_check_funclib
@@ -100,7 +100,7 @@ EOF
fi
}
-check_and_cache "checking for function ${funcname}${libs_msg}" "$cache" "$@"
+check_and_cache "checking for function implementation ${funcname}${libs_msg}" "$cache" "$@"
##################################################
# clean-ups
diff --git a/tests/Makefile b/tests/Makefile
deleted file mode 100644
index 3445bd2..0000000
--- a/tests/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-SHRTOUT = no
-NOEXPORT_VARNAMES = MKC_CACHEDIR
-EXPORT_VARNAMES = SHRTOUT
-
-BUILTINSDIR = ${OBJDIR_custom}
-.export BUILTINSDIR
-
-SUBDIR += configure_test
-SUBDIR += mkinstall
-SUBDIR += ../examples
-SUBDIR += mkshlib
-SUBDIR += mkstaticlib
-SUBDIR += mkpiclib
-SUBDIR += mkprofilelib
-SUBDIR += mkdll
-SUBDIR += pkg_config_0
-SUBDIR += pkg_config_1
-SUBDIR += pkg_config_2
-SUBDIR += lua_dirs
-SUBDIR += rec_makefiles
-SUBDIR += reqd
-SUBDIR += reqd2
-SUBDIR += reqd3
-SUBDIR += reqd4
-SUBDIR += reqd_clean_cache
-SUBDIR += intexts_cleantrg
-SUBDIR += test_subprj_dash
-SUBDIR += test_mkc_vs_PROG
-SUBDIR += test_mkc_vs_LIB
-SUBDIR += test_mkc_vs_SUBDIR
-SUBDIR += test_mkc_vs_SUBPRJ
-
-.include <mkc.mk>
diff --git a/tests/Makefile.inc b/tests/Makefile.inc
new file mode 100644
index 0000000..2b0aecf
--- /dev/null
+++ b/tests/Makefile.inc
@@ -0,0 +1 @@
+.include "../examples/Makefile.inc"
diff --git a/tests/configure_test/expect.out b/tests/configure_test/expect.out
index f7e8ddf..5b8d11b 100644
--- a/tests/configure_test/expect.out
+++ b/tests/configure_test/expect.out
@@ -31,6 +31,8 @@ HAVE_FUNC5.mkc_test_func.include_mkc_test_h=1
HAVE_VAR.mkc_test_var.include_mkc_test_h=1
HAVE_MEMBER.struct_mkc_test_t_a.include_mkc_test_h=1
HAVE_MEMBER.struct_mkc_test_t_b_c.include_mkc_test_h=1
+HAVE_PROTOTYPE.strcmp_ok=1
+HAVE_PROTOTYPE.strcmp_bad=0
CUSTOM.custom_check1=1
CUSTOM.custom_check2=0
HAVE_PROG.sh=1
@@ -39,8 +41,8 @@ HAVE_PROG.awk=1
PROG.awk=/somewhere/bin/awk
HAVE_PROG.megaprog-x34=0
PROG.megaprog-x34=
-MKC_AUTO_CFLAGS=-DHAVE_HEADER_SYS_TIME_H=1 -DHAVE_HEADER_STRING_H=1 -DHAVE_HEADER_INCLUDE_MKC_TEST_H=1 -DSIZEOF_INT=n -DSIZEOF_LONG_LONG=n -DSIZEOF_VOIDP=n -DSIZEOF_SIZE_T_STRING_H=n -DHAVE_DEFINE_MKC_TEST_DEFINE_INCLUDE_MKC_TEST_H=1 -DHAVE_TYPE_SIZE_T_STRING_H=1 -DHAVE_VAR_ERRNO_ERRNO_H=1 -DHAVE_VAR_MKC_TEST_VAR_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_TM_TM_ISDST_TIME_H=1 -DHAVE_MEMBER_STRUCT_SOCKADDR_IN_SIN_ADDR_S_ADDR_ARPA_INET_H_NETINET_IN_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_A_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_B_C_INCLUDE_MKC_TEST_H=1 -DHAVE_FUNC2_STRCMP_STRING_H=1 -DHAVE_FUNC5_MKC_TEST_FUNC_INCLUDE_MKC_TEST_H=1 -DCUSTOM_CUSTOM_CHECK1=1
-MKC_AUTO_SRCS=superfunc1.c superfunc2.c
+MKC_AUTO_CFLAGS= -DHAVE_HEADER_SYS_TIME_H=1 -DHAVE_HEADER_STRING_H=1 -DHAVE_HEADER_INCLUDE_MKC_TEST_H=1 -DSIZEOF_INT=n -DSIZEOF_LONG_LONG=n -DSIZEOF_VOIDP=n -DSIZEOF_SIZE_T_STRING_H=n -DHAVE_DEFINE_MKC_TEST_DEFINE_INCLUDE_MKC_TEST_H=1 -DHAVE_TYPE_SIZE_T_STRING_H=1 -DHAVE_VAR_ERRNO_ERRNO_H=1 -DHAVE_VAR_MKC_TEST_VAR_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_TM_TM_ISDST_TIME_H=1 -DHAVE_MEMBER_STRUCT_SOCKADDR_IN_SIN_ADDR_S_ADDR_ARPA_INET_H_NETINET_IN_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_A_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_B_C_INCLUDE_MKC_TEST_H=1 -DHAVE_FUNC2_STRCMP_STRING_H=1 -DHAVE_FUNC5_MKC_TEST_FUNC_INCLUDE_MKC_TEST_H=1 -DCUSTOM_CUSTOM_CHECK1=1 -DHAVE_PROTOTYPE_STRCMP_OK=1
+MKC_AUTO_SRCS= superfunc1.c superfunc2.c
MKC_AUTO_LDADD=
KNOWN_SYSTEM
@@ -79,6 +81,8 @@ HAVE_FUNC5.mkc_test_func.include_mkc_test_h=1
HAVE_VAR.mkc_test_var.include_mkc_test_h=2
HAVE_MEMBER.struct_mkc_test_t_a.include_mkc_test_h=1
HAVE_MEMBER.struct_mkc_test_t_b_c.include_mkc_test_h=1
+HAVE_PROTOTYPE.strcmp_ok=0
+HAVE_PROTOTYPE.strcmp_bad=1
CUSTOM.custom_check1=0
CUSTOM.custom_check2=1
HAVE_PROG.sh=1
@@ -87,8 +91,8 @@ HAVE_PROG.awk=0
PROG.awk=
HAVE_PROG.megaprog-x34=0
PROG.megaprog-x34=/bad/path
-MKC_AUTO_CFLAGS=-DHAVE_HEADER_SYS_TIME_H=2 -DHAVE_HEADER_STRING_H=2 -DHAVE_HEADER_INCLUDE_MKC_TEST_H=1 -DSIZEOF_INT=n -DSIZEOF_LONG_LONG=n -DSIZEOF_VOIDP=n -DSIZEOF_SIZE_T_STRING_H=n -DHAVE_DEFINE___BAD_DEFINE__=1 -DHAVE_DEFINE_MKC_TEST_DEFINE_INCLUDE_MKC_TEST_H=1 -DHAVE_TYPE_SIZE_T_STRING_H=1 -DHAVE_TYPE_BAD_TYPE=1 -DHAVE_VAR_ERRNO_ERRNO_H=1 -DHAVE_VAR_MKC_TEST_VAR_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_TM_TM_ISDST_TIME_H=1 -DHAVE_MEMBER_STRUCT_SOCKADDR_IN_SIN_ADDR_S_ADDR_ARPA_INET_H_NETINET_IN_H=1 -DHAVE_MEMBER_BAD_MEMBER=1 -DHAVE_MEMBER_BAD_MEMBER_STRING_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_A_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_B_C_INCLUDE_MKC_TEST_H=1 -DHAVE_FUNC2_STRCMP_STRING_H=1 -DHAVE_FUNC3_STRCPY=1 -DHAVE_FUNC5_MKC_TEST_FUNC_INCLUDE_MKC_TEST_H=1 -DCUSTOM_CUSTOM_CHECK2=1
-MKC_AUTO_SRCS=superfunc1.c superfunc2.c
+MKC_AUTO_CFLAGS= -DHAVE_HEADER_SYS_TIME_H=2 -DHAVE_HEADER_STRING_H=2 -DHAVE_HEADER_INCLUDE_MKC_TEST_H=1 -DSIZEOF_INT=n -DSIZEOF_LONG_LONG=n -DSIZEOF_VOIDP=n -DSIZEOF_SIZE_T_STRING_H=n -DHAVE_DEFINE___BAD_DEFINE__=1 -DHAVE_DEFINE_MKC_TEST_DEFINE_INCLUDE_MKC_TEST_H=1 -DHAVE_TYPE_SIZE_T_STRING_H=1 -DHAVE_TYPE_BAD_TYPE=1 -DHAVE_VAR_ERRNO_ERRNO_H=1 -DHAVE_VAR_MKC_TEST_VAR_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_TM_TM_ISDST_TIME_H=1 -DHAVE_MEMBER_STRUCT_SOCKADDR_IN_SIN_ADDR_S_ADDR_ARPA_INET_H_NETINET_IN_H=1 -DHAVE_MEMBER_BAD_MEMBER=1 -DHAVE_MEMBER_BAD_MEMBER_STRING_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_A_INCLUDE_MKC_TEST_H=1 -DHAVE_MEMBER_STRUCT_MKC_TEST_T_B_C_INCLUDE_MKC_TEST_H=1 -DHAVE_FUNC2_STRCMP_STRING_H=1 -DHAVE_FUNC3_STRCPY=1 -DHAVE_FUNC5_MKC_TEST_FUNC_INCLUDE_MKC_TEST_H=1 -DCUSTOM_CUSTOM_CHECK2=1 -DHAVE_PROTOTYPE_STRCMP_BAD=1
+MKC_AUTO_SRCS= superfunc1.c superfunc2.c
MKC_AUTO_LDADD=
KNOWN_SYSTEM
diff --git a/tests/configure_test/mkc_test.mk b/tests/configure_test/mkc_test.mk
index ab04982..3a09220 100644
--- a/tests/configure_test/mkc_test.mk
+++ b/tests/configure_test/mkc_test.mk
@@ -77,6 +77,12 @@ MKC_CUSTOM_FN.custom_check2= my_check2.c
MKC_REQUIRE_CUSTOM+= custom_check3
+MKC_CHECK_PROTOTYPES = strcmp_ok strcmp_bad
+MKC_PROTOTYPE_FUNC.strcmp_ok = int strcmp(const char*, const char*)
+MKC_PROTOTYPE_FUNC.strcmp_bad = int strcmp(const char*, const char*, int lalala)
+MKC_PROTOTYPE_HEADERS.strcmp_ok = string.h
+MKC_PROTOTYPE_HEADERS.strcmp_bad = string.h
+
vars+= HAVE_HEADER.sys_time_h HAVE_HEADER.string_h \
HAVE_FUNCLIB.strcpy HAVE_FUNCLIB.sqrt \
HAVE_FUNC2.strcmp.string_h HAVE_FUNC3.strcpy \
@@ -99,6 +105,7 @@ vars+= HAVE_HEADER.sys_time_h HAVE_HEADER.string_h \
HAVE_VAR.mkc_test_var.include_mkc_test_h \
HAVE_MEMBER.struct_mkc_test_t_a.include_mkc_test_h \
HAVE_MEMBER.struct_mkc_test_t_b_c.include_mkc_test_h \
+ HAVE_PROTOTYPE.strcmp_ok HAVE_PROTOTYPE.strcmp_bad \
\
CUSTOM.custom_check1 CUSTOM.custom_check2 \
\
@@ -110,10 +117,6 @@ vars+= HAVE_HEADER.sys_time_h HAVE_HEADER.string_h \
.include <mkc.configure.mk>
-MKC_AUTO_SRCS:= ${MKC_SRCS}
-MKC_AUTO_CFLAGS:= ${MKC_CFLAGS}
-MKC_AUTO_LDADD:= ${MKC_LDADD}
-
HAVE_MEMBER.struct_sockaddr_in_sin_addr_s_addr.netinet_in_h ?= \
${HAVE_MEMBER.struct_sockaddr_in_sin_addr_s_addr.arpa_inet_h.netinet_in_h}
@@ -125,7 +128,8 @@ all:
.for i in ${vars}
@echo ${i}=${${i}} | \
sed -e 's|\([^ ]*SIZEOF[^ =]*\)=[0-9][0-9]*|\1=n|g' \
- -e 's|\([^ ]*PROG[^ =]*\)=[^ =]*bin/|\1=/somewhere/bin/|g'
+ -e 's|\([^ ]*PROG[^ =]*\)=[^ =]*bin/|\1=/somewhere/bin/|g' \
+ -e '/^MKC_AUTO_SRCS=/ s|/[^ ]*/||g'
.endfor
@echo ''
@printf "%s\n" "${CPPFLAGS}" | \
diff --git a/tests/configure_test/mkc_test_preset.mk b/tests/configure_test/mkc_test_preset.mk
index 6e43bb3..ec381a8 100644
--- a/tests/configure_test/mkc_test_preset.mk
+++ b/tests/configure_test/mkc_test_preset.mk
@@ -20,3 +20,5 @@ CUSTOM.custom_check1=0
CUSTOM.custom_check2=1
PROG.awk=
PROG.megaprog-x34=/bad/path
+HAVE_PROTOTYPE.strcmp_ok=0
+HAVE_PROTOTYPE.strcmp_bad=1
diff --git a/tests/create_cachedir/Makefile b/tests/create_cachedir/Makefile
new file mode 100644
index 0000000..74abaa5
--- /dev/null
+++ b/tests/create_cachedir/Makefile
@@ -0,0 +1,8 @@
+PROG = hello
+
+MKC_CHECK_HEADERS = string.h
+
+CLEANFILES += ${.OBJDIR}/${.CURDIR:T}.test.out
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/tests/create_cachedir/expect.out b/tests/create_cachedir/expect.out
new file mode 100644
index 0000000..bfd8cd9
--- /dev/null
+++ b/tests/create_cachedir/expect.out
@@ -0,0 +1,2 @@
+checking for header string.h... yes
+cache file exists
diff --git a/tests/create_cachedir/hello.c b/tests/create_cachedir/hello.c
new file mode 100644
index 0000000..b8327a7
--- /dev/null
+++ b/tests/create_cachedir/hello.c
@@ -0,0 +1,5 @@
+int main (int argc, char ** argv)
+{
+ /* just a test */
+ return 0;
+}
diff --git a/tests/create_cachedir/test.mk b/tests/create_cachedir/test.mk
new file mode 100644
index 0000000..cdd989e
--- /dev/null
+++ b/tests/create_cachedir/test.mk
@@ -0,0 +1,22 @@
+TEST_MKC_CACHEDIR = ${.CURDIR}/.cache
+CLEANFILES += ${.OBJDIR}/${.CURDIR:T}.test.out ${TEST_MKC_CACHEDIR}
+CLEANDIRS += ${TEST_MKC_CACHEDIR}
+
+.PHONY : test_output
+test_output:
+ @echo 'Testing ${.CURDIR}... ' 1>&2; \
+ tmp_out=${.OBJDIR}/${.CURDIR:T}.test.out; \
+ rm -rf $$tmp_out ${TEST_MKC_CACHEDIR}; \
+ ${MAKE} ${MAKEFLAGS} errorcheck MKC_CACHEDIR=${TEST_MKC_CACHEDIR} 2>&1 | \
+ grep 'checking.*header' ;\
+ if test -f ${TEST_MKC_CACHEDIR}/_mkc_header_string_h.c; then \
+ echo cache file exists; \
+ else \
+ echo cache file does not exist; \
+ fi \
+ ; \
+ ${MAKE} ${MAKEFLAGS} cleandir 2>/dev/null 1>&2
+
+# rm -rf $$MKC_CACHEDIR; \
+
+.include <mkc.minitest.mk>
diff --git a/tests/endianess/Makefile b/tests/endianess/Makefile
new file mode 100644
index 0000000..958a2e4
--- /dev/null
+++ b/tests/endianess/Makefile
@@ -0,0 +1,14 @@
+# this is a backward compatibility test for endianess (single n)
+
+MKC_CHECK_BUILTINS += endianess
+
+MKC_REQD = 0.12.0
+
+.include <mkc.configure.mk>
+
+.PHONY: showme
+showme:
+ @echo BUILTIN.endianess=${BUILTIN.endianess}
+
+.include "test.mk"
+.include <mkc.prog.mk>
diff --git a/tests/endianess/expect.out b/tests/endianess/expect.out
new file mode 100644
index 0000000..ab508f5
--- /dev/null
+++ b/tests/endianess/expect.out
@@ -0,0 +1,3 @@
+=========== all ============
+warning: "endianess test deprecated; use endianness instead"
+BUILTIN.endianess=big
diff --git a/tests/endianess/test.mk b/tests/endianess/test.mk
new file mode 100644
index 0000000..26d9005
--- /dev/null
+++ b/tests/endianess/test.mk
@@ -0,0 +1,12 @@
+CLEANDIRS += ${.CURDIR}/testdir
+
+.PHONY : test_output
+test_output:
+ @set -e; \
+ \
+ echo =========== all ============; \
+ ${MAKE} ${MAKEFLAGS} showme 2>&1 | \
+ sed -e 's,^.*warning:,warning:,' -e 's,little,big,'; \
+ ${MAKE} ${MAKEFLAGS} distclean > /dev/null
+
+.include <mkc.minitest.mk>
diff --git a/tests/mkinstall/test.mk b/tests/mkinstall/test.mk
index 4f86b05..d3af118 100644
--- a/tests/mkinstall/test.mk
+++ b/tests/mkinstall/test.mk
@@ -11,7 +11,7 @@ test_output :
\
echo ===== all SHRTOUT=yes ======; \
${MAKE} ${MAKEFLAGS} clean > /dev/null; \
- env SHRTOUT=YES ${MAKE} ${MAKEFLAGS} all 2>&1 | \
+ env ${MAKE} ${MAKEFLAGS} SHRTOUT=YES all 2>&1 | \
mkc_test_helper_paths; \
\
echo ========= installdirs MKINSTALL=no ==========; \
diff --git a/tests/pkg_config_1_1/Makefile b/tests/pkg_config_1_1/Makefile
new file mode 100644
index 0000000..203f131
--- /dev/null
+++ b/tests/pkg_config_1_1/Makefile
@@ -0,0 +1,7 @@
+# The same as pkg_config_1 but with diferent variable
+LIB= mkc_fake
+
+MKC_REQUIRE_PKGCONFIG= mkc_fake-2.0>=2.10
+
+.include "test.mk"
+.include <mkc.lib.mk>
diff --git a/tests/pkg_config_1_1/test.mk b/tests/pkg_config_1_1/test.mk
new file mode 100644
index 0000000..6fe834c
--- /dev/null
+++ b/tests/pkg_config_1_1/test.mk
@@ -0,0 +1,14 @@
+test:
+ @echo 'Testing ${.CURDIR}... ' 1>&2; \
+ set -e; cd ${.CURDIR}; \
+ tmp_out=${.OBJDIR}/${.CURDIR:T}.test.out; \
+ rm -f $$tmp_out; \
+ ${MAKE} ${MAKEFLAGS} all 2>&1 | grep ERROR: > $$tmp_out || true; \
+ if test -s $$tmp_out; \
+ then echo ' succeeded' 1>&2; \
+ else echo ' FAILED' 1>&2; ex=1; \
+ fi; \
+ ${MAKE} ${MAKEFLAGS} cleandir 2>&1 | grep ERROR: > $$tmp_out || true; \
+ exit $$ex
+
+CLEANFILES += ${.OBJDIR}/${.CURDIR:T}.test.out
diff --git a/tests/rec_makefiles/Makefile.rec b/tests/rec_makefiles/Makefile.common
index 54e194e..b919dc5 100644
--- a/tests/rec_makefiles/Makefile.rec
+++ b/tests/rec_makefiles/Makefile.common
@@ -6,3 +6,6 @@ print-values:
.endfor
A=1
+B=2
+C=3
+D=4
diff --git a/tests/rec_makefiles/expect.out b/tests/rec_makefiles/expect.out
index 2690df1..d2f1d8e 100644
--- a/tests/rec_makefiles/expect.out
+++ b/tests/rec_makefiles/expect.out
@@ -1,15 +1,15 @@
=========== subsubdir1 =============
A=1
-B=333
-C=
-D=
+B=2
+C=3
+D=4
=========== subsubdir2 =============
A=1
B=2
C=3
-D=
+D=4
=========== prj2 =============
A=1
-B=
-C=
+B=2
+C=3
D=4
diff --git a/tests/rec_makefiles/subdir1/Makefile.rec b/tests/rec_makefiles/subdir1/Makefile.rec
deleted file mode 100644
index ac5d589..0000000
--- a/tests/rec_makefiles/subdir1/Makefile.rec
+++ /dev/null
@@ -1 +0,0 @@
-B=2
diff --git a/tests/rec_makefiles/subdir1/subsubdir1/Makefile.rec b/tests/rec_makefiles/subdir1/subsubdir1/Makefile.rec
deleted file mode 100644
index 0ad6340..0000000
--- a/tests/rec_makefiles/subdir1/subsubdir1/Makefile.rec
+++ /dev/null
@@ -1 +0,0 @@
-B=333
diff --git a/tests/rec_makefiles/subdir1/subsubdir2/Makefile.rec b/tests/rec_makefiles/subdir1/subsubdir2/Makefile.rec
deleted file mode 100644
index 40b10c5..0000000
--- a/tests/rec_makefiles/subdir1/subsubdir2/Makefile.rec
+++ /dev/null
@@ -1 +0,0 @@
-C=3
diff --git a/tests/rec_makefiles/subdir2/Makefile.rec b/tests/rec_makefiles/subdir2/Makefile.rec
deleted file mode 100644
index 1d13f5a..0000000
--- a/tests/rec_makefiles/subdir2/Makefile.rec
+++ /dev/null
@@ -1 +0,0 @@
-D=4
diff --git a/tests/rec_makefiles/test.mk b/tests/rec_makefiles/test.mk
index cd3ed8f..a9ff6c8 100644
--- a/tests/rec_makefiles/test.mk
+++ b/tests/rec_makefiles/test.mk
@@ -1,7 +1,9 @@
.PHONY : test
test:
- set -e; env VERBOSE_ECHO=: ${MAKE} all >${.OBJDIR}/_output.tmp; \
- if diff ${.CURDIR}/expect.out ${.OBJDIR}/_output.tmp; \
+ set -e; \
+ env SRCTOP=${.CURDIR} VERBOSE_ECHO=: \
+ ${MAKE} ${MAKEFLAGS} all > ${.OBJDIR}/_output.tmp; \
+ if cmp ${.CURDIR}/expect.out ${.OBJDIR}/_output.tmp; \
then echo ' succeeded' 1>&2; \
else echo ' FAILED' 1>&2; false; \
fi
diff --git a/tests/reqd/expect.out b/tests/reqd/expect.out
index 4c34049..c5cf415 100644
--- a/tests/reqd/expect.out
+++ b/tests/reqd/expect.out
@@ -1 +1 @@
-ERROR: We need mk-configure v.999.0.0 while 0.25.0 is detected
+ERROR: We need mk-configure v.999.0.0 while 0.26.0 is detected
diff --git a/tests/reqd2/expect.out b/tests/reqd2/expect.out
index 4c34049..c5cf415 100644
--- a/tests/reqd2/expect.out
+++ b/tests/reqd2/expect.out
@@ -1 +1 @@
-ERROR: We need mk-configure v.999.0.0 while 0.25.0 is detected
+ERROR: We need mk-configure v.999.0.0 while 0.26.0 is detected
diff --git a/tests/reqd3/expect.out b/tests/reqd3/expect.out
index 4c34049..c5cf415 100644
--- a/tests/reqd3/expect.out
+++ b/tests/reqd3/expect.out
@@ -1 +1 @@
-ERROR: We need mk-configure v.999.0.0 while 0.25.0 is detected
+ERROR: We need mk-configure v.999.0.0 while 0.26.0 is detected
diff --git a/tests/reqd4/expect.out b/tests/reqd4/expect.out
index 8df812e..29fe3b6 100644
--- a/tests/reqd4/expect.out
+++ b/tests/reqd4/expect.out
@@ -1,4 +1,4 @@
-ERROR: We need mk-configure v.999.0.0 while 0.25.0 is detected
+ERROR: We need mk-configure v.999.0.0 while 0.26.0 is detected
"bmake-20110606 or newer is required"
=========== all ============
/objdir/Makefile
diff --git a/tests/reqd_clean_cache/Makefile b/tests/reqd_clean_cache/Makefile
index 04ea2e9..bbbabe2 100644
--- a/tests/reqd_clean_cache/Makefile
+++ b/tests/reqd_clean_cache/Makefile
@@ -10,5 +10,9 @@ MKC_REQUIRE_FUNCS3 = brbrbr
MKC_REQUIRE_CUSTOM = test1
MKC_CUSTOM_FN.test1 = test1.c
+MKC_REQUIRE_PROTOTYPES = bad999
+MKC_PROTOTYPE_HEADERS.bad999 = bad_include.h
+MKC_PROTOTYPE_FUNC.bad999 = void badfunc999(void)
+
.include "test.mk"
.include <mkc.mk>
diff --git a/tests/reqd_clean_cache/expect.out b/tests/reqd_clean_cache/expect.out
index 877cecc..bd1e169 100644
--- a/tests/reqd_clean_cache/expect.out
+++ b/tests/reqd_clean_cache/expect.out
@@ -16,6 +16,7 @@ ERROR: cannot find declaration of function brbrbr
ERROR: custom test test1 failed
ERROR: cannot find program trtrtr
ERROR: cannot find program brbrbr
+ERROR: prototype test bad999 failed
*** Error code 1
Stop.
diff --git a/tests/reqd_clean_cache/test.mk b/tests/reqd_clean_cache/test.mk
index e5cea19..92c35c3 100644
--- a/tests/reqd_clean_cache/test.mk
+++ b/tests/reqd_clean_cache/test.mk
@@ -7,6 +7,7 @@ test_output :
echo =========== all ============; \
{ ${MAKE} ${MAKEFLAGS} all 2>/dev/null || true; \
find ${.OBJDIR} -type f -o -type l | sort; } | \
+ sed 's,bmake\[[0-9]*\],bmake,' | \
env NOSORT=1 mkc_test_helper "${PREFIX}" "${.OBJDIR}"; \
\
${MAKE} ${MAKEFLAGS} cleandir > /dev/null
diff --git a/tests/require_prototype/Makefile b/tests/require_prototype/Makefile
new file mode 100644
index 0000000..bdcf340
--- /dev/null
+++ b/tests/require_prototype/Makefile
@@ -0,0 +1,14 @@
+CLEANFILES += ${.OBJDIR}/${.CURDIR:T}.test.out
+
+test:
+ @echo 'Testing ${.CURDIR}... ' 1>&2; \
+ set -e; \
+ tmp_out=${.OBJDIR}/${.CURDIR:T}.test.out; \
+ rm -f $$tmp_out; \
+ ${MAKE} ${MAKEFLAGS} -f ${.CURDIR}/test.mk cleandir >/dev/null 2>&1; \
+ ${MAKE} ${MAKEFLAGS} -f ${.CURDIR}/test.mk all > $$tmp_out 2>&1; \
+ diff ${.CURDIR}/expect.out $$tmp_out && \
+ echo ' succeeded' 1>&2 || \
+ { echo ' FAILED' 1>&2; false; }
+
+.include <mkc.subprj.mk>
diff --git a/tests/require_prototype/expect.out b/tests/require_prototype/expect.out
new file mode 100644
index 0000000..40bb8b4
--- /dev/null
+++ b/tests/require_prototype/expect.out
@@ -0,0 +1 @@
+checking for prototype pid_t fork(void) ( unistd.h unistd.h )... yes
diff --git a/tests/require_prototype/test.mk b/tests/require_prototype/test.mk
new file mode 100644
index 0000000..d8fa02e
--- /dev/null
+++ b/tests/require_prototype/test.mk
@@ -0,0 +1,5 @@
+MKC_REQUIRE_PROTOTYPES = fork
+MKC_PROTOTYPE_HEADERS.fork = unistd.h unistd.h # intentionally double!
+MKC_PROTOTYPE_FUNC.fork = pid_t fork (void)
+
+.include <mkc.prog.mk>
diff --git a/tests/sys_queue/Makefile b/tests/sys_queue/Makefile
new file mode 100644
index 0000000..b50aa77
--- /dev/null
+++ b/tests/sys_queue/Makefile
@@ -0,0 +1,11 @@
+PROG = hello
+SRCS = hello.c
+
+WARNS = 4
+
+MKC_FEATURES = CIRCLEQ LIST SIMPLEQ SLIST STAILQ TAILQ
+
+MKC_REQD = 0.26.0
+
+test: all
+.include <mkc.prog.mk>
diff --git a/tests/sys_queue/hello.c b/tests/sys_queue/hello.c
new file mode 100644
index 0000000..dbdae31
--- /dev/null
+++ b/tests/sys_queue/hello.c
@@ -0,0 +1,17 @@
+#include <mkc_CIRCLEQ.h>
+#include <mkc_LIST.h>
+#include <mkc_SIMPLEQ.h>
+#include <mkc_SLIST.h>
+#include <mkc_STAILQ.h>
+#include <mkc_TAILQ.h>
+
+#if !defined(CIRCLEQ_ENTRY) || !defined(LIST_ENTRY) || \
+ !defined(SIMPLEQ_ENTRY) || !defined(SLIST_ENTRY) || \
+ !defined(STAILQ_ENTRY) || !defined(TAILQ_ENTRY)
+#error "mk-configure bug!!!"
+#endif
+
+int main (int argc, char ** argv)
+{
+ return 0;
+}
diff --git a/tests/test_subprj_dash/Makefile b/tests/test_subprj_dash/Makefile
index 532832d..f518e28 100644
--- a/tests/test_subprj_dash/Makefile
+++ b/tests/test_subprj_dash/Makefile
@@ -6,6 +6,7 @@ test:
tmp_out=${.OBJDIR}/${.CURDIR:T}.test.out; \
rm -f $$tmp_out; \
${MAKE} ${MAKEFLAGS} -f ${.CURDIR}/test.mk all 2>&1 | \
+ sed 's,bmake\[[0-9]*\],bmake,' | \
mkc_test_helper "${PREFIX}" "${.OBJDIR}" > $$tmp_out; \
diff ${.CURDIR}/expect.out $$tmp_out && \
echo ' succeeded' 1>&2 || \