summaryrefslogtreecommitdiff
path: root/src/kmk
diff options
context:
space:
mode:
authorFelix Geyer <debfx-pkg@fobos.de>2011-08-21 11:16:23 +0200
committerFelix Geyer <debfx-pkg@fobos.de>2011-08-21 11:16:23 +0200
commitbd9ff04c49dda0d5d1d99fb88960c1779f3229a3 (patch)
treeceb9f9f990c51a3bd1263e81091e460d66bbcb39 /src/kmk
parentbeb92cf0e95b1ffa9361993d7a248dbab63741c3 (diff)
downloadkbuild-bd9ff04c49dda0d5d1d99fb88960c1779f3229a3.tar.gz
Imported Upstream version 0.1.9998svn2543upstream/0.1.9998svn2543
Diffstat (limited to 'src/kmk')
-rw-r--r--src/kmk/Makefile.am30
-rw-r--r--src/kmk/Makefile.kmk131
-rw-r--r--src/kmk/alloccache.c4
-rw-r--r--src/kmk/electric.c4
-rw-r--r--src/kmk/electric.h4
-rw-r--r--src/kmk/expreval.c4
-rw-r--r--src/kmk/function.c245
-rw-r--r--src/kmk/incdep.c4
-rw-r--r--src/kmk/job.c7
-rw-r--r--src/kmk/kbuild.c41
-rw-r--r--src/kmk/kbuild.h4
-rw-r--r--src/kmk/kdepdb.c1087
-rw-r--r--src/kmk/kmkbuiltin.c4
-rw-r--r--src/kmk/kmkbuiltin.h4
-rw-r--r--src/kmk/kmkbuiltin/append.c6
-rw-r--r--src/kmk/kmkbuiltin/chmod.c8
-rw-r--r--src/kmk/kmkbuiltin/cp.c10
-rw-r--r--src/kmk/kmkbuiltin/cp_utils.c18
-rw-r--r--src/kmk/kmkbuiltin/darwin.c4
-rw-r--r--src/kmk/kmkbuiltin/err.c4
-rw-r--r--src/kmk/kmkbuiltin/err.h4
-rw-r--r--src/kmk/kmkbuiltin/install.c88
-rw-r--r--src/kmk/kmkbuiltin/kDepIDB.c4
-rw-r--r--src/kmk/kmkbuiltin/kDepObj.c4
-rw-r--r--src/kmk/kmkbuiltin/kbuild_protection.c4
-rw-r--r--src/kmk/kmkbuiltin/kbuild_protection.h4
-rw-r--r--src/kmk/kmkbuiltin/kbuild_version.c4
-rw-r--r--src/kmk/kmkbuiltin/ln.c16
-rw-r--r--src/kmk/kmkbuiltin/md5sum.c8
-rw-r--r--src/kmk/kmkbuiltin/mkdir.c16
-rw-r--r--src/kmk/kmkbuiltin/mscfakes.c35
-rw-r--r--src/kmk/kmkbuiltin/mscfakes.h4
-rw-r--r--src/kmk/kmkbuiltin/mv.c2
-rw-r--r--src/kmk/kmkbuiltin/openbsd.c54
-rw-r--r--src/kmk/kmkbuiltin/osdep.c7
-rw-r--r--src/kmk/kmkbuiltin/redirect.c4
-rw-r--r--src/kmk/kmkbuiltin/rm.c46
-rw-r--r--src/kmk/kmkbuiltin/rmdir.c4
-rw-r--r--src/kmk/kmkbuiltin/sleep.c4
-rw-r--r--src/kmk/kmkbuiltin/solfakes.c4
-rw-r--r--src/kmk/kmkbuiltin/solfakes.h4
-rw-r--r--src/kmk/maintMakefile4
-rw-r--r--src/kmk/read.c19
-rw-r--r--src/kmk/strcache2.c4
-rw-r--r--src/kmk/strcache2.h4
-rw-r--r--src/kmk/testcase-2ndtargetexp.kmk4
-rw-r--r--src/kmk/testcase-if1of.kmk4
-rw-r--r--src/kmk/testcase-includedep-sub.kmk4
-rw-r--r--src/kmk/testcase-includedep.kmk4
-rw-r--r--src/kmk/testcase-lazy-deps-vars.kmk4
-rw-r--r--src/kmk/testcase-math.kmk4
-rw-r--r--src/kmk/testcase-root.kmk30
-rw-r--r--src/kmk/testcase-stack.kmk4
-rw-r--r--src/kmk/testcase-xargs.kmk4
-rw-r--r--src/kmk/tests/scripts/features/ifcond4
-rw-r--r--src/kmk/tests/scripts/functions/evalcall4
-rw-r--r--src/kmk/tests/scripts/functions/expr4
-rw-r--r--src/kmk/tests/scripts/functions/for4
-rw-r--r--src/kmk/tests/scripts/functions/if-expr4
-rw-r--r--src/kmk/tests/scripts/functions/insert4
-rw-r--r--src/kmk/tests/scripts/functions/intersects4
-rw-r--r--src/kmk/tests/scripts/functions/lastpos4
-rw-r--r--src/kmk/tests/scripts/functions/length4
-rw-r--r--src/kmk/tests/scripts/functions/length-var4
-rw-r--r--src/kmk/tests/scripts/functions/pos4
-rw-r--r--src/kmk/tests/scripts/functions/printf4
-rw-r--r--src/kmk/tests/scripts/functions/root4
-rw-r--r--src/kmk/tests/scripts/functions/select4
-rw-r--r--src/kmk/tests/scripts/functions/substr4
-rw-r--r--src/kmk/tests/scripts/functions/translate4
-rw-r--r--src/kmk/tests/scripts/functions/while4
-rw-r--r--src/kmk/tests/scripts/variables/must_make4
-rw-r--r--src/kmk/variable.c101
-rw-r--r--src/kmk/w32/Makefile.kmk2
-rw-r--r--src/kmk/w32/pathstuff.c12
-rw-r--r--src/kmk/w32/tstFileInfo.c2
76 files changed, 1955 insertions, 270 deletions
diff --git a/src/kmk/Makefile.am b/src/kmk/Makefile.am
index 6c1068c..45e788d 100644
--- a/src/kmk/Makefile.am
+++ b/src/kmk/Makefile.am
@@ -128,25 +128,29 @@ DEFS = \
-DCONFIG_WITH_INCLUDEDEP \
-DCONFIG_WITHOUT_THREADS \
-DCONFIG_WITH_VALUE_LENGTH \
- -DCONFIG_WITH_RSORT \
+ \
-DCONFIG_WITH_ABSPATHEX \
- -DCONFIG_WITH_COMPARE \
- -DCONFIG_WITH_STACK \
+ -DCONFIG_WITH_COMMANDS_FUNC \
+ -DCONFIG_WITH_DATE \
+ -DCONFIG_WITH_DEFINED_FUNCTIONS \
+ -DCONFIG_WITH_EVALPLUS \
+ -DCONFIG_WITH_FILE_SIZE \
+ -DCONFIG_WITH_LOOP_FUNCTIONS \
-DCONFIG_WITH_MATH \
- -DCONFIG_WITH_XARGS \
-DCONFIG_WITH_NANOTS \
+ -DCONFIG_WITH_ROOT_FUNC \
+ -DCONFIG_WITH_RSORT \
+ -DCONFIG_WITH_STACK \
+ -DCONFIG_WITH_STRING_FUNCTIONS \
+ -DCONFIG_WITH_WHERE_FUNCTION \
+ -DCONFIG_WITH_WHICH \
+ -DCONFIG_WITH_XARGS \
+ \
+ -DCONFIG_WITH_COMPARE \
-DCONFIG_WITH_SET_CONDITIONALS \
-DCONFIG_WITH_IF_CONDITIONALS \
- -DCONFIG_WITH_DATE \
- -DCONFIG_WITH_FILE_SIZE \
- -DCONFIG_WITH_WHICH \
-DCONFIG_WITH_PRINTF \
- -DCONFIG_WITH_EVALPLUS \
-DCONFIG_WITH_MINIMAL_STATS \
- -DCONFIG_WITH_COMMANDS_FUNC \
- -DCONFIG_WITH_STRING_FUNCTIONS \
- -DCONFIG_WITH_LOOP_FUNCTIONS \
- -DCONFIG_WITH_ROOT_FUNC \
-DCONFIG_PRETTY_COMMAND_PRINTING \
-DCONFIG_WITH_PRINT_STATS_SWITCH \
-DCONFIG_WITH_PRINT_TIME_SWITCH \
@@ -161,7 +165,7 @@ DEFS = \
-DKBUILD_SVN_REV=1 \
-DKBUILD_VERSION_MAJOR=0 \
-DKBUILD_VERSION_MINOR=1 \
- -DKBUILD_VERSION_PATCH=98 \
+ -DKBUILD_VERSION_PATCH=9998 \
\
-DCONFIG_WITH_KMK_BUILTIN \
@DEFS@
diff --git a/src/kmk/Makefile.kmk b/src/kmk/Makefile.kmk
index 5eb7885..fe2cd43 100644
--- a/src/kmk/Makefile.kmk
+++ b/src/kmk/Makefile.kmk
@@ -1,10 +1,10 @@
-# $Id: Makefile.kmk 2263 2009-01-23 00:22:47Z bird $
+# $Id: Makefile.kmk 2532 2011-08-02 13:05:37Z bird $
## @file
# Sub-makefile for kmk / GNU Make.
#
#
-# Copyright (c) 2004-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2004-2011 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
@@ -31,39 +31,40 @@ include $(KBUILD_PATH)/subheader.kmk
# Template for kmk and the kmk_* binaries in this makefile.
#
TEMPLATE_BIN-KMK = Template for src/gmake binaries
-TEMPLATE_BIN-KMK_EXTENDS = BIN
+TEMPLATE_BIN-KMK_EXTENDS = BIN-THREADED
TEMPLATE_BIN-KMK_DEFS = \
HAVE_CONFIG_H \
$(TEMPLATE_BIN_DEFS) \
KBUILD_SVN_REV=$(KBUILD_SVN_REV) \
KBUILD_TYPE=\"$(KBUILD_TYPE)\"
TEMPLATE_BIN-KMK_DEPS = \
- $(PATH_kmk)/config.h \
- $(PATH_kmk)/fts.h
+ $(kmk_0_OUTDIR)/config.h \
+ $(kmk_0_OUTDIR)/fts.h
TEMPLATE_BIN-KMK_CLEAN = $(TEMPLATE_BIN-KMK_DEPS)
TEMPLATE_BIN-KMK_DEPS.solaris = \
- $(PATH_kmk)/paths.h
+ $(kmk_0_OUTDIR)/paths.h
TEMPLATE_BIN-KMK_CLEAN.solaris = $(TEMPLATE_BIN-KMK_DEPS.solaris)
TEMPLATE_BIN-KMK_DEPS.win = \
- $(PATH_kmk)/sysexits.h \
- $(PATH_kmk)/unistd.h \
- $(PATH_kmk)/paths.h \
- $(PATH_kmk)/grp.h \
- $(PATH_kmk)/pwd.h \
- $(PATH_kmk)/inttypes.h
-TEMPLATE_BIN-KMK_CFLAGS.win.amd64 = $(TEMPLATE_BIN_CFLAGS.win.amd64) -wd4244 -wd4267
+ $(kmk_0_OUTDIR)/sysexits.h \
+ $(kmk_0_OUTDIR)/unistd.h \
+ $(kmk_0_OUTDIR)/paths.h \
+ $(kmk_0_OUTDIR)/grp.h \
+ $(kmk_0_OUTDIR)/pwd.h \
+ $(kmk_0_OUTDIR)/inttypes.h
+TEMPLATE_BIN-KMK_CFLAGS.win.amd64 = $(TEMPLATE_BIN-THREADED_CFLAGS.win.amd64) -wd4244 -wd4267
TEMPLATE_BIN-KMK_CLEAN.win = $(TEMPLATE_BIN-KMK_DEPS.win)
-TEMPLATE_BIN-KMK_INCS = $(PATH_kmk) . $(TEMPLATE_BIN_INCS)
+TEMPLATE_BIN-KMK_INCS = $(kmk_0_OUTDIR) . $(TEMPLATE_BIN-THREADED_INCS)
TEMPLATE_BIN-KMK_INCS.darwin = glob
TEMPLATE_BIN-KMK_INCS.dragonfly = glob
TEMPLATE_BIN-KMK_INCS.freebsd = glob
+TEMPLATE_BIN-KMK_INCS.openbsd = glob
TEMPLATE_BIN-KMK_INCS.solaris = glob
-TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN_LIBS) $(TARGET_kmkmissing) $(LIB_KUTIL)
+TEMPLATE_BIN-KMK_LIBS = $(TEMPLATE_BIN-THREADED_LIBS) $(kmkmissing_1_TARGET) $(LIB_KUTIL)
ifdef ELECTRIC_HEAP # for electric heap (see electric.c) - windows only.
ifeq ($(KBUILD_TARGET),win)
- TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN_CFLAGS) /FI$(kmk_PATH)/electric.h -DELECTRIC_HEAP=1
+ TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) /FI$(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1
else
- TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN_CFLAGS) -include $(kmk_PATH)/electric.h -DELECTRIC_HEAP=1
+ TEMPLATE_BIN-KMK_CFLAGS = $(TEMPLATE_BIN-THREADED_CFLAGS) -include $(kmk_DEFPATH)/electric.h -DELECTRIC_HEAP=1
endif
endif
@@ -103,6 +104,10 @@ kmkmissing_SOURCES.freebsd = \
kmkmissing_SOURCES.linux += \
kmkbuiltin/strlcpy.c
+kmkmissing_SOURCES.openbsd = \
+ kmkbuiltin/openbsd.c \
+ glob/glob.c
+
kmkmissing_SOURCES.solaris = \
kmkbuiltin/strlcpy.c \
kmkbuiltin/solfakes.c \
@@ -148,29 +153,33 @@ kmk_DEFS = \
CONFIG_NO_DEFAULT_TERMINAL_RULES \
CONFIG_NO_DEFAULT_SUFFIX_RULES \
CONFIG_NO_DEFAULT_VARIABLES \
+ \
+ CONFIG_WITH_ABSPATHEX \
+ CONFIG_WITH_COMMANDS_FUNC \
+ CONFIG_WITH_DATE \
+ CONFIG_WITH_DEFINED_FUNCTIONS \
+ CONFIG_WITH_EVALPLUS \
+ CONFIG_WITH_FILE_SIZE \
+ CONFIG_WITH_LOOP_FUNCTIONS \
+ CONFIG_WITH_MATH \
+ CONFIG_WITH_NANOTS \
+ CONFIG_WITH_ROOT_FUNC \
+ CONFIG_WITH_RSORT \
+ CONFIG_WITH_STACK \
+ CONFIG_WITH_STRING_FUNCTIONS \
+ CONFIG_WITH_WHERE_FUNCTION \
+ CONFIG_WITH_WHICH \
+ CONFIG_WITH_XARGS \
+ \
CONFIG_WITH_EXTENDED_NOTPARALLEL \
CONFIG_WITH_INCLUDEDEP \
CONFIG_WITH_VALUE_LENGTH \
- CONFIG_WITH_RSORT \
- CONFIG_WITH_ABSPATHEX \
CONFIG_WITH_COMPARE \
- CONFIG_WITH_STACK \
- CONFIG_WITH_MATH \
- CONFIG_WITH_XARGS \
- CONFIG_WITH_NANOTS \
CONFIG_WITH_SET_CONDITIONALS \
CONFIG_WITH_IF_CONDITIONALS \
- CONFIG_WITH_DATE \
- CONFIG_WITH_FILE_SIZE \
- CONFIG_WITH_WHICH \
CONFIG_WITH_PRINTF \
- CONFIG_WITH_EVALPLUS \
CONFIG_WITH_MINIMAL_STATS \
- CONFIG_WITH_COMMANDS_FUNC \
- CONFIG_WITH_PRINTF \
- CONFIG_WITH_STRING_FUNCTIONS \
- CONFIG_WITH_LOOP_FUNCTIONS \
- CONFIG_WITH_ROOT_FUNC \
+ \
CONFIG_PRETTY_COMMAND_PRINTING \
CONFIG_WITH_PRINT_STATS_SWITCH \
CONFIG_WITH_PRINT_TIME_SWITCH \
@@ -215,12 +224,11 @@ kmk_SOURCES = \
vpath.c \
remote-stub.c
+kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
+
#kmk_LIBS.solaris = malloc
#kmk_DEFS.solaris += HAVE_MALLINFO
-kmk_LIBS.freebsd.amd64 = pthread
-kmk_DEFS.freebsd.x86 = CONFIG_WITHOUT_THREADS
-
#
# kmkbuiltin commands
#
@@ -401,9 +409,9 @@ PROGRAMS += kmk_gmake
kmk_gmake_TEMPLATE = BIN-KMK
kmk_gmake_DEFS = \
HAVE_CONFIG_H \
- NO_ARCHIVES \
CONFIG_WITH_TOUPPER_TOLOWER \
EXPERIMENTAL
+# NO_ARCHIVES
kmk_gmake_SOURCES = \
main.c \
@@ -486,33 +494,33 @@ include $(FILE_KBUILD_SUB_FOOTER)
#
# Use checked in config.h instead of running ./Configure for it.
#
-kmk_config.h.$(KBUILD_TARGET) := $(kmk_PATH)/config.h.$(KBUILD_TARGET)
-$(PATH_kmk)/config.h: $(kmk_config.h.$(KBUILD_TARGET))
+kmk_config.h.$(KBUILD_TARGET) := $(kmk_DEFPATH)/config.h.$(KBUILD_TARGET)
+$(kmk_0_OUTDIR)/config.h: $(kmk_config.h.$(KBUILD_TARGET))
$(MKDIR) -p $(dir $@)
$(CP) $^ $@
#
# Some missing headers.
#
-$(PATH_kmk)/fts.h: $(kmk_PATH)/kmkbuiltin/ftsfake.h | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/fts.h: $(kmk_DEFPATH)/kmkbuiltin/ftsfake.h | $(call DIRDEP,$(kmk_0_OUTDIR))
$(CP) $^ $@
-$(PATH_kmk)/unistd.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/unistd.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
-$(PATH_kmk)/sysexits.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/sysexits.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
-$(PATH_kmk)/inttypes.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/inttypes.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
-$(PATH_kmk)/paths.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/paths.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
-$(PATH_kmk)/pwd.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/pwd.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
-$(PATH_kmk)/grp.h: | $(call DIRDEP,$(PATH_kmk))
+$(kmk_0_OUTDIR)/grp.h: | $(call DIRDEP,$(kmk_0_OUTDIR))
$(ECHO_EXT) > $@
@@ -566,22 +574,25 @@ test_shell_newline:
test_stack:
- $(MAKE) -f $(kmk_PATH)/testcase-stack.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-stack.kmk
test_math:
- $(MAKE) -f $(kmk_PATH)/testcase-math.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-math.kmk
test_if1of:
- $(MAKE) -f $(kmk_PATH)/testcase-if1of.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-if1of.kmk
test_local:
- $(MAKE) -f $(kmk_PATH)/testcase-local.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-local.kmk
test_includedep:
- $(MAKE) -f $(kmk_PATH)/testcase-includedep.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-includedep.kmk
+
+test_root:
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-root.kmk
test_2ndtargetexp:
- $(MAKE) -f $(kmk_PATH)/testcase-2ndtargetexp.kmk
+ $(MAKE) -f $(kmk_DEFPATH)/testcase-2ndtargetexp.kmk
test_30_continued_on_failure_worker:
this_executable_does_not_exist.exe
@@ -598,9 +609,19 @@ test_30_continued_on_failure:
fi
test_lazy_deps_vars:
- $(MAKE) -C $(kmk_PATH) -f testcase-lazy-deps-vars.kmk
-
-
-test_all: test_math test_stack test_shell test_if1of test_local test_includedep test_2ndtargetexp test_30_continued_on_failure test_lazy_deps_vars
+ $(MAKE) -C $(kmk_DEFPATH) -f testcase-lazy-deps-vars.kmk
+
+
+test_all: \
+ test_math \
+ test_stack \
+ test_shell \
+ test_if1of \
+ test_local \
+ test_root \
+ test_includedep \
+ test_2ndtargetexp \
+ test_30_continued_on_failure \
+ test_lazy_deps_vars
diff --git a/src/kmk/alloccache.c b/src/kmk/alloccache.c
index 8c40663..82202c7 100644
--- a/src/kmk/alloccache.c
+++ b/src/kmk/alloccache.c
@@ -1,4 +1,4 @@
-/* $Id: alloccache.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: alloccache.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* alloccache - Fixed sized allocation cache.
*
@@ -15,7 +15,7 @@
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/electric.c b/src/kmk/electric.c
index e756a33..c8d0235 100644
--- a/src/kmk/electric.c
+++ b/src/kmk/electric.c
@@ -1,10 +1,10 @@
-/* $Id: electric.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: electric.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* A simple electric heap implementation.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/electric.h b/src/kmk/electric.h
index 4333c39..eb39082 100644
--- a/src/kmk/electric.h
+++ b/src/kmk/electric.h
@@ -1,10 +1,10 @@
-/* $Id: electric.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: electric.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* A simple electric heap implementation, wrapper header.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/expreval.c b/src/kmk/expreval.c
index 1a48e60..0e7f6b7 100644
--- a/src/kmk/expreval.c
+++ b/src/kmk/expreval.c
@@ -1,11 +1,11 @@
#ifdef CONFIG_WITH_IF_CONDITIONALS
-/* $Id: expreval.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: expreval.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* expreval - Expressions evaluator, C / BSD make / nmake style.
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/function.c b/src/kmk/function.c
index 3708ebc..7fe5f4c 100644
--- a/src/kmk/function.c
+++ b/src/kmk/function.c
@@ -676,6 +676,29 @@ func_flavor (char *o, char **argv, const char *funcname UNUSED)
return o;
}
+#ifdef CONFIG_WITH_WHERE_FUNCTION
+static char *
+func_where (char *o, char **argv, const char *funcname UNUSED)
+{
+ struct variable *v = lookup_variable (argv[0], strlen (argv[0]));
+ char buf[64];
+
+ if (v == 0)
+ o = variable_buffer_output (o, "undefined", 9);
+ else
+ if (v->fileinfo.filenm)
+ {
+ o = variable_buffer_output (o, v->fileinfo.filenm, strlen(v->fileinfo.filenm));
+ sprintf (buf, ":%lu", v->fileinfo.lineno);
+ o = variable_buffer_output (o, buf, strlen(buf));
+ }
+ else
+ o = variable_buffer_output (o, "no-location", 11);
+
+ return o;
+}
+#endif /* CONFIG_WITH_WHERE_FUNCTION */
+
#ifdef VMS
# define IS_PATHSEP(c) ((c) == ']')
#else
@@ -801,6 +824,7 @@ func_basename_dir (char *o, char **argv, const char *funcname)
}
#ifdef CONFIG_WITH_ROOT_FUNC
+
/*
$(root path)
@@ -874,7 +898,7 @@ func_root (char *o, char **argv, const char *funcname UNUSED)
#endif
if (p2 != NULL)
{
- /* Include all subsequent path seperators. */
+ /* Include all subsequent path separators. */
while (len > 0 && IS_PATHSEP(*p2))
p2++, len--;
@@ -890,6 +914,87 @@ func_root (char *o, char **argv, const char *funcname UNUSED)
return o;
}
+
+/*
+ $(notroot path)
+
+ This is mainly for dealing with drive letters and UNC paths on Windows
+ and OS/2.
+ */
+static char *
+func_notroot (char *o, char **argv, const char *funcname UNUSED)
+{
+ const char *paths = argv[0] ? argv[0] : "";
+ int doneany = 0;
+ const char *p;
+ unsigned int len;
+
+ while ((p = find_next_token (&paths, &len)) != 0)
+ {
+ const char *p2 = p;
+
+#ifdef HAVE_DOS_PATHS
+ if ( len >= 2
+ && p2[1] == ':'
+ && ( (p2[0] >= 'A' && p2[0] <= 'Z')
+ || (p2[0] >= 'a' && p2[0] <= 'z')))
+ {
+ p2 += 2;
+ len -= 2;
+ }
+ else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1])
+ && !IS_PATHSEP(p2[2]))
+ {
+ /* Min recognized UNC: "//./" - find the next slash
+ Typical root: "//srv/shr/" */
+ /* XXX: Check if //./ needs special handling. */
+ unsigned int saved_len = len;
+
+ p2 += 3;
+ len -= 3;
+ while (len > 0 && !IS_PATHSEP(*p2))
+ p2++, len--;
+
+ if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1])))
+ {
+ p2++;
+ len--;
+
+ if (len) /* optional share */
+ while (len > 0 && !IS_PATHSEP(*p2))
+ p2++, len--;
+ }
+ else
+ {
+ p2 = p;
+ len = saved_len;
+ }
+ }
+
+#elif defined (VMS) || defined (AMGIA)
+ /* XXX: VMS and AMGIA */
+ fatal (NILF, _("$(root ) is not implemented on this platform"));
+#endif
+
+ /* Exclude all subsequent / leading path separators. */
+
+ while (len > 0 && IS_PATHSEP(*p2))
+ p2++, len--;
+ if (len > 0)
+ o = variable_buffer_output (o, p2, len);
+ else
+ o = variable_buffer_output (o, ".", 1);
+ o = variable_buffer_output (o, " ", 1);
+ doneany = 1;
+ }
+
+ if (doneany)
+ /* Kill last space. */
+ --o;
+
+ return o;
+}
+
#endif /* CONFIG_WITH_ROOT_FUNC */
static char *
@@ -931,6 +1036,119 @@ func_subst (char *o, char **argv, const char *funcname UNUSED)
return o;
}
+#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
+
+/* Used by func_firstdefined and func_lastdefined to parse the optional last
+ argument. Returns 0 if the variable name is to be returned and 1 if it's
+ the variable value value. */
+static int
+parse_value_name_argument (const char *arg1, const char *funcname)
+{
+ const char *end;
+ int rc;
+
+ if (arg1 == NULL)
+ return 0;
+
+ end = strchr (arg1, '\0');
+ strip_whitespace (&arg1, &end);
+
+ if (!strncmp (arg1, "name", end - arg1))
+ rc = 0;
+ else if (!strncmp (arg1, "value", end - arg1))
+ rc = 1;
+ else
+#if 1 /* FIXME: later */
+ fatal (*expanding_var,
+ _("second argument to `%s' function must be `name' or `value', not `%s'"),
+ funcname, arg1);
+#else
+ {
+ /* check the expanded form */
+ char *exp = expand_argument (arg1, strchr (arg1, '\0'));
+ arg1 = exp;
+ end = strchr (arg1, '\0');
+ strip_whitespace (&arg1, &end);
+
+ if (!strncmp (arg1, "name", end - arg1))
+ rc = 0;
+ else if (!strncmp (arg1, "value", end - arg1))
+ rc = 1;
+ else
+ fatal (*expanding_var,
+ _("second argument to `%s' function must be `name' or `value', not `%s'"),
+ funcname, exp);
+ free (exp);
+ }
+#endif
+
+ return rc;
+}
+
+/* Given a list of variable names (ARGV[0]), returned the first variable which
+ is defined (i.e. value is not empty). ARGV[1] indicates whether to return
+ the variable name or its value. */
+static char *
+func_firstdefined (char *o, char **argv, const char *funcname)
+{
+ unsigned int i;
+ const char *words = argv[0]; /* Use a temp variable for find_next_token */
+ const char *p;
+ int ret_value = parse_value_name_argument (argv[1], funcname);
+
+ /* FIXME: Optimize by not expanding the arguments, but instead expand them
+ one by one here. This will require a find_next_token variant which
+ takes `$(' and `)' into account. */
+ while ((p = find_next_token (&words, &i)) != NULL)
+ {
+ struct variable *v = lookup_variable (p, i);
+ if (v && v->value_length)
+ {
+ if (ret_value)
+ variable_expand_string_2 (o, v->value, v->value_length, &o);
+ else
+ o = variable_buffer_output (o, p, i);
+ break;
+ }
+ }
+
+ return o;
+}
+
+/* Given a list of variable names (ARGV[0]), returned the last variable which
+ is defined (i.e. value is not empty). ARGV[1] indicates whether to return
+ the variable name or its value. */
+static char *
+func_lastdefined (char *o, char **argv, const char *funcname)
+{
+ struct variable *last_v = NULL;
+ unsigned int i;
+ const char *words = argv[0]; /* Use a temp variable for find_next_token */
+ const char *p;
+ int ret_value = parse_value_name_argument (argv[1], funcname);
+
+ /* FIXME: Optimize this. Walk from the end on unexpanded arguments. */
+ while ((p = find_next_token (&words, &i)) != NULL)
+ {
+ struct variable *v = lookup_variable (p, i);
+ if (v && v->value_length)
+ {
+ last_v = v;
+ break;
+ }
+ }
+
+ if (last_v != NULL)
+ {
+ if (ret_value)
+ variable_expand_string_2 (o, last_v->value, last_v->value_length, &o);
+ else
+ o = variable_buffer_output (o, last_v->name, last_v->length);
+ }
+ return o;
+}
+
+#endif /* CONFIG_WITH_DEFINED_FUNCTIONS */
static char *
func_firstword (char *o, char **argv, const char *funcname UNUSED)
@@ -2476,9 +2694,9 @@ static char *
func_insert (char *o, char **argv, const char *funcname UNUSED)
{
const char *in = argv[0];
- size_t in_len = strlen (in);
+ math_int in_len = (math_int)strlen (in);
const char *str = argv[1];
- size_t str_len = strlen (str);
+ math_int str_len = (math_int)strlen (str);
math_int n = 0;
math_int length = str_len;
const char *pad = " ";
@@ -2617,7 +2835,7 @@ static char *
func_substr (char *o, char **argv, const char *funcname UNUSED)
{
const char *str = argv[0];
- size_t str_len = strlen (str);
+ math_int str_len = (math_int)strlen (str);
math_int start = math_int_from_string (argv[1]);
math_int length = 0;
const char *pad = NULL;
@@ -3401,9 +3619,10 @@ func_abspathex (char *o, char **argv, const char *funcname UNUSED)
/* cwd needs leading spaces chopped and may be optional,
in which case we're exactly like $(abspath ). */
- while (isblank(*cwd))
- cwd++;
- if (!*cwd)
+ if (cwd)
+ while (isblank (*cwd))
+ cwd++;
+ if (!cwd || !*cwd)
o = func_abspath (o, argv, funcname);
else
{
@@ -4443,7 +4662,7 @@ math_int_from_string (const char *str)
ch -= 'A' - 10;
else
{
- error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
+ error (NILF, _("bad number: '%s' (base=%u, pos=%lu)\n"), start, base, (unsigned long)(str - start));
return 0;
}
num *= base;
@@ -5047,15 +5266,22 @@ static struct function_table_entry function_table_init[] =
{ STRING_SIZE_TUPLE("notdir"), 0, 1, 1, func_notdir_suffix},
#ifdef CONFIG_WITH_ROOT_FUNC
{ STRING_SIZE_TUPLE("root"), 0, 1, 1, func_root},
+ { STRING_SIZE_TUPLE("notroot"), 0, 1, 1, func_notroot},
#endif
{ STRING_SIZE_TUPLE("subst"), 3, 3, 1, func_subst},
{ STRING_SIZE_TUPLE("suffix"), 0, 1, 1, func_notdir_suffix},
{ STRING_SIZE_TUPLE("filter"), 2, 2, 1, func_filter_filterout},
{ STRING_SIZE_TUPLE("filter-out"), 2, 2, 1, func_filter_filterout},
{ STRING_SIZE_TUPLE("findstring"), 2, 2, 1, func_findstring},
+#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
+ { STRING_SIZE_TUPLE("firstdefined"), 0, 2, 1, func_firstdefined},
+#endif
{ STRING_SIZE_TUPLE("firstword"), 0, 1, 1, func_firstword},
{ STRING_SIZE_TUPLE("flavor"), 0, 1, 1, func_flavor},
{ STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join},
+#ifdef CONFIG_WITH_DEFINED_FUNCTIONS
+ { STRING_SIZE_TUPLE("lastdefined"), 0, 2, 1, func_lastdefined},
+#endif
{ STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword},
{ STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst},
{ STRING_SIZE_TUPLE("realpath"), 0, 1, 1, func_realpath},
@@ -5065,6 +5291,9 @@ static struct function_table_entry function_table_init[] =
{ STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell},
{ STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort},
{ STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip},
+#ifdef CONFIG_WITH_WHERE_FUNCTION
+ { STRING_SIZE_TUPLE("where"), 0, 1, 1, func_where},
+#endif
{ STRING_SIZE_TUPLE("wildcard"), 0, 1, 1, func_wildcard},
{ STRING_SIZE_TUPLE("word"), 2, 2, 1, func_word},
{ STRING_SIZE_TUPLE("wordlist"), 3, 3, 1, func_wordlist},
diff --git a/src/kmk/incdep.c b/src/kmk/incdep.c
index 42ea7c7..140e0f8 100644
--- a/src/kmk/incdep.c
+++ b/src/kmk/incdep.c
@@ -1,11 +1,11 @@
#ifdef CONFIG_WITH_INCLUDEDEP
-/* $Id: incdep.c 2283 2009-02-24 04:54:00Z bird $ */
+/* $Id: incdep.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* incdep - Simple dependency files.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/job.c b/src/kmk/job.c
index 6d14300..a2c55ff 100644
--- a/src/kmk/job.c
+++ b/src/kmk/job.c
@@ -1008,6 +1008,7 @@ static void
set_child_handler_action_flags (int set_handler, int set_alarm)
{
struct sigaction sa;
+ int rval = 0;
#if defined(__EMX__) && !defined(__KLIBC__) /* bird */
/* The child handler must be turned off here. */
@@ -1018,11 +1019,13 @@ set_child_handler_action_flags (int set_handler, int set_alarm)
sa.sa_handler = child_handler;
sa.sa_flags = set_handler ? 0 : SA_RESTART;
#if defined SIGCHLD
- sigaction (SIGCHLD, &sa, NULL);
+ rval = sigaction (SIGCHLD, &sa, NULL);
#endif
#if defined SIGCLD && SIGCLD != SIGCHLD
- sigaction (SIGCLD, &sa, NULL);
+ rval = sigaction (SIGCLD, &sa, NULL);
#endif
+ if (rval != 0)
+ fprintf (stderr, "sigaction: %s (%d)\n", strerror (errno), errno);
#if defined SIGALRM
if (set_alarm)
{
diff --git a/src/kmk/kbuild.c b/src/kmk/kbuild.c
index ee2e55c..28a24cb 100644
--- a/src/kmk/kbuild.c
+++ b/src/kmk/kbuild.c
@@ -1,10 +1,10 @@
-/* $Id: kbuild.c 2248 2009-01-19 04:34:56Z bird $ */
+/* $Id: kbuild.c 2540 2011-08-02 20:13:24Z bird $ */
/** @file
* kBuild specific make functionality.
*/
/*
- * Copyright (c) 2006-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
@@ -154,7 +154,7 @@ void init_kbuild(int argc, char **argv)
memcpy(szTmp, pszImageName, cchImageName + 1);
rc = 0;
}
- }
+ }
}
# endif
@@ -2109,22 +2109,33 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
memcpy(pszDst, "_CMDS_", sizeof("_CMDS_"));
pVar = kbuild_get_recursive_variable(pszSrcVar);
do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
- !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
+ do_variable_definition_2(NILF, "kbsrc_cmds", pVar->value, pVar->value_length,
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
memcpy(pszSrc, "_OUTPUT", sizeof("_OUTPUT"));
memcpy(pszDst, "_OUTPUT_", sizeof("_OUTPUT_"));
pVar = kbuild_get_recursive_variable(pszSrcVar);
pOutput = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
- !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
+ pOutput = do_variable_definition_2(NILF, "kbsrc_output", pVar->value, pVar->value_length,
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
memcpy(pszSrc, "_OUTPUT_MAYBE", sizeof("_OUTPUT_MAYBE"));
memcpy(pszDst, "_OUTPUT_MAYBE_", sizeof("_OUTPUT_MAYBE_"));
pVar = kbuild_query_recursive_variable(pszSrcVar);
if (pVar)
+ {
pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, pVar->value, pVar->value_length,
- !pVar->recursive, 0, o_file, f_simple, 0 /* !target_var */);
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
+ pOutputMaybe = do_variable_definition_2(NILF, "kbsrc_output_maybe", pVar->value, pVar->value_length,
+ !pVar->recursive, 0, o_local, f_simple, 0 /* !target_var */);
+ }
else
- pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_file, f_simple, 0 /* !target_var */);
+ {
+ pOutputMaybe = do_variable_definition_2(NILF, pszDstVar, "", 0, 1, 0, o_local, f_simple, 0 /* !target_var */);
+ pOutputMaybe = do_variable_definition_2(NILF, "kbsrc_output_maybe", "", 0, 1, 0, o_local, f_simple, 0 /* !target_var */);
+ }
memcpy(pszSrc, "_DEPEND", sizeof("_DEPEND"));
memcpy(pszDst, "_DEPEND_", sizeof("_DEPEND_"));
@@ -2137,7 +2148,10 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
memcpy(psz, pSource->value, pSource->value_length + 1);
do_variable_definition_2(NILF, pszDstVar, pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length,
!pVar->recursive && !pDeps->recursive && !pSource->recursive,
- pszVal, o_file, f_simple, 0 /* !target_var */);
+ NULL, o_local, f_simple, 0 /* !target_var */);
+ do_variable_definition_2(NILF, "kbsrc_depend", pszVal, pVar->value_length + 1 + pDeps->value_length + 1 + pSource->value_length,
+ !pVar->recursive && !pDeps->recursive && !pSource->recursive,
+ pszVal, o_local, f_simple, 0 /* !target_var */);
memcpy(pszSrc, "_DEPORD", sizeof("_DEPORD"));
memcpy(pszDst, "_DEPORD_", sizeof("_DEPORD_"));
@@ -2151,7 +2165,11 @@ func_kbuild_source_one(char *o, char **argv, const char *pszFuncName)
do_variable_definition_2(NILF, pszDstVar, pszVal,
pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length,
!pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive,
- pszVal, o_file, f_simple, 0 /* !target_var */);
+ NULL, o_local, f_simple, 0 /* !target_var */);
+ do_variable_definition_2(NILF, "kbsrc_depord", pszVal,
+ pVar->value_length + 1 + pDirDep->value_length + 1 + pOrderDeps->value_length,
+ !pVar->recursive && !pDirDep->recursive && !pOrderDeps->recursive,
+ pszVal, o_local, f_simple, 0 /* !target_var */);
/*
_OUT_FILES += $($(target)_$(source)_OUTPUT_) $($(target)_$(source)_OUTPUT_MAYBE_)
@@ -2472,16 +2490,19 @@ func_kbuild_expand_template(char *o, char **argv, const char *pszFuncName)
aKeys[0].cch = 0;
aKeys[0].psz = NULL;
+ /* .$(bld_type) */
aKeys[1].cch = cchBldType + 1;
aKeys[1].psz = xmalloc (aKeys[1].cch + 1);
aKeys[1].psz[0] = '.';
memcpy(aKeys[1].psz + 1, pszBldType, cchBldType + 1);
+ /* .$(bld_trg) */
aKeys[2].cch = cchBldTrg + 1;
aKeys[2].psz = xmalloc (aKeys[2].cch + 1);
aKeys[2].psz[0] = '.';
memcpy(aKeys[2].psz + 1, pszBldTrg, cchBldTrg + 1);
+ /* .$(bld_trg).$(bld_trg_arch) */
aKeys[3].cch = cchBldTrg + 1 + cchBldTrgArch + 1;
aKeys[3].psz = xmalloc (aKeys[3].cch + 1);
aKeys[3].psz[0] = '.';
@@ -2489,11 +2510,13 @@ func_kbuild_expand_template(char *o, char **argv, const char *pszFuncName)
aKeys[3].psz[1 + cchBldTrg] = '.';
memcpy(aKeys[3].psz + 1 + cchBldTrg + 1, pszBldTrgArch, cchBldTrgArch + 1);
+ /* .$(bld_trg_cpu) */
aKeys[4].cch = cchBldTrgCpu + 1;
aKeys[4].psz = xmalloc (aKeys[4].cch + 1);
aKeys[4].psz[0] = '.';
memcpy(aKeys[4].psz + 1, pszBldTrgCpu, cchBldTrgCpu + 1);
+ /* .$(bld_trg_arch) */
aKeys[5].cch = cchBldTrgArch + 1;
aKeys[5].psz = xmalloc (aKeys[5].cch + 1);
aKeys[5].psz[0] = '.';
diff --git a/src/kmk/kbuild.h b/src/kmk/kbuild.h
index 1f7f438..5d06d31 100644
--- a/src/kmk/kbuild.h
+++ b/src/kmk/kbuild.h
@@ -1,10 +1,10 @@
-/* $Id: kbuild.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: kbuild.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kBuild specific make functionality.
*/
/*
- * Copyright (c) 2006-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kdepdb.c b/src/kmk/kdepdb.c
new file mode 100644
index 0000000..c90cd6b
--- /dev/null
+++ b/src/kmk/kdepdb.c
@@ -0,0 +1,1087 @@
+/* $Id: incdep.c 2283 2009-02-24 04:54:00Z bird $ */
+/** @file
+ * kdepdb - Dependency database.
+ */
+
+/*
+ * Copyright (c) 2009-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "make.h"
+#include "../lib/k/kDefs.h"
+#include "../lib/k/kTypes.h"
+#include <assert.h>
+#include <glob.h>
+
+#include "dep.h"
+#include "filedef.h"
+#include "job.h"
+#include "commands.h"
+#include "variable.h"
+#include "rule.h"
+#include "debug.h"
+#include "strcache2.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# include <sys/file.h>
+#endif
+
+#if K_OS == K_WINDOWS
+# include <Windows.h>
+#else
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** @def KDEPDB_ASSERT_SIZE
+ * Check the size of an on-disk type.
+ *
+ * @param Type The type which size it being checked.
+ * @param Size The size it should have.
+ */
+#ifdef __GNUC__
+# define KDEPDB_ASSERT_SIZE(Type, Size) \
+ extern int kDepDbAssertSize[1] __attribute__((unused)), \
+ kDepDbAssertSize[sizeof(Type) == (Size)] __attribute__((unused))
+#else
+# define KDEPDB_ASSERT_SIZE(Type, Size) \
+ typedef int kDepDbAssertSize[sizeof(Type) == (Size)]
+#endif
+KDEPDB_ASSERT_SIZE(KU8, 1);
+KDEPDB_ASSERT_SIZE(KU16, 2);
+KDEPDB_ASSERT_SIZE(KU32, 4);
+KDEPDB_ASSERT_SIZE(KU64, 8);
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+/**
+ * File header.
+ *
+ * @remarks All on-disk formats are in little-endian format.
+ */
+typedef struct KDEPDBHDR
+{
+ /** The file magic. */
+ KU8 szMagic[8];
+ /** The major file format version. */
+ KU8 uVerMajor;
+ /** The minor file format version. */
+ KU8 uVerMinor;
+ /** Reserved \#2. */
+ KU16 uReserved2;
+ /** Reserved \#1. */
+ KU32 uReserved1;
+ /** The internal name of this file. */
+ KU8 szName[16];
+} KDEPDBHDR;
+KDEPDB_ASSERT_SIZE(KDEPDBHDR, 32);
+
+/** The file header magic value. */
+#define KDEPDBHDR_MAGIC "kDepDb\0"
+/** The current major file format version number. */
+#define KDEPDBHDR_VERSION_MAJOR 0
+/** The current minor file format version number.
+ * Numbers above 240 indicate unsupported development variants. */
+#define KDEPDBHDR_VERSION_MINOR 240
+
+
+/**
+ * Hash table file.
+ *
+ * The hash table is recreated in a new file when we have to grow it.
+ */
+typedef struct KDEPDBHASH
+{
+ /** The file header. */
+ KDEPDBHDR Hdr;
+ /** The number of hash table entries. */
+ KU32 cEntries;
+ /** The number of hash table entries with content. */
+ KU32 cUsedEntries;
+ /** The number of collisions on insert. */
+ KU32 cCollisions;
+ /** Reserved member \#5. */
+ KU32 uReserved5;
+ /** Reserved member \#4. */
+ KU32 uReserved4;
+ /** Reserved member \#3. */
+ KU32 uReserved3;
+ /** Reserved member \#2. */
+ KU32 uReserved2;
+ /** Reserved member \#1. */
+ KU32 uReserved1;
+ /** The hash table. */
+ KU32 auEntries[32];
+} KDEPDBHASH;
+KDEPDB_ASSERT_SIZE(KDEPDBHASH, 32+32+4*32);
+
+/** The item value indicating that it is unused. */
+#define KDEPDBHASH_UNUSED KU32_C(0xffffffff)
+/** The item indicating that it hash been deleted. */
+#define KDEPDBHASH_DELETED KU32_C(0xfffffffe)
+/** The first special item value. */
+#define KDEPDBHASH_END KU32_C(0xfffffff0)
+
+
+/**
+ * A string table string entry.
+ *
+ * This should be a multiple of 32 bytes.
+ */
+typedef struct KDEPDBSTRING
+{
+ /** The hash number for the string. */
+ KU32 uHash;
+ /** The string length, excluding the zero terminator. */
+ KU32 cchString;
+ /** The string. */
+ KU8 szString[24];
+} KDEPDBSTRING;
+KDEPDB_ASSERT_SIZE(KDEPDBSTRING, 32);
+
+
+/**
+ * String table file.
+ *
+ * The file is insertion only and will grow forever.
+ */
+typedef struct KDEPDBSTRTAB
+{
+ /** The file header. */
+ KDEPDBHDR Hdr;
+ /** The end of the valid string table indexes. */
+ KU32 iStringEnd;
+ /** Reserved member \#7. */
+ KU32 uReserved7;
+ /** Reserved member \#6. */
+ KU32 uReserved6;
+ /** Reserved member \#5. */
+ KU32 uReserved5;
+ /** Reserved member \#4. */
+ KU32 uReserved4;
+ /** Reserved member \#3. */
+ KU32 uReserved3;
+ /** Reserved member \#2. */
+ KU32 uReserved2;
+ /** Reserved member \#1. */
+ KU32 uReserved1;
+ /** The string table. */
+ KDEPDBSTRING aStrings[1];
+} KDEPDBSTRTAB;
+KDEPDB_ASSERT_SIZE(KDEPDBSTRTAB, 32+32+32);
+
+/** The end of the valid string table indexes (exclusive). */
+#define KDEPDBG_STRTAB_IDX_END KU32_C(0x80000000)
+/** The string was not found. */
+#define KDEPDBG_STRTAB_IDX_NOT_FOUND KU32_C(0xfffffffd)
+/** Error during string table operation. */
+#define KDEPDBG_STRTAB_IDX_ERROR KU32_C(0xfffffffe)
+/** Generic invalid string table index. */
+#define KDEPDBG_STRTAB_IDX_INVALID KU32_C(0xffffffff)
+
+
+/**
+ * Directory entry.
+ */
+typedef struct KDEPDBDIRENTRY
+{
+ /** The string table index of the entry name.
+ * Unused entries are set to KDEPDBG_STRTAB_IDX_INVALID. */
+ KU32 iName;
+ /** The actual data stream size.
+ * Unused entries are set to KU32_MAX. */
+ KU32 cbData;
+ /** The number of blocks allocated for this stream.
+ * Unused entries are set to KU32_MAX. */
+ KU32 cBlocks;
+ /** The start block number.
+ * The stream is a contiguous sequence of blocks. This optimizes and
+ * simplifies reading the stream at the expense of operations extending it.
+ *
+ * In unused entries, this serves as the free chain pointer with KU32_MAX as
+ * nil value. */
+ KU32 iStartBlock;
+} KDEPDBDIRENTRY;
+KDEPDB_ASSERT_SIZE(KDEPDBDIRENTRY, 16);
+
+/**
+ * Directory file.
+ */
+typedef struct KDEPDBDIR
+{
+ /** The file header. */
+ KDEPDBHDR Hdr;
+ /** The number of entries. */
+ KU32 cEntries;
+ /** The head of the free chain. (Index into aEntries.) */
+ KU32 iFreeHead;
+ /** Reserved member \#6. */
+ KU32 uReserved6;
+ /** Reserved member \#5. */
+ KU32 uReserved5;
+ /** Reserved member \#4. */
+ KU32 uReserved4;
+ /** Reserved member \#3. */
+ KU32 uReserved3;
+ /** Reserved member \#2. */
+ KU32 uReserved2;
+ /** Reserved member \#1. */
+ KU32 uReserved1;
+ /** Directory entries. */
+ KDEPDBDIRENTRY aEntries[2];
+} KDEPDBDIR;
+KDEPDB_ASSERT_SIZE(KDEPDBDIR, 32+32+32);
+
+
+/**
+ * A block allocation bitmap.
+ *
+ * This can track 2^(12+8) = 2^20 = 1M blocks.
+ */
+typedef struct KDEPDBDATABITMAP
+{
+ /** Bitmap where each bit is a block.
+ * 0 indicates unused blocks and 1 indicates used ones. */
+ KU8 bm[4096];
+} KDEPDBDATABITMAP;
+KDEPDB_ASSERT_SIZE(KDEPDBDATABITMAP, 4096);
+
+/**
+ * Data file.
+ *
+ * The block numbering starts with this structure as block 0.
+ */
+typedef struct KDEPDBDATA
+{
+ /** The file header. */
+ KDEPDBHDR Hdr;
+ /** The size of a block. */
+ KU32 cbBlock;
+ /** Reserved member \#7. */
+ KU32 uReserved7;
+ /** Reserved member \#6. */
+ KU32 uReserved6;
+ /** Reserved member \#5. */
+ KU32 uReserved5;
+ /** Reserved member \#4. */
+ KU32 uReserved4;
+ /** Reserved member \#3. */
+ KU32 uReserved3;
+ /** Reserved member \#2. */
+ KU32 uReserved2;
+ /** Reserved member \#1. */
+ KU32 uReserved1;
+
+ /** Block numbers for the allocation bitmaps. */
+ KU32 aiBitmaps[4096];
+} KDEPDBDATA;
+
+/** The end of the valid block indexes (exclusive). */
+#define KDEPDB_BLOCK_IDX_END KU32_C(0xfffffff0)
+/** The index of an unallocated bitmap block. */
+#define KDEPDB_BLOCK_IDX_UNALLOCATED KU32_C(0xffffffff)
+
+
+/**
+ * Stream storing dependencies.
+ *
+ * The stream name gives the output file name, so all that we need is the list
+ * of files it depends on. These are serialized as a list of string table
+ * indexes.
+ */
+typedef struct KDEPDBDEPSTREAM
+{
+ /** String table indexes for the dependencies. */
+ KU32 aiDeps[1];
+} KDEPDBDEPSTREAM;
+
+
+/**
+ * A file handle structure.
+ */
+typedef struct KDEPDBFH
+{
+#if K_OS == K_OS_WINDOWS
+ /** The file handle. */
+ HANDLE hFile;
+ /** The mapping object handle. */
+ HANDLE hMapObj;
+#else
+ /** The file handle. */
+ int fd;
+#endif
+ /** The current file size. */
+ KU32 cb;
+} KDEPDBFH;
+
+
+/**
+ * Internal control structure for a string table.
+ */
+typedef struct KDEPDBINTSTRTAB
+{
+ /** The hash file. */
+ KDEPDBHASH *pHash;
+ /** The handle of the hash file. */
+ KDEPDBFH hHash;
+ /** The string table file. */
+ KDEPDBSTRTAB *pStrTab;
+ /** The handle of the string table file. */
+ KDEPDBFH hStrTab;
+ /** The end of the allocated string table indexes (i.e. when to grow the
+ * file). */
+ KU32 iStringAlloced;
+} KDEPDBINTSTRTAB;
+
+
+/**
+ * Internal control structure for a data set.
+ *
+ * This governs the directory file, the directory hash file and the data file.
+ */
+typedef struct KDEPDBINTDATASET
+{
+ /** The hash file. */
+ KDEPDBHASH pHash;
+ /** The size of the hash file. */
+ KU32 cbHash;
+ /** The size of the directory file. */
+ KU32 cbDir;
+ /** The mapping of the directory file. */
+ KDEPDBHASH pDir;
+ /** The data file. */
+ KDEPDBDATA pData;
+ /** The size of the data file. */
+ KU32 cbData;
+ /** The handle of the hash file. */
+ KDEPDBFH hHash;
+ /** The handle of the directory file. */
+ KDEPDBFH hDir;
+ /** The handle of the data file. */
+ KDEPDBFH hData;
+} KDEPDBINTDATASET;
+
+
+/**
+ * The database instance.
+ *
+ * To simplifiy things the database uses 8 files for storing the different kinds
+ * of data. This greatly reduces the complexity compared to a single file
+ * solution.
+ */
+typedef struct KDEPDB
+{
+ /** The string table. */
+ KDEPDBINTSTRTAB StrTab;
+ /** The variable data set. */
+ KDEPDBINTDATASET DepSet;
+ /** The command data set. */
+ KDEPDBINTDATASET CmdSet;
+} KDEPDB;
+
+
+/*******************************************************************************
+* Internal Functions *
+*******************************************************************************/
+static void *kDepDbAlloc(KSIZE cb);
+static void kDepDbFree(void *pv);
+static void kDepDbFHInit(KDEPDBFH *pFH);
+static int kDepDbFHUpdateSize(KDEPDBFH *pFH);
+static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfNew);
+static int kDepDbFHClose(KDEPDBFH *pFH);
+static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf);
+static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap);
+static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap);
+static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap);
+static KU32 kDepDbHashString(const char *pszString, size_t cchString);
+
+
+/** xmalloc wrapper. */
+static void *kDepDbAlloc(KSIZE cb)
+{
+ return xmalloc(cb);
+}
+
+/** free wrapper. */
+static void kDepDbFree(void *pv)
+{
+ if (pv)
+ free(pv);
+}
+
+
+/**
+ * Initializes the file handle structure so closing it without first opening it
+ * will work smoothly.
+ *
+ * @param pFH The file handle structure.
+ */
+static void kDepDbFHInit(KDEPDBFH *pFH)
+{
+#if K_OS == K_OS_WINDOWS
+ pFH->hFile = INVALID_HANDLE_VALUE;
+ pFH->hMapObj = INVALID_HANDLE_VALUE;
+#else
+ pFH->fd = -1;
+#endif
+ pFH->cb = 0;
+}
+
+/**
+ * Updates the file size.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ * @param pFH The file handle structure.
+ */
+static int kDepDbFHUpdateSize(KDEPDBFH *pFH)
+{
+#if K_OS == K_OS_WINDOWS
+ DWORD rc;
+ DWORD dwHigh;
+ DWORD dwLow;
+
+ SetLastError(0);
+ dwLow = GetFileSize(File, &High);
+ rc = GetLastError();
+ if (rc)
+ {
+ pFH->cb = 0;
+ return (int)rc;
+ }
+ if (High)
+ pFH->cb = KU32_MAX;
+ else
+ pFH->cb = dwLow;
+#else
+ off_t cb;
+
+ cb = lseek(pFH->fd, 0, SEEK_END);
+ if (cb == -1)
+ {
+ pFH->cb = 0;
+ return errno;
+ }
+ pFH->cb = cb;
+ if ((off_t)pFH->cb != cb)
+ pFH->cb = KU32_MAX;
+#endif
+ return 0;
+}
+
+/**
+ * Opens an existing file or creates a new one.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ * @param pszFilename The name of the file.
+ * @param fCreate Whether we should create the file or not.
+ * @param pfCreated Where to return whether we created it or not.
+ */
+static int kDepDbFHOpen(KDEPDBFH *pFH, const char *pszFilename, KBOOL fCreate, KBOOL *pfCreated)
+{
+ int rc;
+#if K_OS == K_OS_WINDOWS
+ SECURITY_ATTRIBUTES SecAttr;
+
+ SecAttr.bInheritHandle = FALSE;
+ SecAttr.lpSecurityDescriptor = NULL;
+ SecAttr.nLength = 0;
+ pFH->cb = 0;
+ SetLastError(0);
+ pFH->hFile = CreateFile(pszFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, &SecAttr,
+ fCreate ? OPEN_ALWAYS : OPEN_EXISTING, 0, NULL);
+ if (pFH->hFile == INVALID_HANDLE_VALUE)
+ return GetLastError();
+ *pfCreated = GetLastError() == 0;
+
+#else
+ int fFlags = O_RDWR;
+# ifdef O_BINARY
+ fFlags |= O_BINARY;
+# endif
+ pFH->cb = 0;
+ pFH->fd = open(pszFilename, fFlags, 0);
+ if (pFH->fd >= 0)
+ *pfCreated = K_FALSE;
+ else if (!fCreate)
+ return errno;
+ else
+ {
+ pFH->fd = open(pszFilename, fFlags | O_EXCL | O_CREAT, 0666);
+ if (pFH->fd < 0)
+ return errno;
+ *pfCreated = K_TRUE;
+ }
+ fcntl(pFH->fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+ /* update the size */
+ rc = kDepDbFHUpdateSize(pFH);
+ if (rc)
+ kDepDbFHClose(pFH);
+ return rc;
+}
+
+/**
+ * Closes an open file.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ */
+static int kDepDbFHClose(KDEPDBFH *pFH)
+{
+#if K_OS == K_OS_WINDOWS
+ if (pFH->hFile != INVALID_HANDLE_VALUE)
+ {
+ if (!CloseHandle(pFH->hFile))
+ return GetLastError();
+ pFH->hFile = INVALID_HANDLE_VALUE;
+ }
+
+#else
+ if (pFH->fd >= 0)
+ {
+ if (close(pFH->fd) != 0)
+ return errno;
+ pFH->fd = -1;
+ }
+#endif
+ pFH->cb = 0;
+ return 0;
+}
+
+/**
+ * Writes to a file.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ * @param off The offset into the file to start writing at.
+ * @param pvBuf What to write.
+ * @param cbBuf How much to write.
+ */
+static int kDepDbFHWriteAt(KDEPDBFH *pFH, KU32 off, void const *pvBuf, KSIZE cbBuf)
+{
+#if K_OS == K_OS_WINDOWS
+ ULONG cbWritten;
+
+ if (SetFilePointer(pFH->hFile, off, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ return GetLastError();
+
+ if (!WriteFile(pFH->hFile, pvBuf, cbBuf, &cbWritten, NULL))
+ return GetLastError();
+ if (cbWritten != cbBuf)
+ return -1;
+
+#else
+ ssize_t cbWritten;
+ if (lseek(pFH->fd, off, SEEK_SET) == -1)
+ return errno;
+ errno = 0;
+ cbWritten = write(pFH->fd, pvBuf, cbBuf);
+ if ((size_t)cbWritten != cbBuf)
+ return errno ? errno : EIO;
+#endif
+ return kDepDbFHUpdateSize(pFH);
+}
+
+
+/**
+ * Creates a memory mapping of the file.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ * @param ppvMap Where to return the map address.
+ */
+static int kDepDbFHMap(KDEPDBFH *pFH, void **ppvMap)
+{
+#if K_OS == K_OS_WINDOWS
+ *ppvMap = NULL;
+ return -1;
+#else
+ *ppvMap = mmap(NULL, pFH->cb, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pFH->fd, 0);
+ if (*ppvMap == (void *)-1)
+ {
+ *ppvMap = NULL;
+ return errno;
+ }
+#endif
+ return 0;
+}
+
+
+/**
+ * Flushes and destroys a memory of the file.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ * @param ppvMap The pointer to the mapping pointer. This will be set to
+ * NULL on success.
+ */
+static int kDepDbFHUnmap(KDEPDBFH *pFH, void **ppvMap)
+{
+#if K_OS == K_OS_WINDOWS
+ return -1;
+#else
+ if (msync(*ppvMap, pFH->cb, MS_SYNC) == -1)
+ return errno;
+ if (munmap(*ppvMap, pFH->cb) == -1)
+ return errno;
+ *ppvMap = NULL;
+#endif
+ return 0;
+}
+
+
+/**
+ * Grows the memory mapping of the file.
+ *
+ * The content of the new space is undefined.
+ *
+ * @returns 0 on success. Some non-zero native error code on failure.
+ *
+ * @param pFH The file handle structure.
+ * @param cbNew The new mapping size.
+ * @param ppvMap The pointer to the mapping pointer. This may change and
+ * may be set to NULL on failure.
+ */
+static int kDepDbFHGrow(KDEPDBFH *pFH, KSIZE cbNew, void **ppvMap)
+{
+#if K_OS == K_OS_WINDOWS
+ return -1;
+#else
+ if ((KU32)cbNew != cbNew)
+ return ERANGE;
+ if (cbNew <= pFH->cb)
+ return 0;
+
+ if (munmap(*ppvMap, pFH->cb) == -1)
+ return errno;
+ *ppvMap = NULL;
+
+ pFH->cb = cbNew;
+ return kDepDbFHMap(pFH, ppvMap);
+#endif
+}
+
+
+/** Macro for reading an potentially unaligned 16-bit word from a string. */
+# if K_ARCH == K_ARCH_AMD64 \
+ || K_ARCH == K_ARCH_X86_32 \
+ || K_ARCH == K_ARCH_X86_16
+# define kDepDbHashString_get_unaligned_16bits(ptr) ( *((const KU16 *)(ptr)) )
+# elif K_ENDIAN == K_ENDIAN_LITTLE
+# define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0]) \
+ | (((const KU8 *)(ptr))[1] << 8) )
+# else
+# define kDepDbHashString_get_unaligned_16bits(ptr) ( (((const KU8 *)(ptr))[0] << 8) \
+ | (((const KU8 *)(ptr))[1]) )
+# endif
+
+
+/**
+ * Hash a string.
+ *
+ * @returns Hash value.
+ *
+ * @param pszString The string to hash.
+ * @param cchString How much to hash.
+ */
+static KU32 kDepDbHashString(const char *pszString, size_t cchString)
+{
+ /*
+ * Paul Hsieh hash SuperFast function:
+ * http://www.azillionmonkeys.com/qed/hash.html
+ */
+ /** @todo A path for well aligned data should be added to speed up execution on
+ * alignment sensitive systems. */
+ unsigned int uRem;
+ KU32 uHash;
+ KU32 uTmp;
+
+ assert(sizeof(KU8) == sizeof(char));
+
+ /* main loop, walking on 2 x KU16 */
+ uHash = cchString;
+ uRem = cchString & 3;
+ cchString >>= 2;
+ while (cchString > 0)
+ {
+ uHash += kDepDbHashString_get_unaligned_16bits(pszString);
+ uTmp = (kDepDbHashString_get_unaligned_16bits(pszString + 2) << 11) ^ uHash;
+ uHash = (uHash << 16) ^ uTmp;
+ pszString += 2 * sizeof(KU16);
+ uHash += uHash >> 11;
+ cchString--;
+ }
+
+ /* the remainder */
+ switch (uRem)
+ {
+ case 3:
+ uHash += kDepDbHashString_get_unaligned_16bits(pszString);
+ uHash ^= uHash << 16;
+ uHash ^= pszString[sizeof(KU16)] << 18;
+ uHash += uHash >> 11;
+ break;
+ case 2:
+ uHash += kDepDbHashString_get_unaligned_16bits(pszString);
+ uHash ^= uHash << 11;
+ uHash += uHash >> 17;
+ break;
+ case 1:
+ uHash += *pszString;
+ uHash ^= uHash << 10;
+ uHash += uHash >> 1;
+ break;
+ }
+
+ /* force "avalanching" of final 127 bits. */
+ uHash ^= uHash << 3;
+ uHash += uHash >> 5;
+ uHash ^= uHash << 4;
+ uHash += uHash >> 17;
+ uHash ^= uHash << 25;
+ uHash += uHash >> 6;
+
+ return uHash;
+}
+
+
+/***
+ * Looks up a string in the string table.
+ *
+ * @returns The string table index.
+ * @retval KDEPDBG_STRTAB_IDX_NOT_FOUND is not found.
+ * @retval KDEPDBG_STRTAB_IDX_ERROR on internal inconsistency.
+ *
+ * @param pStrTab The string table.
+ * @param pszString The string.
+ * @param cchStringIn The string length.
+ * @param uHash The hash of the string.
+ */
+static KU32 kDepDbStrTabLookupHashed(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash)
+{
+ KU32 const cchString = (KU32)cchStringIn;
+ KDEPDBHASH const *pHash = pStrTab->pHash;
+ KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0];
+ KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
+ KU32 iHash;
+
+ /* sanity */
+ if (cchString != cchStringIn)
+ return KDEPDBG_STRTAB_IDX_NOT_FOUND;
+
+ /*
+ * Hash lookup of the string.
+ */
+ iHash = uHash % pHash->cEntries;
+ for (;;)
+ {
+ KU32 iString = K_LE2H_U32(pHash->auEntries[iHash]);
+ if (iString < iStringEnd)
+ {
+ KDEPDBSTRING const *pString = &paStrings[iString];
+ if ( K_LE2H_U32(pString->uHash) == uHash
+ && K_LE2H_U32(pString->cchString) == cchString
+ && !memcmp(pString->szString, pszString, cchString))
+ return iString;
+ }
+ else if (iString == KDEPDBHASH_UNUSED)
+ return KDEPDBG_STRTAB_IDX_NOT_FOUND;
+ else if (iString != KDEPDBHASH_DELETED)
+ return KDEPDBG_STRTAB_IDX_ERROR;
+
+ /* advance */
+ iHash = (iHash + 1) % pHash->cEntries;
+ }
+}
+
+
+/**
+ * Doubles the hash table size and rehashes it.
+ *
+ * @returns 0 on success, -1 on failure.
+ * @param pStrTab The string table.
+ * @todo Rebuild from string table, we'll be accessing it anyways.
+ */
+static int kDepDbStrTabReHash(KDEPDBINTSTRTAB *pStrTab)
+{
+ KDEPDBSTRING const *paStrings = &pStrTab->pStrTab->aStrings[0];
+ KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
+ KDEPDBHASH *pHash = pStrTab->pHash;
+ KDEPDBHASH HashHdr = *pHash;
+ KU32 *pauNew;
+ KU32 cEntriesNew;
+ KU32 i;
+
+ /*
+ * Calc the size of the new hash table.
+ */
+ if (pHash->cEntries >= KU32_C(0x80000000))
+ return -1;
+ cEntriesNew = 1024;
+ while (cEntriesNew <= pHash->cEntries)
+ cEntriesNew <<= 1;
+
+ /*
+ * Allocate and initialize an empty hash table in memory.
+ */
+ pauNew = kDepDbAlloc(cEntriesNew * sizeof(KU32));
+ if (!pauNew)
+ return -1;
+ i = cEntriesNew;
+ while (i-- > 0)
+ pauNew[i] = KDEPDBHASH_UNUSED;
+
+ /*
+ * Popuplate the new table.
+ */
+ HashHdr.cEntries = K_LE2H_U32(cEntriesNew);
+ HashHdr.cCollisions = 0;
+ HashHdr.cUsedEntries = 0;
+ i = pHash->cEntries;
+ while (i-- > 0)
+ {
+ KU32 iString = K_LE2H_U32(pHash->auEntries[i]);
+ if (iString < iStringEnd)
+ {
+ KU32 iHash = (paStrings[iString].uHash % cEntriesNew);
+ if (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED))
+ {
+ do
+ {
+ iHash = (iHash + 1) % cEntriesNew;
+ HashHdr.cCollisions++;
+ } while (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED));
+ }
+ pauNew[iHash] = iString;
+ HashHdr.cUsedEntries++;
+ }
+ else if ( iString != KDEPDBHASH_UNUSED
+ && iString != KDEPDBHASH_DELETED)
+ {
+ kDepDbFree(pauNew);
+ return -1;
+ }
+ }
+ HashHdr.cCollisions = K_H2LE_U32(HashHdr.cCollisions);
+ HashHdr.cUsedEntries = K_H2LE_U32(HashHdr.cUsedEntries);
+
+ /*
+ * Unmap the hash, write the new hash table and map it again.
+ */
+ if (!kDepDbFHUnmap(&pStrTab->hHash, (void **)&pStrTab->pHash))
+ {
+ if ( !kDepDbFHWriteAt(&pStrTab->hHash, 0, &HashHdr, K_OFFSETOF(KDEPDBHASH, auEntries))
+ && !kDepDbFHWriteAt(&pStrTab->hHash, K_OFFSETOF(KDEPDBHASH, auEntries), pauNew, sizeof(pauNew[0]) * cEntriesNew))
+ {
+ kDepDbFree(pauNew);
+ pauNew = NULL;
+ if (!kDepDbFHMap(&pStrTab->hHash, (void **)&pStrTab->pHash))
+ return 0;
+ }
+ else
+ kDepDbFHWriteAt(&pStrTab->hHash, 0, "\0\0\0\0", 4); /* file is screwed, trash the magic. */
+ }
+
+ kDepDbFree(pauNew);
+ return -1;
+}
+
+
+/**
+ * Add a string to the string table.
+ *
+ * If already in the table, the index of the existing entry is returned.
+ *
+ * @returns String index on success,
+ * @retval KDEPDBG_STRTAB_IDX_ERROR on I/O and inconsistency errors.
+ *
+ * @param pStrTab The string table.
+ * @param pszString The string to add.
+ * @param cchStringIn The length of the string.
+ * @param uHash The hash of the string.
+ */
+static KU32 kDepDbStrTabAddHashed(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash)
+{
+ KU32 const cchString = (KU32)cchStringIn;
+ KDEPDBHASH *pHash = pStrTab->pHash;
+ KDEPDBSTRING *paStrings = &pStrTab->pStrTab->aStrings[0];
+ KU32 const iStringEnd = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
+ KU32 iInsertAt = KDEPDBHASH_UNUSED;
+ KU32 cCollisions = 0;
+ KU32 iHash;
+ KU32 iString;
+ KU32 cEntries;
+ KDEPDBSTRING *pNewString;
+
+ /* sanity */
+ if (cchString != cchStringIn)
+ return KDEPDBG_STRTAB_IDX_NOT_FOUND;
+
+ /*
+ * Hash lookup of the string, finding either an existing copy or where to
+ * insert the new string at in the hash table.
+ */
+ iHash = uHash % pHash->cEntries;
+ for (;;)
+ {
+ iString = K_LE2H_U32(pHash->auEntries[iHash]);
+ if (iString < iStringEnd)
+ {
+ KDEPDBSTRING const *pString = &paStrings[iString];
+ if ( K_LE2H_U32(pString->uHash) == uHash
+ && K_LE2H_U32(pString->cchString) == cchString
+ && !memcmp(pString->szString, pszString, cchString))
+ return iString;
+ }
+ else
+ {
+ if (iInsertAt == KDEPDBHASH_UNUSED)
+ iInsertAt = iHash;
+ if (iString == KDEPDBHASH_UNUSED)
+ break;
+ if (iString != KDEPDBHASH_DELETED)
+ return KDEPDBG_STRTAB_IDX_ERROR;
+ }
+
+ /* advance */
+ cCollisions++;
+ iHash = (iHash + 1) % pHash->cEntries;
+ }
+
+ /*
+ * Add string to the string table.
+ * The string table file is grown in 256KB increments and ensuring at least 64KB unused new space.
+ */
+ cEntries = cchString + 1 <= sizeof(paStrings[0].szString)
+ ? 1
+ : (cchString + 1 - sizeof(paStrings[0].szString) + sizeof(KDEPDBSTRING) - 1) / sizeof(KDEPDBSTRING);
+ if (iStringEnd + cEntries > pStrTab->iStringAlloced)
+ {
+ KSIZE cbNewSize = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024);
+ KU32 iStringAlloced = (pStrTab->hStrTab.cb - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING);
+ if ( iStringAlloced <= pStrTab->iStringAlloced
+ || iStringAlloced >= KDEPDBG_STRTAB_IDX_END
+ || iStringAlloced >= KDEPDBHASH_END)
+ return KDEPDBG_STRTAB_IDX_ERROR;
+ if (kDepDbFHGrow(&pStrTab->hStrTab, cbNewSize, (void **)&pStrTab->pStrTab) != 0)
+ return KDEPDBG_STRTAB_IDX_ERROR;
+ pStrTab->iStringAlloced = iStringAlloced;
+ paStrings = &pStrTab->pStrTab->aStrings[0];
+ }
+
+ pNewString = &paStrings[iStringEnd];
+ pNewString->uHash = K_H2LE_U32(uHash);
+ pNewString->cchString = K_H2LE_U32(cchString);
+ memcpy(&pNewString->szString, pszString, cchString);
+ pNewString->szString[cchString] = '\0';
+
+ pStrTab->pStrTab->iStringEnd = K_H2LE_U32(iStringEnd + cEntries);
+
+ /*
+ * Insert hash table entry, rehash it if necessary.
+ */
+ pHash->auEntries[iInsertAt] = K_H2LE_U32(iStringEnd);
+ pHash->cUsedEntries = K_H2LE_U32(K_LE2H_U32(pHash->cUsedEntries) + 1);
+ pHash->cCollisions = K_H2LE_U32(K_LE2H_U32(pHash->cCollisions) + cCollisions);
+ if ( K_LE2H_U32(pHash->cUsedEntries) > K_LE2H_U32(pHash->cEntries) / 3 * 2
+ && kDepDbStrTabReHash(pStrTab) != 0)
+ return KDEPDBG_STRTAB_IDX_ERROR;
+
+ return iStringEnd;
+}
+
+
+/** Wrapper for kDepDbStrTabLookupHashed. */
+static KU32 kDepDbStrTabLookupN(KDEPDBINTSTRTAB const *pStrTab, const char *pszString, size_t cchString)
+{
+ return kDepDbStrTabLookupHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString));
+}
+
+
+/** Wrapper for kDepDbStrTabAddHashed. */
+static KU32 kDepDbStrTabAddN(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchString)
+{
+ return kDepDbStrTabAddHashed(pStrTab, pszString, cchString, kDepDbHashString(pszString, cchString));
+}
+
+
+/** Wrapper for kDepDbStrTabLookupHashed. */
+static KU32 kDepDbStrTabLookup(KDEPDBINTSTRTAB const *pStrTab, const char *pszString)
+{
+ return kDepDbStrTabLookupN(pStrTab, pszString, strlen(pszString));
+}
+
+
+/** Wrapper for kDepDbStrTabAddHashed. */
+static KU32 kDepDbStrTabAdd(KDEPDBINTSTRTAB *pStrTab, const char *pszString)
+{
+ return kDepDbStrTabAddN(pStrTab, pszString, strlen(pszString));
+}
+
+
+/**
+ * Opens the string table files, creating them if necessary.
+ */
+static int kDepDbStrTabInit(KDEPDBINTSTRTAB *pStrTab, const char *pszFilenameBase)
+{
+ size_t cchFilenameBase = strlen(pszFilenameBase);
+ char szPath[4096];
+ int rc;
+ KBOOL fNew;
+
+ /* Basic member init, so kDepDbStrTabTerm always works. */
+ pStrTab->pHash = NULL;
+ kDepDbFHInit(&pStrTab->hHash);
+ pStrTab->pStrTab = NULL;
+ kDepDbFHInit(&pStrTab->hStrTab);
+ pStrTab->iStringAlloced = 0;
+
+ /* check the length. */
+ if (cchFilenameBase + sizeof(".strtab.hash") > sizeof(szPath))
+ return -1;
+
+ /*
+ * Open the string table first.
+ */
+ memcpy(szPath, pszFilenameBase, cchFilenameBase);
+ memcpy(&szPath[cchFilenameBase], ".strtab", sizeof(".strtab"));
+ rc = kDepDbFHOpen(&pStrTab->hStrTab, szPath, K_TRUE, &fNew);
+
+
+ return -1;
+}
+
diff --git a/src/kmk/kmkbuiltin.c b/src/kmk/kmkbuiltin.c
index 4d923d6..1926a85 100644
--- a/src/kmk/kmkbuiltin.c
+++ b/src/kmk/kmkbuiltin.c
@@ -1,10 +1,10 @@
-/* $Id: kmkbuiltin.c 2263 2009-01-23 00:22:47Z bird $ */
+/* $Id: kmkbuiltin.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kMk Builtin command execution.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin.h b/src/kmk/kmkbuiltin.h
index 3db949f..3d1eb44 100644
--- a/src/kmk/kmkbuiltin.h
+++ b/src/kmk/kmkbuiltin.h
@@ -1,10 +1,10 @@
-/* $Id: kmkbuiltin.h 2263 2009-01-23 00:22:47Z bird $ */
+/* $Id: kmkbuiltin.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kMk Builtin command handling.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/append.c b/src/kmk/kmkbuiltin/append.c
index 42418f9..aac2e5b 100644
--- a/src/kmk/kmkbuiltin/append.c
+++ b/src/kmk/kmkbuiltin/append.c
@@ -1,10 +1,10 @@
-/* $Id: append.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: append.c 2466 2011-07-12 09:52:39Z bird $ */
/** @file
* kMk Builtin command - append text to file.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
@@ -177,7 +177,7 @@ int kmk_builtin_append(int argc, char **argv, char **envp)
iFile = i;
pFile = fopen(argv[i], fTruncate ? "w" : "a");
if (!pFile)
- return err(1, "failed to open '%s'.", argv[i]);
+ return err(1, "failed to open '%s'", argv[i]);
/*
* Start define?
diff --git a/src/kmk/kmkbuiltin/chmod.c b/src/kmk/kmkbuiltin/chmod.c
index 3e1eaec..6d360af 100644
--- a/src/kmk/kmkbuiltin/chmod.c
+++ b/src/kmk/kmkbuiltin/chmod.c
@@ -67,7 +67,7 @@ extern void * bsd_setmode(const char *p);
extern mode_t bsd_getmode(const void *bbox, mode_t omode);
extern void bsd_strmode(mode_t mode, char *p);
-#if defined(__APPLE__) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)
+#if (defined(__APPLE__) && !defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) || defined(__OpenBSD__)
extern int lchmod(const char *, mode_t);
#endif
@@ -195,12 +195,12 @@ done: argv += optind;
fts_set(ftsp, p, FTS_SKIP);
continue;
case FTS_DNR: /* Warn, chmod, continue. */
- warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno));
rval = 1;
break;
case FTS_ERR: /* Warn, continue. */
case FTS_NS:
- warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+ warnx("fts: %s: %s", p->fts_path, strerror(p->fts_errno));
rval = 1;
continue;
case FTS_SL: /* Ignore. */
@@ -221,7 +221,7 @@ done: argv += optind;
if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
continue;
if ((*change_mode)(p->fts_accpath, newmode) && !fflag) {
- warn("%s", p->fts_path);
+ warn("%schmod: %s", hflag ? "l" : "", p->fts_path);
rval = 1;
} else {
if (vflag) {
diff --git a/src/kmk/kmkbuiltin/cp.c b/src/kmk/kmkbuiltin/cp.c
index 44b76ab..9622cd1 100644
--- a/src/kmk/kmkbuiltin/cp.c
+++ b/src/kmk/kmkbuiltin/cp.c
@@ -336,7 +336,7 @@ kmk_builtin_cp(int argc, char *argv[], char **envp)
r = stat(to.p_path, &to_stat);
if (r == -1 && errno != ENOENT) {
kBuildProtectionTerm(&g_ProtData);
- return err(1, "%s", to.p_path);
+ return err(1, "stat: %s", to.p_path);
}
if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
/*
@@ -423,14 +423,14 @@ copy(char *argv[], enum op type, int fts_options)
if ( cp_ignore_non_existing
&& curr->fts_errno == ENOENT) {
if (vflag) {
- warnx("%s: %s", curr->fts_path,
+ warnx("fts: %s: %s", curr->fts_path,
strerror(curr->fts_errno));
}
continue;
}
case FTS_DNR:
case FTS_ERR:
- warnx("%s: %s",
+ warnx("fts: %s: %s",
curr->fts_path, strerror(curr->fts_errno));
badcp = rval = 1;
continue;
@@ -593,10 +593,10 @@ copy(char *argv[], enum op type, int fts_options)
if (dne) {
if (mkdir(to.p_path,
curr->fts_statp->st_mode | S_IRWXU) < 0)
- return err(1, "%s", to.p_path);
+ return err(1, "mkdir: %s", to.p_path);
} else if (!S_ISDIR(to_stat.st_mode)) {
errno = ENOTDIR;
- return err(1, "%s", to.p_path);
+ return err(1, "to-mode: %s", to.p_path);
}
/*
* Arrange to correct directory attributes later
diff --git a/src/kmk/kmkbuiltin/cp_utils.c b/src/kmk/kmkbuiltin/cp_utils.c
index 1773815..a966fdd 100644
--- a/src/kmk/kmkbuiltin/cp_utils.c
+++ b/src/kmk/kmkbuiltin/cp_utils.c
@@ -97,7 +97,7 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
*pcopied = 0;
if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) {
- warn("%s", entp->fts_path);
+ warn("open: %s", entp->fts_path);
return (1);
}
@@ -123,7 +123,7 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
if (lseek(from_fd, 0, SEEK_SET) != 0) {
close(from_fd);
if ((from_fd = open(entp->fts_path, O_RDONLY | O_BINARY, 0)) == -1) {
- warn("%s", entp->fts_path);
+ warn("open: %s", entp->fts_path);
return (1);
}
}
@@ -161,7 +161,7 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
fs->st_mode & ~(S_ISUID | S_ISGID));
if (to_fd == -1) {
- warn("%s", to.p_path);
+ warn("open: %s", to.p_path);
(void)close(from_fd);
return (1);
}
@@ -179,7 +179,7 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
fs->st_size <= 8 * 1048576) {
if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
- warn("%s", entp->fts_path);
+ warn("mmap: %s", entp->fts_path);
rval = 1;
} else {
wtotal = 0;
@@ -199,12 +199,12 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
break;
}
if (wcount != (ssize_t)wresid) {
- warn("%s", to.p_path);
+ warn("write[%zd != %zu]: %s", wcount, wresid, to.p_path);
rval = 1;
}
/* Some systems don't unmap on close(2). */
if (munmap(p, fs->st_size) < 0) {
- warn("%s", entp->fts_path);
+ warn("munmap: %s", entp->fts_path);
rval = 1;
}
}
@@ -229,13 +229,13 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
break;
}
if (wcount != (ssize_t)wresid) {
- warn("%s", to.p_path);
+ warn("write[%zd != %zu]: %s", wcount, wresid, to.p_path);
rval = 1;
break;
}
}
if (rcount < 0) {
- warn("%s", entp->fts_path);
+ warn("read: %s", entp->fts_path);
rval = 1;
}
}
@@ -251,7 +251,7 @@ copy_file(const FTSENT *entp, int dne, int changed_only, int *pcopied)
rval = 1;
(void)close(from_fd);
if (close(to_fd)) {
- warn("%s", to.p_path);
+ warn("close: %s", to.p_path);
rval = 1;
}
return (rval);
diff --git a/src/kmk/kmkbuiltin/darwin.c b/src/kmk/kmkbuiltin/darwin.c
index 7c3bfdd..bc35e68 100644
--- a/src/kmk/kmkbuiltin/darwin.c
+++ b/src/kmk/kmkbuiltin/darwin.c
@@ -1,10 +1,10 @@
-/* $Id: darwin.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: darwin.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Missing BSD functions on Darwin / Mac OS X.
*/
/*
- * Copyright (c) 2006-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/err.c b/src/kmk/kmkbuiltin/err.c
index e6d4e7a..230b2fe 100644
--- a/src/kmk/kmkbuiltin/err.c
+++ b/src/kmk/kmkbuiltin/err.c
@@ -1,10 +1,10 @@
-/* $Id: err.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: err.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Override err.h so we get the program name right.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/err.h b/src/kmk/kmkbuiltin/err.h
index eb61c62..726a97b 100644
--- a/src/kmk/kmkbuiltin/err.h
+++ b/src/kmk/kmkbuiltin/err.h
@@ -1,10 +1,10 @@
-/* $Id: err.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: err.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Override err.h stuff so we get the program names right.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/install.c b/src/kmk/kmkbuiltin/install.c
index 9ab4b00..6c4b1cc 100644
--- a/src/kmk/kmkbuiltin/install.c
+++ b/src/kmk/kmkbuiltin/install.c
@@ -122,10 +122,11 @@ extern mode_t bsd_getmode(const void *bbox, mode_t omode);
static gid_t gid;
static uid_t uid;
-static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose;
+static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given;
static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
static const char *suffix = BACKUP_SUFFIX;
static int ignore_perm_errors;
+static int hard_link_files_when_possible;
static struct option long_options[] =
{
@@ -133,6 +134,8 @@ static struct option long_options[] =
{ "version", no_argument, 0, 262 },
{ "ignore-perm-errors", no_argument, 0, 263 },
{ "no-ignore-perm-errors", no_argument, 0, 264 },
+ { "hard-link-files-when-possible", no_argument, 0, 265 },
+ { "no-hard-link-files-when-possible", no_argument, 0, 266 },
{ 0, 0, 0, 0 },
};
@@ -168,8 +171,9 @@ kmk_builtin_install(int argc, char *argv[], char ** envp)
suffix = BACKUP_SUFFIX;
gid = 0;
uid = 0;
- dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = 0;
+ dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0;
ignore_perm_errors = geteuid() != 0;
+ hard_link_files_when_possible = 0;
/* reset getopt and set progname. */
g_progname = argv[0];
@@ -219,6 +223,7 @@ kmk_builtin_install(int argc, char *argv[], char ** envp)
optarg);
mode = bsd_getmode(set, 0);
free(set);
+ mode_given = 1;
break;
case 'o':
owner = optarg;
@@ -246,6 +251,12 @@ kmk_builtin_install(int argc, char *argv[], char ** envp)
case 264:
ignore_perm_errors = 0;
break;
+ case 265:
+ hard_link_files_when_possible = 1;
+ break;
+ case 266:
+ hard_link_files_when_possible = 0;
+ break;
case '?':
default:
return usage(stderr);
@@ -334,7 +345,8 @@ kmk_builtin_install(int argc, char *argv[], char ** envp)
if (to_sb.st_dev == from_sb.st_dev &&
to_sb.st_dev != 0 &&
to_sb.st_ino == from_sb.st_ino &&
- to_sb.st_ino != 0)
+ to_sb.st_ino != 0 &&
+ !hard_link_files_when_possible)
return errx(EX_USAGE,
"%s and %s are the same file", *argv, to_name);
}
@@ -384,9 +396,9 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
#if defined(__EMX__) || defined(_MSC_VER)
|| ( stricmp(from_name, _PATH_DEVNULL)
&& stricmp(from_name, "nul")
-#ifdef __EMX__
+# ifdef __EMX__
&& stricmp(from_name, "/dev/nul")
-#endif
+# endif
)
#else
|| strcmp(from_name, _PATH_DEVNULL)
@@ -422,6 +434,67 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
/* Only copy safe if the target exists. */
tempcopy = safecopy && target;
+ /* Try hard linking if wanted and possible. */
+ if (hard_link_files_when_possible)
+ {
+#ifdef KBUILD_OS_OS2
+ const char *why_not = "not supported on OS/2";
+#else
+ const char *why_not = NULL;
+ if (devnull) {
+ why_not = "/dev/null";
+ } else if (dostrip) {
+ why_not = "strip (-s)";
+ } else if (docompare) {
+ why_not = "compare (-C)";
+ } else if (dobackup) {
+ why_not = "backup (-b/-B)";
+ } else if (safecopy) {
+ why_not = "safe copy (-S)";
+ } else if (lstat(from_name, &temp_sb)) {
+ why_not = "lstat on source failed";
+ } else if (S_ISLNK(temp_sb.st_mode)) {
+ why_not = "symlink";
+ } else if (!S_ISREG(temp_sb.st_mode)) {
+ why_not = "not regular file";
+# if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2)
+ } else if ((mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) {
+# else
+ } else if (mode != (from_sb.st_mode & ALLPERMS)) {
+# endif
+ printf("install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n"
+ "install: src path '%s'\n"
+ "install: dst path '%s'\n",
+ (from_sb.st_mode & ALLPERMS), mode, from_name, to_name);
+ why_not = NULL;
+ } else if (uid != (uid_t)-1 && gid != from_sb.st_uid) {
+ why_not = "uid mismatch";
+ } else if (gid != (gid_t)-1 && gid != from_sb.st_gid) {
+ why_not = "gid mismatch";
+ } else {
+ int rcLink = link(from_name, to_name);
+ if (rcLink != 0 && errno == EEXIST) {
+ unlink(to_name);
+ rcLink = link(from_name, to_name);
+ }
+ if (rcLink == 0) {
+ if (verbose)
+ printf("install: %s -> %s (hardlinked)\n", from_name, to_name);
+ goto l_done;
+ }
+ if (verbose)
+ printf("install: hard linking '%s' to '%s' failed: %s\n",
+ to_name, from_name, strerror(errno));
+ why_not = NULL;
+ }
+#endif
+ if (verbose && why_not)
+ printf("install: not hard linking '%s' to '%s' because: %s\n",
+ to_name, from_name, why_not);
+
+ /* Can't hard link or we failed, continue as nothing happend. */
+ }
+
if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0)
return err(EX_OSERR, "%s", from_name);
@@ -683,7 +756,7 @@ l_done:
(void)close(to_fd);
if (temp_fd >= 0)
(void)close(temp_fd);
- if (!devnull)
+ if (from_fd >= 0 && !devnull)
(void)close(from_fd);
return rc;
}
@@ -972,7 +1045,8 @@ static int
usage(FILE *pf)
{
fprintf(pf,
-"usage: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
+"usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n"
+" [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
" [-g group] [-m mode] [-o owner] file1 file2\n"
" or: %s [-bCcpSsv] [--[no-]ignore-perm-errors] [-B suffix] [-f flags]\n"
" [-g group] [-m mode] [-o owner] file1 ... fileN directory\n"
diff --git a/src/kmk/kmkbuiltin/kDepIDB.c b/src/kmk/kmkbuiltin/kDepIDB.c
index d377ef2..e5fd714 100644
--- a/src/kmk/kmkbuiltin/kDepIDB.c
+++ b/src/kmk/kmkbuiltin/kDepIDB.c
@@ -1,10 +1,10 @@
-/* $Id: kDepIDB.c 2263 2009-01-23 00:22:47Z bird $ */
+/* $Id: kDepIDB.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kDepIDB - Extract dependency information from a MS Visual C++ .idb file.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/kDepObj.c b/src/kmk/kmkbuiltin/kDepObj.c
index 270044d..6f6bfc6 100644
--- a/src/kmk/kmkbuiltin/kDepObj.c
+++ b/src/kmk/kmkbuiltin/kDepObj.c
@@ -1,10 +1,10 @@
-/* $Id: kDepObj.c 2278 2009-02-24 02:19:35Z bird $ */
+/* $Id: kDepObj.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kDepObj - Extract dependency information from an object file.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/kbuild_protection.c b/src/kmk/kmkbuiltin/kbuild_protection.c
index ba5e877..6a98f80 100644
--- a/src/kmk/kmkbuiltin/kbuild_protection.c
+++ b/src/kmk/kmkbuiltin/kbuild_protection.c
@@ -1,10 +1,10 @@
-/* $Id: kbuild_protection.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: kbuild_protection.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Simple File Protection.
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/kbuild_protection.h b/src/kmk/kmkbuiltin/kbuild_protection.h
index 78ecf23..5f8c8ec 100644
--- a/src/kmk/kmkbuiltin/kbuild_protection.h
+++ b/src/kmk/kmkbuiltin/kbuild_protection.h
@@ -1,10 +1,10 @@
-/* $Id: kbuild_protection.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: kbuild_protection.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Simple File Protection.
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/kbuild_version.c b/src/kmk/kmkbuiltin/kbuild_version.c
index 98b19e1..ec0613b 100644
--- a/src/kmk/kmkbuiltin/kbuild_version.c
+++ b/src/kmk/kmkbuiltin/kbuild_version.c
@@ -1,10 +1,10 @@
-/* $Id: kbuild_version.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: kbuild_version.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kbuild_version(), helper function.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/ln.c b/src/kmk/kmkbuiltin/ln.c
index 73fe5db..2756ec8 100644
--- a/src/kmk/kmkbuiltin/ln.c
+++ b/src/kmk/kmkbuiltin/ln.c
@@ -154,10 +154,10 @@ kmk_builtin_ln(int argc, char *argv[], char **envp)
* the target--simulate "not a directory" error
*/
errno = ENOTDIR;
- return err(1, "%s", sourcedir);
+ return err(1, "st_mode: %s", sourcedir);
}
if (stat(sourcedir, &sb))
- return err(1, "%s", sourcedir);
+ return err(1, "stat: %s", sourcedir);
if (!S_ISDIR(sb.st_mode))
return usage(stderr);
for (exitval = 0; *argv != sourcedir; ++argv)
@@ -176,13 +176,13 @@ linkit(const char *target, const char *source, int isdir)
if (!sflag) {
/* If target doesn't exist, quit now. */
if (stat(target, &sb)) {
- warn("%s", target);
+ warn("stat: %s", target);
return (1);
}
/* Only symbolic links to directories. */
if (S_ISDIR(sb.st_mode)) {
errno = EISDIR;
- warn("%s", target);
+ warn("st_mode: %s", target);
return (1);
}
}
@@ -209,7 +209,7 @@ linkit(const char *target, const char *source, int isdir)
if (snprintf(path, sizeof(path), "%s/%s", source, p) >=
(ssize_t)sizeof(path)) {
errno = ENAMETOOLONG;
- warn("%s", target);
+ warn("snprintf: %s", target);
return (1);
}
source = path;
@@ -222,7 +222,7 @@ linkit(const char *target, const char *source, int isdir)
*/
if (fflag && exists) {
if (unlink(source)) {
- warn("%s", source);
+ warn("unlink: %s", source);
return (1);
}
} else if (iflag && exists) {
@@ -238,14 +238,14 @@ linkit(const char *target, const char *source, int isdir)
}
if (unlink(source)) {
- warn("%s", source);
+ warn("unlink: %s", source);
return (1);
}
}
/* Attempt the link. */
if ((*linkf)(target, source)) {
- warn("%s", source);
+ warn("%s: %s", linkf == link ? "link" : "symlink", source);
return (1);
}
if (vflag)
diff --git a/src/kmk/kmkbuiltin/md5sum.c b/src/kmk/kmkbuiltin/md5sum.c
index 0e673b9..c56dc07 100644
--- a/src/kmk/kmkbuiltin/md5sum.c
+++ b/src/kmk/kmkbuiltin/md5sum.c
@@ -1,10 +1,10 @@
-/* $Id: md5sum.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: md5sum.c 2414 2010-09-12 18:42:06Z bird $ */
/** @file
* md5sum.
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
@@ -169,8 +169,8 @@ static void *open_file(const char *pszFilename, unsigned fText)
#elif defined(_O_SEQUENTIAL)
fFlags |= _O_SEQUENTIAL;
#endif
-#ifdef _O_BINARY
- if (!fText) fFlags |= _O_BINARY;
+#ifdef O_BINARY
+ if (!fText) fFlags |= O_BINARY;
#elif defined(_O_BINARY)
if (!fText) fFlags |= _O_BINARY;
#endif
diff --git a/src/kmk/kmkbuiltin/mkdir.c b/src/kmk/kmkbuiltin/mkdir.c
index e066460..3b75e64 100644
--- a/src/kmk/kmkbuiltin/mkdir.c
+++ b/src/kmk/kmkbuiltin/mkdir.c
@@ -143,9 +143,9 @@ kmk_builtin_mkdir(int argc, char *argv[], char **envp)
success = 0;
} else if (mkdir(*argv, omode) < 0) {
if (errno == ENOTDIR || errno == ENOENT)
- warn("%s", dirname(*argv));
+ warn("mkdir: %s", dirname(*argv));
else
- warn("%s", *argv);
+ warn("mkdir: %s", *argv);
success = 0;
} else if (vflag)
(void)printf("%s\n", *argv);
@@ -160,7 +160,7 @@ kmk_builtin_mkdir(int argc, char *argv[], char **envp)
* as chmod will (obviously) ignore the umask.
*/
if (success && mode != NULL && chmod(*argv, omode) == -1) {
- warn("%s", *argv);
+ warn("chmod: %s", *argv);
exitval = 1;
}
}
@@ -241,9 +241,11 @@ build(char *path, mode_t omode)
if (last)
(void)umask(oumask);
if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
- if (errno == EEXIST || errno == EISDIR || errno == ENOSYS /* (solaris crap) */) {
+ if (errno == EEXIST || errno == EISDIR
+ || errno == ENOSYS /* (solaris crap) */
+ || errno == EACCES /* (ditto) */) {
if (stat(path, &sb) < 0) {
- warn("%s", path);
+ warn("stat: %s", path);
retval = 1;
break;
} else if (!S_ISDIR(sb.st_mode)) {
@@ -251,12 +253,12 @@ build(char *path, mode_t omode)
errno = EEXIST;
else
errno = ENOTDIR;
- warn("%s", path);
+ warn("st_mode: %s", path);
retval = 1;
break;
}
} else {
- warn("%s", path);
+ warn("mkdir: %s", path);
retval = 1;
break;
}
diff --git a/src/kmk/kmkbuiltin/mscfakes.c b/src/kmk/kmkbuiltin/mscfakes.c
index c3be36f..7d040ff 100644
--- a/src/kmk/kmkbuiltin/mscfakes.c
+++ b/src/kmk/kmkbuiltin/mscfakes.c
@@ -1,10 +1,10 @@
-/* $Id: mscfakes.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: mscfakes.c 2484 2011-07-21 19:01:08Z bird $ */
/** @file
* Fake Unix stuff for MSC.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
@@ -157,6 +157,9 @@ msc_set_errno(DWORD dwErr)
case ERROR_ALREADY_EXISTS: errno = EEXIST; break;
case ERROR_FILENAME_EXCED_RANGE: errno = ENOENT; break;
case ERROR_NESTING_NOT_ALLOWED: errno = EAGAIN; break;
+#ifdef EMLINK
+ case ERROR_TOO_MANY_LINKS: errno = EMLINK; break;
+#endif
}
return -1;
@@ -212,7 +215,6 @@ int lchmod(const char *pszPath, mode_t mode)
int msc_chmod(const char *pszPath, mode_t mode)
{
int rc = 0;
- int saved_errno;
int fMustBeDir;
char *pszPathFree = msc_fix_path(&pszPath, &fMustBeDir);
@@ -255,11 +257,32 @@ int msc_chmod(const char *pszPath, mode_t mode)
}
+typedef BOOL (WINAPI *PFNCREATEHARDLINKA)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
int link(const char *pszDst, const char *pszLink)
{
- errno = ENOSYS;
- err(1, "link() is not implemented on windows!");
- return -1;
+ static PFNCREATEHARDLINKA s_pfnCreateHardLinkA = NULL;
+ static int s_fTried = FALSE;
+
+ /* The API was introduced in Windows 2000, so resolve it dynamically. */
+ if (!s_pfnCreateHardLinkA)
+ {
+ if (!s_fTried)
+ {
+ HMODULE hmod = LoadLibrary("KERNEL32.DLL");
+ if (hmod)
+ *(FARPROC *)&s_pfnCreateHardLinkA = GetProcAddress(hmod, "CreateHardLinkA");
+ s_fTried = TRUE;
+ }
+ if (!s_pfnCreateHardLinkA)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+ }
+
+ if (s_pfnCreateHardLinkA(pszLink, pszDst, NULL))
+ return 0;
+ return msc_set_errno(GetLastError());
}
diff --git a/src/kmk/kmkbuiltin/mscfakes.h b/src/kmk/kmkbuiltin/mscfakes.h
index 320543b..705a3dc 100644
--- a/src/kmk/kmkbuiltin/mscfakes.h
+++ b/src/kmk/kmkbuiltin/mscfakes.h
@@ -1,10 +1,10 @@
-/* $Id: mscfakes.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: mscfakes.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Unix fakes for MSC.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/mv.c b/src/kmk/kmkbuiltin/mv.c
index 2233c56..8ebf1ce 100644
--- a/src/kmk/kmkbuiltin/mv.c
+++ b/src/kmk/kmkbuiltin/mv.c
@@ -99,7 +99,7 @@ static int usage(FILE *);
extern void bsd_strmode(mode_t mode, char *p);
-#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__)
+#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
# ifdef __OS2__
static
# endif
diff --git a/src/kmk/kmkbuiltin/openbsd.c b/src/kmk/kmkbuiltin/openbsd.c
new file mode 100644
index 0000000..b6b59db
--- /dev/null
+++ b/src/kmk/kmkbuiltin/openbsd.c
@@ -0,0 +1,54 @@
+/* $Id: openbsd.c 2421 2010-10-17 21:27:53Z bird $ */
+/** @file
+ * Missing BSD functions in OpenBSD.
+ */
+
+/*
+ * Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
+ *
+ * This file is part of kBuild.
+ *
+ * kBuild is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * kBuild is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with kBuild. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "config.h"
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+int lchmod(const char *path, mode_t mode)
+{
+ struct stat st;
+ if (lstat(path, &st))
+ return -1;
+ if (S_ISLNK(st.st_mode))
+ return 0; /* pretend success */
+ return chmod(path, mode);
+}
+
+
+int lutimes(const char *path, const struct timeval *tvs)
+{
+ struct stat st;
+ if (lstat(path, &st))
+ return -1;
+ if (S_ISLNK(st.st_mode))
+ return 0; /* pretend success */
+ return utimes(path, tvs);
+}
+
diff --git a/src/kmk/kmkbuiltin/osdep.c b/src/kmk/kmkbuiltin/osdep.c
index 8e16094..d8201df 100644
--- a/src/kmk/kmkbuiltin/osdep.c
+++ b/src/kmk/kmkbuiltin/osdep.c
@@ -1,10 +1,10 @@
-/* $Id: osdep.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: osdep.c 2421 2010-10-17 21:27:53Z bird $ */
/** @file
* Include all the OS dependent bits when bootstrapping.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
@@ -38,5 +38,8 @@
#elif defined(__APPLE__)
# include "darwin.c"
+#elif defined(__OpenBSD__)
+# include "openbsd.c"
+
#endif
diff --git a/src/kmk/kmkbuiltin/redirect.c b/src/kmk/kmkbuiltin/redirect.c
index 109a393..c3f3cda 100644
--- a/src/kmk/kmkbuiltin/redirect.c
+++ b/src/kmk/kmkbuiltin/redirect.c
@@ -1,10 +1,10 @@
-/* $Id: redirect.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: redirect.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kmk_redirect - Do simple program <-> file redirection (++).
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/rm.c b/src/kmk/kmkbuiltin/rm.c
index 1b6522c..4134a6d 100644
--- a/src/kmk/kmkbuiltin/rm.c
+++ b/src/kmk/kmkbuiltin/rm.c
@@ -38,7 +38,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
#endif /* not lint */
#include <sys/cdefs.h>
-//__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");
+/*__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");*/
#endif
#include "config.h"
@@ -119,6 +119,13 @@ static int rm_overwrite(char *, struct stat *);
static int rm_tree(char **);
static int usage(FILE *);
+#if 1
+#define CUR_LINE_H2(x) "[line " #x "]"
+#define CUR_LINE_H1(x) CUR_LINE_H2(x)
+#define CUR_LINE() CUR_LINE_H1(__LINE__)
+#else
+# define CUR_LINE()
+#endif
/*
@@ -279,17 +286,18 @@ rm_tree(char **argv)
return err(1, "fts_open");
}
while ((p = fts_read(fts)) != NULL) {
+ const char *operation = "chflags";
switch (p->fts_info) {
case FTS_DNR:
if (!fflag || p->fts_errno != ENOENT) {
- fprintf(stderr, "%s: %s: %s\n",
+ fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n",
argv0, p->fts_path, strerror(p->fts_errno));
eval = 1;
}
continue;
case FTS_ERR:
fts_close(fts);
- return errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
+ return errx(1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno));
case FTS_NS:
/*
* Assume that since fts_read() couldn't stat the
@@ -298,7 +306,7 @@ rm_tree(char **argv)
if (!needstat)
break;
if (!fflag || p->fts_errno != ENOENT) {
- fprintf(stderr, "%s: %s: %s\n",
+ fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n",
argv0, p->fts_path, strerror(p->fts_errno));
eval = 1;
}
@@ -362,6 +370,7 @@ rm_tree(char **argv)
p->fts_path);
continue;
}
+ operation = "mkdir";
break;
#ifdef FTS_W
@@ -373,6 +382,7 @@ rm_tree(char **argv)
p->fts_path);
continue;
}
+ operation = "undelete";
break;
#endif
@@ -402,16 +412,18 @@ rm_tree(char **argv)
p->fts_path);
continue;
}
+ operation = "unlink";
+ break;
}
}
#ifdef UF_APPEND
err:
#endif
- fprintf(stderr, "%s: %s: %s\n", argv0, p->fts_path, strerror(errno));
+ fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno));
eval = 1;
}
if (errno) {
- fprintf(stderr, "%s: fts_read: %s\n", argv0, strerror(errno));
+ fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno));
eval = 1;
}
fts_close(fts);
@@ -439,6 +451,7 @@ rm_file(char **argv)
* to remove a directory is an error, so must always stat the file.
*/
while ((f = *argv++) != NULL) {
+ const char *operation = "?";
/* Assume if can't stat the file, can't unlink it. */
if (lstat(f, &sb)) {
#ifdef FTS_WHITEOUT
@@ -449,7 +462,7 @@ rm_file(char **argv)
{
#endif
if (!fflag || errno != ENOENT) {
- fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(errno));
+ fprintf(stderr, "lstat: %s: %s: %s " CUR_LINE() "\n", argv0, f, strerror(errno));
eval = 1;
}
continue;
@@ -477,11 +490,13 @@ rm_file(char **argv)
rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
#endif
if (rval == 0) {
- if (S_ISWHT(sb.st_mode))
+ if (S_ISWHT(sb.st_mode)) {
rval = undelete(f);
- else if (S_ISDIR(sb.st_mode))
+ operation = "undelete";
+ } else if (S_ISDIR(sb.st_mode)) {
rval = rmdir(f);
- else {
+ operation = "rmdir";
+ } else {
if (Pflag)
if (!rm_overwrite(f, &sb))
continue;
@@ -492,10 +507,11 @@ rm_file(char **argv)
rval = unlink(f);
}
#endif
+ operation = "unlink";
}
}
if (rval && (!fflag || errno != ENOENT)) {
- fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(errno));
+ fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno));
eval = 1;
}
if (vflag && rval == 0)
@@ -525,6 +541,7 @@ rm_overwrite(char *file, struct stat *sbp)
off_t len;
int bsize, fd, wlen;
char *buf = NULL;
+ const char *operation = "lstat";
fd = -1;
if (sbp == NULL) {
@@ -534,6 +551,7 @@ rm_overwrite(char *file, struct stat *sbp)
}
if (!S_ISREG(sbp->st_mode))
return (1);
+ operation = "open";
if ((fd = open(file, O_WRONLY, 0)) == -1)
goto err;
#ifdef HAVE_FSTATFS
@@ -549,6 +567,7 @@ rm_overwrite(char *file, struct stat *sbp)
exit(err(1, "%s: malloc", file));
#define PASS(byte) { \
+ operation = "write"; \
memset(buf, byte, bsize); \
for (len = sbp->st_size; len > 0; len -= wlen) { \
wlen = len < bsize ? len : bsize; \
@@ -557,9 +576,11 @@ rm_overwrite(char *file, struct stat *sbp)
} \
}
PASS(0xff);
+ operation = "fsync/lseek";
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
goto err;
PASS(0x00);
+ operation = "fsync/lseek";
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
goto err;
PASS(0xff);
@@ -567,13 +588,14 @@ rm_overwrite(char *file, struct stat *sbp)
free(buf);
return (1);
}
+ operation = "fsync/close";
err: eval = 1;
if (buf)
free(buf);
if (fd != -1)
close(fd);
- fprintf(stderr, "%s: %s: %s\n", argv0, file, strerror(errno));
+ fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, file, strerror(errno));
return (0);
}
diff --git a/src/kmk/kmkbuiltin/rmdir.c b/src/kmk/kmkbuiltin/rmdir.c
index 0e6da6a..34771dd 100644
--- a/src/kmk/kmkbuiltin/rmdir.c
+++ b/src/kmk/kmkbuiltin/rmdir.c
@@ -127,7 +127,7 @@ kmk_builtin_rmdir(int argc, char *argv[], char **envp)
if (rmdir(*argv) < 0) {
if ( (!ignore_fail_on_non_empty || (errno != ENOTEMPTY && errno != EPERM && errno != EACCES && errno != EINVAL && errno != EEXIST))
&& (!ignore_fail_on_not_exist || errno != ENOENT)) {
- warn("%s", *argv);
+ warn("rmdir: %s", *argv);
errors = 1;
continue;
}
@@ -180,7 +180,7 @@ rm_path(char *path)
if (ignore_fail_on_non_empty && (errno == ENOTEMPTY || errno == EPERM || errno == EACCES || errno == EINVAL || errno == EEXIST))
break;
if (!ignore_fail_on_not_exist || errno != ENOENT) {
- warn("%s", path);
+ warn("rmdir: %s", path);
return (1);
}
}
diff --git a/src/kmk/kmkbuiltin/sleep.c b/src/kmk/kmkbuiltin/sleep.c
index f3a778d..a5365dc 100644
--- a/src/kmk/kmkbuiltin/sleep.c
+++ b/src/kmk/kmkbuiltin/sleep.c
@@ -1,10 +1,10 @@
-/* $Id: sleep.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: sleep.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* kmk_sleep - suspend execution for an interval of time.
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/solfakes.c b/src/kmk/kmkbuiltin/solfakes.c
index 25d7734..2f4b818 100644
--- a/src/kmk/kmkbuiltin/solfakes.c
+++ b/src/kmk/kmkbuiltin/solfakes.c
@@ -1,10 +1,10 @@
-/* $Id: solfakes.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: solfakes.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Fake Unix stuff for Solaris.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/kmkbuiltin/solfakes.h b/src/kmk/kmkbuiltin/solfakes.h
index 2792efb..010d809 100644
--- a/src/kmk/kmkbuiltin/solfakes.h
+++ b/src/kmk/kmkbuiltin/solfakes.h
@@ -1,10 +1,10 @@
-/* $Id: solfakes.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: solfakes.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* Unix fakes for Solaris.
*/
/*
- * Copyright (c) 2005-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/maintMakefile b/src/kmk/maintMakefile
index 276457f..5b27cab 100644
--- a/src/kmk/maintMakefile
+++ b/src/kmk/maintMakefile
@@ -3,7 +3,11 @@
# tree, not a dist copy.
# We like mondo-warnings!
+ifeq ($(KBUILD_TARGET),openbsd) # bird
+AM_CFLAGS += -Wall -Wshadow -Wpointer-arith -Wbad-function-cast
+else
AM_CFLAGS += -Wall -Wextra -Wdeclaration-after-statement -Wshadow -Wpointer-arith -Wbad-function-cast
+endif
# I want this one but I have to wait for the const cleanup!
# -Wwrite-strings
diff --git a/src/kmk/read.c b/src/kmk/read.c
index 8bbf4ff..dddf54b 100644
--- a/src/kmk/read.c
+++ b/src/kmk/read.c
@@ -480,7 +480,12 @@ eval_makefile (const char *filename, int flags)
{
int stream_buf_size = 256*1024;
if (st.st_size < stream_buf_size)
- stream_buf_size = (st.st_size + 0xfff) & ~0xfff;
+ {
+ if (st.st_size)
+ stream_buf_size = (st.st_size + 0xfff) & ~0xfff;
+ else
+ stream_buf_size = 0x1000;
+ }
stream_buf = xmalloc (stream_buf_size);
setvbuf (ebuf.fp, stream_buf, _IOFBF, stream_buf_size);
}
@@ -2082,7 +2087,7 @@ conditional_line (char *line, char *eol, int len, const struct floc *flocp)
unsigned int l;
char termin = *line == '(' ? ',' : *line;
#ifdef CONFIG_WITH_VALUE_LENGTH
- char *buf_pos;
+ char *s1_end, *s2_end;
#endif
if (termin != ',' && termin != '"' && termin != '\'')
@@ -2135,8 +2140,7 @@ conditional_line (char *line, char *eol, int len, const struct floc *flocp)
s1 = alloca (l + 1);
memcpy (s1, s2, l + 1);
#else
- s1 = variable_expand_string_2 (NULL, s1, l, &buf_pos);
- ++buf_pos;
+ s1 = variable_expand_string_2 (NULL, s1, l, &s1_end);
#endif
if (termin != ',')
@@ -2187,10 +2191,9 @@ conditional_line (char *line, char *eol, int len, const struct floc *flocp)
#ifndef CONFIG_WITH_VALUE_LENGTH
s2 = variable_expand (s2);
#else
- if ((size_t)buf_pos & 7)
- buf_pos = variable_buffer_output (buf_pos, "\0\0\0\0\0\0\0\0",
- 8 - ((size_t)buf_pos & 7));
- s2 = variable_expand_string_2 (buf_pos, s2, l, &buf_pos);
+ s2 = variable_expand_string_2 (s1_end + 1, s2, l, &s2_end);
+ if (s2 != s1_end + 1)
+ s1 += s2 - s1_end - 1; /* the variable buffer was reallocated */
#endif
#ifdef CONFIG_WITH_SET_CONDITIONALS
if (cmdtype == c_if1of || cmdtype == c_ifn1of)
diff --git a/src/kmk/strcache2.c b/src/kmk/strcache2.c
index 807d587..861d27a 100644
--- a/src/kmk/strcache2.c
+++ b/src/kmk/strcache2.c
@@ -1,10 +1,10 @@
-/* $Id: strcache2.c 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: strcache2.c 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* strcache2 - New string cache.
*/
/*
- * Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/strcache2.h b/src/kmk/strcache2.h
index 3619b6b..8ef8650 100644
--- a/src/kmk/strcache2.h
+++ b/src/kmk/strcache2.h
@@ -1,10 +1,10 @@
-/* $Id: strcache2.h 2243 2009-01-10 02:24:02Z bird $ */
+/* $Id: strcache2.h 2413 2010-09-11 17:43:04Z bird $ */
/** @file
* strcache - New string cache.
*/
/*
- * Copyright (c) 2006-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*
diff --git a/src/kmk/testcase-2ndtargetexp.kmk b/src/kmk/testcase-2ndtargetexp.kmk
index d5730fe..1e19a8b 100644
--- a/src/kmk/testcase-2ndtargetexp.kmk
+++ b/src/kmk/testcase-2ndtargetexp.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-2ndtargetexp.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-2ndtargetexp.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the 2nd target expansion feature.
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-if1of.kmk b/src/kmk/testcase-if1of.kmk
index f8c9553..dc878ba 100644
--- a/src/kmk/testcase-if1of.kmk
+++ b/src/kmk/testcase-if1of.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-if1of.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-if1of.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the if1of and ifn1of conditionals.
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-includedep-sub.kmk b/src/kmk/testcase-includedep-sub.kmk
index d95e142..b5bf546 100644
--- a/src/kmk/testcase-includedep-sub.kmk
+++ b/src/kmk/testcase-includedep-sub.kmk
@@ -1,11 +1,11 @@
-# $Id: testcase-includedep-sub.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-includedep-sub.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the includdep directive, helper file
# that gets included all the time.
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-includedep.kmk b/src/kmk/testcase-includedep.kmk
index 0f8912a..685f527 100644
--- a/src/kmk/testcase-includedep.kmk
+++ b/src/kmk/testcase-includedep.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-includedep.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-includedep.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the includedep directive.
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-lazy-deps-vars.kmk b/src/kmk/testcase-lazy-deps-vars.kmk
index 01f0e34..75b6b9b 100644
--- a/src/kmk/testcase-lazy-deps-vars.kmk
+++ b/src/kmk/testcase-lazy-deps-vars.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-lazy-deps-vars.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-lazy-deps-vars.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the lazy dependency lists.
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-math.kmk b/src/kmk/testcase-math.kmk
index 0572eae..bd4fb7e 100644
--- a/src/kmk/testcase-math.kmk
+++ b/src/kmk/testcase-math.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-math.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-math.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the math functions.
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-root.kmk b/src/kmk/testcase-root.kmk
new file mode 100644
index 0000000..92de5c5
--- /dev/null
+++ b/src/kmk/testcase-root.kmk
@@ -0,0 +1,30 @@
+#
+# The $(root ...) and $(notroot ) functions.
+#
+
+
+
+x := $(root /a)
+y := $(notroot /a)
+ifneq ($x,/)
+ $(error x=$x)
+endif
+ifneq ($y,a)
+ $(error y=$y)
+endif
+
+x := $(root /a /b /)
+y := $(notroot /a /b /)
+ifneq ($x,/ / /)
+ $(error x=$x)
+endif
+ifneq ($y,a b .)
+ $(error y=$y)
+endif
+
+
+# dummy
+all:
+ echo The root and notroot functions works.
+
+
diff --git a/src/kmk/testcase-stack.kmk b/src/kmk/testcase-stack.kmk
index 66f6aad..e610319 100644
--- a/src/kmk/testcase-stack.kmk
+++ b/src/kmk/testcase-stack.kmk
@@ -1,10 +1,10 @@
-# $Id: testcase-stack.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-stack.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the functions.
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/testcase-xargs.kmk b/src/kmk/testcase-xargs.kmk
index 984a9c2..ee6b5a8 100644
--- a/src/kmk/testcase-xargs.kmk
+++ b/src/kmk/testcase-xargs.kmk
@@ -1,11 +1,11 @@
-# $Id: testcase-xargs.kmk 2243 2009-01-10 02:24:02Z bird $
+# $Id: testcase-xargs.kmk 2413 2010-09-11 17:43:04Z bird $
## @file
# kBuild - testcase for the xargs function.
# Requires manual inspection of the output.
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/features/ifcond b/src/kmk/tests/scripts/features/ifcond
index 5c20aed..b492e77 100644
--- a/src/kmk/tests/scripts/features/ifcond
+++ b/src/kmk/tests/scripts/features/ifcond
@@ -1,10 +1,10 @@
-# $Id: ifcond 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: ifcond 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# if conditionals.
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/evalcall b/src/kmk/tests/scripts/functions/evalcall
index c955f4d..f0213c2 100644
--- a/src/kmk/tests/scripts/functions/evalcall
+++ b/src/kmk/tests/scripts/functions/evalcall
@@ -1,10 +1,10 @@
-# $Id: evalcall 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: evalcall 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(evalcall var,argN...)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/expr b/src/kmk/tests/scripts/functions/expr
index 36fc481..a68205f 100644
--- a/src/kmk/tests/scripts/functions/expr
+++ b/src/kmk/tests/scripts/functions/expr
@@ -1,10 +1,10 @@
-# $Id: expr 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: expr 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(expr expr)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/for b/src/kmk/tests/scripts/functions/for
index 8b4affe..0152395 100644
--- a/src/kmk/tests/scripts/functions/for
+++ b/src/kmk/tests/scripts/functions/for
@@ -1,10 +1,10 @@
-# $Id: for 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: for 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(for init,condition,next,body)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/if-expr b/src/kmk/tests/scripts/functions/if-expr
index 91ba633..764522d 100644
--- a/src/kmk/tests/scripts/functions/if-expr
+++ b/src/kmk/tests/scripts/functions/if-expr
@@ -1,10 +1,10 @@
-# $Id: if-expr 2277 2009-02-24 02:18:24Z bird $ -*-perl-*-
+# $Id: if-expr 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(if-expr expr, if-expand, else-expand)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/insert b/src/kmk/tests/scripts/functions/insert
index 152edff..6a597c6 100644
--- a/src/kmk/tests/scripts/functions/insert
+++ b/src/kmk/tests/scripts/functions/insert
@@ -1,10 +1,10 @@
-# $Id: insert 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: insert 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(insert in, str[, n[, length[, pad]]])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/intersects b/src/kmk/tests/scripts/functions/intersects
index 469401a..8d136fb 100644
--- a/src/kmk/tests/scripts/functions/intersects
+++ b/src/kmk/tests/scripts/functions/intersects
@@ -1,10 +1,10 @@
-# $Id: intersects 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: intersects 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(intersects set-a,set-b)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/lastpos b/src/kmk/tests/scripts/functions/lastpos
index 277b0de..248db2b 100644
--- a/src/kmk/tests/scripts/functions/lastpos
+++ b/src/kmk/tests/scripts/functions/lastpos
@@ -1,10 +1,10 @@
-# $Id: lastpos 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: lastpos 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(lastpos needle, haystack[, start])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/length b/src/kmk/tests/scripts/functions/length
index 0d68099..c8ea34d 100644
--- a/src/kmk/tests/scripts/functions/length
+++ b/src/kmk/tests/scripts/functions/length
@@ -1,10 +1,10 @@
-# $Id: length 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: length 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(length text)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/length-var b/src/kmk/tests/scripts/functions/length-var
index 2baaac9..0583713 100644
--- a/src/kmk/tests/scripts/functions/length-var
+++ b/src/kmk/tests/scripts/functions/length-var
@@ -1,10 +1,10 @@
-# $Id: length-var 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: length-var 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(length-var var)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/pos b/src/kmk/tests/scripts/functions/pos
index 74d3fab..bdc3d40 100644
--- a/src/kmk/tests/scripts/functions/pos
+++ b/src/kmk/tests/scripts/functions/pos
@@ -1,10 +1,10 @@
-# $Id: pos 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: pos 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(pos needle, haystack[, start])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/printf b/src/kmk/tests/scripts/functions/printf
index 75094d8..cb20168 100644
--- a/src/kmk/tests/scripts/functions/printf
+++ b/src/kmk/tests/scripts/functions/printf
@@ -1,10 +1,10 @@
-# $Id: printf 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: printf 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(printf fmt[,args...])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/root b/src/kmk/tests/scripts/functions/root
index 8922168..46abbd1 100644
--- a/src/kmk/tests/scripts/functions/root
+++ b/src/kmk/tests/scripts/functions/root
@@ -1,10 +1,10 @@
-# $Id: root 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: root 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(root path...)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/select b/src/kmk/tests/scripts/functions/select
index 340e164..843ff2e 100644
--- a/src/kmk/tests/scripts/functions/select
+++ b/src/kmk/tests/scripts/functions/select
@@ -1,10 +1,10 @@
-# $Id: select 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: select 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(select when1-cond, when1-body[,whenN-cond, whenN-body])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/substr b/src/kmk/tests/scripts/functions/substr
index 821f906..bf0eba9 100644
--- a/src/kmk/tests/scripts/functions/substr
+++ b/src/kmk/tests/scripts/functions/substr
@@ -1,10 +1,10 @@
-# $Id: substr 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: substr 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(substr str, start[, length[, pad]])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/translate b/src/kmk/tests/scripts/functions/translate
index 1937478..2dcf83f 100644
--- a/src/kmk/tests/scripts/functions/translate
+++ b/src/kmk/tests/scripts/functions/translate
@@ -1,10 +1,10 @@
-# $Id: translate 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: translate 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(translate string, from-set[, to-set[, pad-char]])
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/functions/while b/src/kmk/tests/scripts/functions/while
index 2f43a1a..c0e6481 100644
--- a/src/kmk/tests/scripts/functions/while
+++ b/src/kmk/tests/scripts/functions/while
@@ -1,10 +1,10 @@
-# $Id: while 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: while 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# $(while condition,body)
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/tests/scripts/variables/must_make b/src/kmk/tests/scripts/variables/must_make
index f5d2dca..83a8275 100644
--- a/src/kmk/tests/scripts/variables/must_make
+++ b/src/kmk/tests/scripts/variables/must_make
@@ -1,10 +1,10 @@
-# $Id: must_make 2243 2009-01-10 02:24:02Z bird $ -*-perl-*-
+# $Id: must_make 2413 2010-09-11 17:43:04Z bird $ -*-perl-*-
## @file
# .MUST_MAKE target variable.
#
#
-# Copyright (c) 2008-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2008-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/variable.c b/src/kmk/variable.c
index ffa0a25..02dca60 100644
--- a/src/kmk/variable.c
+++ b/src/kmk/variable.c
@@ -32,6 +32,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include "hash.h"
#ifdef KMK
# include "kbuild.h"
+# ifdef WINDOWS32
+# include <Windows.h>
+# else
+# include <sys/utsname.h>
+# endif
#endif
#ifdef CONFIG_WITH_STRCACHE2
# include <stddef.h>
@@ -1072,6 +1077,30 @@ merge_variable_set_lists (struct variable_set_list **setlist0,
}
}
+#if defined(KMK) && !defined(WINDOWS32)
+/* Parses out the next number from the uname release level string. Fast
+ forwards to the end of the string when encountering some non-conforming
+ chars. */
+
+static unsigned long parse_release_number (const char **ppsz)
+{
+ unsigned long ul;
+ char *psz = (char *)*ppsz;
+ if (ISDIGIT (*psz))
+ {
+ ul = strtoul (psz, &psz, 10);
+ if (psz != NULL && *psz == '.')
+ psz++;
+ else
+ psz = strchr (*ppsz, '\0');
+ *ppsz = psz;
+ }
+ else
+ ul = 0;
+ return ul;
+}
+#endif
+
/* Define the automatic variables, and record the addresses
of their structures so we can change their values quickly. */
@@ -1091,6 +1120,12 @@ define_automatic_variables (void)
const char *val;
struct variable *envvar1;
struct variable *envvar2;
+# ifdef WINDOWS32
+ OSVERSIONINFOEX oix;
+# else
+ struct utsname uts;
+# endif
+ unsigned long ulMajor = 0, ulMinor = 0, ulPatch = 0, ul4th = 0;
#endif
sprintf (buf, "%u", makelevel);
@@ -1165,6 +1200,58 @@ define_automatic_variables (void)
define_variable ("BUILD_PLATFORM_CPU", sizeof ("BUILD_PLATFORM_CPU") - 1,
val, o_default, 0);
+ /* The host kernel version. */
+#if defined(WINDOWS32)
+ memset (&oix, '\0', sizeof (oix));
+ oix.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if (!GetVersionEx ((LPOSVERSIONINFO)&oix))
+ {
+ memset (&oix, '\0', sizeof (oix));
+ oix.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx ((LPOSVERSIONINFO)&oix);
+ }
+ if (oix.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ ulMajor = oix.dwMajorVersion;
+ ulMinor = oix.dwMinorVersion;
+ ulPatch = oix.wServicePackMajor;
+ ul4th = oix.wServicePackMinor;
+ }
+ else
+ {
+ ulMajor = oix.dwPlatformId == 1 ? 0 /*Win95/98/ME*/
+ : oix.dwPlatformId == 3 ? 1 /*WinCE*/
+ : 2; /*??*/
+ ulMinor = oix.dwMajorVersion;
+ ulPatch = oix.dwMinorVersion;
+ ul4th = oix.wServicePackMajor;
+ }
+#else
+ memset (&uts, 0, sizeof(uts));
+ uname (&uts);
+ val = uts.release;
+ ulMajor = parse_release_number (&val);
+ ulMinor = parse_release_number (&val);
+ ulPatch = parse_release_number (&val);
+ ul4th = parse_release_number (&val);
+#endif
+
+ sprintf (buf, "%lu.%lu.%lu.%lu", ulMajor, ulMinor, ulPatch, ul4th);
+ define_variable ("KBUILD_HOST_VERSION", sizeof ("KBUILD_HOST_VERSION") - 1,
+ buf, o_default, 0);
+
+ sprintf (buf, "%lu", ulMajor);
+ define_variable ("KBUILD_HOST_VERSION_MAJOR", sizeof ("KBUILD_HOST_VERSION_MAJOR") - 1,
+ buf, o_default, 0);
+
+ sprintf (buf, "%lu", ulMinor);
+ define_variable ("KBUILD_HOST_VERSION_MINOR", sizeof ("KBUILD_HOST_VERSION_MINOR") - 1,
+ buf, o_default, 0);
+
+ sprintf (buf, "%lu", ulPatch);
+ define_variable ("KBUILD_HOST_VERSION_PATCH", sizeof ("KBUILD_HOST_VERSION_PATCH") - 1,
+ buf, o_default, 0);
+
/* The kBuild locations. */
define_variable ("KBUILD_PATH", sizeof ("KBUILD_PATH") - 1,
get_kbuild_path (), o_default, 0);
@@ -1191,6 +1278,7 @@ define_automatic_variables (void)
&& defined (CONFIG_WITH_SET_CONDITIONALS) \
&& defined (CONFIG_WITH_DATE) \
&& defined (CONFIG_WITH_FILE_SIZE) \
+ && defined (CONFIG_WITH_WHERE_FUNCTION) \
&& defined (CONFIG_WITH_WHICH) \
&& defined (CONFIG_WITH_EVALPLUS) \
&& (defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS)) \
@@ -1199,9 +1287,10 @@ define_automatic_variables (void)
&& defined (CONFIG_WITH_LOOP_FUNCTIONS) \
&& defined (CONFIG_WITH_ROOT_FUNC) \
&& defined (CONFIG_WITH_STRING_FUNCTIONS) \
+ && defined (CONFIG_WITH_DEFINED_FUNCTIONS) \
&& defined (KMK_HELPERS)
(void) define_variable ("KMK_FEATURES", 12,
- "append-dash-n abspath includedep-queue"
+ "append-dash-n abspath includedep-queue install-hard-linking"
" rsort"
" abspathex"
" toupper tolower"
@@ -1217,6 +1306,7 @@ define_automatic_variables (void)
" date"
" file-size"
" expr if-expr select"
+ " where"
" which"
" evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var"
" make-stats"
@@ -1226,10 +1316,11 @@ define_automatic_variables (void)
" root"
" length insert pos lastpos substr translate"
" kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl "
+ " firstdefined lastdefined "
, o_default, 0);
# else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */
# error "All features should be enabled by default!"
- strcpy (buf, "append-dash-n abspath includedep-queue");
+ strcpy (buf, "append-dash-n abspath includedep-queue install-hard-linking");
# if defined (CONFIG_WITH_RSORT)
strcat (buf, " rsort");
# endif
@@ -1275,6 +1366,9 @@ define_automatic_variables (void)
# if defined (CONFIG_WITH_IF_CONDITIONALS)
strcat (buf, " expr if-expr select");
# endif
+# if defined (CONFIG_WITH_WHERE_FUNCTION)
+ strcat (buf, " where");
+# endif
# if defined (CONFIG_WITH_WHICH)
strcat (buf, " which");
# endif
@@ -1299,6 +1393,9 @@ define_automatic_variables (void)
# if defined (CONFIG_WITH_STRING_FUNCTIONS)
strcat (buf, " length insert pos lastpos substr translate");
# endif
+# if defined (CONFIG_WITH_DEFINED_FUNCTIONS)
+ strcat (buf, " firstdefined lastdefined");
+# endif
# if defined (KMK_HELPERS)
strcat (buf, " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl");
# endif
diff --git a/src/kmk/w32/Makefile.kmk b/src/kmk/w32/Makefile.kmk
index 8eae64b..a6ef432 100644
--- a/src/kmk/w32/Makefile.kmk
+++ b/src/kmk/w32/Makefile.kmk
@@ -4,7 +4,7 @@
#
#
-# Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+# Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
#
# This file is part of kBuild.
#
diff --git a/src/kmk/w32/pathstuff.c b/src/kmk/w32/pathstuff.c
index aafbd53..eca3f24 100644
--- a/src/kmk/w32/pathstuff.c
+++ b/src/kmk/w32/pathstuff.c
@@ -1,6 +1,6 @@
/* Path conversion for Windows pathnames.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007 Free Software Foundation, Inc.
+2007, 2009 Free Software Foundation, Inc.
This file is part of GNU Make.
GNU Make is free software; you can redistribute it and/or modify it under the
@@ -51,6 +51,9 @@ convert_Path_to_windows32(char *Path, char to_delim)
char *p; /* points to element of old Path */
/* is this a multi-element Path ? */
+ /* FIXME: Perhaps use ":;\"" in strpbrk to convert all quotes to
+ delimiters as well, as a way to handle quoted directories in
+ PATH? */
for (p = Path, etok = strpbrk(p, ":;");
etok;
etok = strpbrk(p, ":;"))
@@ -76,8 +79,11 @@ convert_Path_to_windows32(char *Path, char to_delim)
for (p++; *p && *p != '"'; p++) /* skip quoted part */
;
etok = strpbrk(p, ":;"); /* find next delimiter */
- *etok = to_delim;
- p = ++etok;
+ if (etok) {
+ *etok = to_delim;
+ p = ++etok;
+ } else
+ p += strlen(p);
} else {
/* found another one, no drive letter */
*etok = to_delim;
diff --git a/src/kmk/w32/tstFileInfo.c b/src/kmk/w32/tstFileInfo.c
index 53a0962..94d47bb 100644
--- a/src/kmk/w32/tstFileInfo.c
+++ b/src/kmk/w32/tstFileInfo.c
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (c) 2007-2009 knut st. osmundsen <bird-kBuild-spamix@anduin.net>
+ * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
*
* This file is part of kBuild.
*