diff options
170 files changed, 4241 insertions, 637 deletions
@@ -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} @@ -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 @@ -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. @@ -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 */ +} @@ -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 Binary files differnew file mode 100644 index 0000000..194fe85 --- /dev/null +++ b/presentation/presentation.pdf 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 || \ |