diff options
author | Felix Geyer <debfx-pkg@fobos.de> | 2011-08-21 11:16:23 +0200 |
---|---|---|
committer | Felix Geyer <debfx-pkg@fobos.de> | 2011-08-21 11:16:23 +0200 |
commit | bd9ff04c49dda0d5d1d99fb88960c1779f3229a3 (patch) | |
tree | ceb9f9f990c51a3bd1263e81091e460d66bbcb39 /src/kmk | |
parent | beb92cf0e95b1ffa9361993d7a248dbab63741c3 (diff) | |
download | kbuild-bd9ff04c49dda0d5d1d99fb88960c1779f3229a3.tar.gz |
Imported Upstream version 0.1.9998svn2543upstream/0.1.9998svn2543
Diffstat (limited to 'src/kmk')
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. * |