[Pkg-virtualbox-commits] [kbuild] 01/07: Imported Upstream version 0.1.9998svn2788+dfsg

Gianfranco Costamagna locutusofborg-guest at moszumanska.debian.org
Mon Sep 28 10:10:19 UTC 2015


This is an automated email from the git hooks/post-receive script.

locutusofborg-guest pushed a commit to branch master
in repository kbuild.

commit 66fc233046b910612db6d018de0797be2e159650
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Wed Sep 9 17:30:59 2015 +0200

    Imported Upstream version 0.1.9998svn2788+dfsg
---
 kBuild/units/qt4.kmk  |  32 +-
 src/kmk/file.c        |  12 +
 src/kmk/filedef.h     |   7 +
 src/kmk/function.c    |   2 +-
 src/kmk/kmk_cc_exec.c | 835 ++++++++++++++++++++++++++++++++++++++++++--------
 src/kmk/kmk_cc_exec.h |   9 +-
 src/kmk/main.c        |  16 +-
 src/kmk/read.c        |  22 ++
 8 files changed, 793 insertions(+), 142 deletions(-)

diff --git a/kBuild/units/qt4.kmk b/kBuild/units/qt4.kmk
index 5558bcd..b812984 100644
--- a/kBuild/units/qt4.kmk
+++ b/kBuild/units/qt4.kmk
@@ -1,4 +1,4 @@
-# $Id: qt4.kmk 2726 2014-02-26 23:23:54Z bird $
+# $Id: qt4.kmk 2787 2015-08-13 09:16:00Z bird $
 ## @file
 # Qt 4 unit.
 #
@@ -79,19 +79,35 @@ ifndef PATH_SDK_QT4
    else
     # The Unices. Includes and esp. libs are tricky, so override the PATH_SDK_QT4_LIB* stuff if it doesn't work.
     # Try find the general root of thing by looking for the qt3to4 program, if not found, then look for rcc.
-    PATH_SDK_QT4 := $(patsubst %/bin/qt3to4,%,$(firstword $(wildcard \
-	/usr/bin/qt3to4 \
-    	/usr/local/bin/qt3to4 \
-	/usr/qt/4/bin/qt3to4 \
-	/usr/share/qt4/bin/qt3to4 \
+    PATH_SDK_QT4 := $(patsubst %/bin/qt3to4-qt4,%,$(firstword $(wildcard \
+    	/usr/bin/qt3to4-qt4 \
+    	/usr/local/bin/qt3to4-qt4 \
+    	/usr/qt/4/bin/qt3to4-qt4 \
+    	/usr/share/qt4/bin/qt3to4-qt4 \
     	)))
     ifeq ($(PATH_SDK_QT4),)
+     PATH_SDK_QT4 := $(patsubst %/bin/qt3to4,%,$(firstword $(wildcard \
+     	/usr/bin/qt3to4 \
+     	/usr/local/bin/qt3to4 \
+     	/usr/qt/4/bin/qt3to4 \
+     	/usr/share/qt4/bin/qt3to4 \
+       	)))
+    endif
+    ifeq ($(PATH_SDK_QT4),)
+     PATH_SDK_QT4 := $(patsubst %/bin/rcc-qt4,%,$(firstword $(wildcard \
+     	/usr/bin/rcc-qt4 \
+     	/usr/local/bin/rcc-qt4 \
+     	/usr/qt/4/bin/rcc-qt4 \
+     	/usr/share/qt4/bin/rcc-qt4 \
+     	)))
+    endif
+    ifeq ($(PATH_SDK_QT4),)
      PATH_SDK_QT4 := $(patsubst %/bin/rcc,%,$(firstword $(wildcard \
      	/usr/bin/rcc \
-	/usr/local/bin/rcc \
+     	/usr/local/bin/rcc \
      	/usr/qt/4/bin/rcc \
      	/usr/share/qt4/bin/rcc \
-	)))
+     	)))
     endif
     ifneq ($(PATH_SDK_QT4),)
      export PATH_SDK_QT4
diff --git a/src/kmk/file.c b/src/kmk/file.c
index d6c6223..b87931b 100644
--- a/src/kmk/file.c
+++ b/src/kmk/file.c
@@ -1208,6 +1208,18 @@ print_file (const void *item)
     puts (_("#  Command line target."));
   if (f->dontcare)
     puts (_("#  A default, MAKEFILES, or -include/sinclude makefile."));
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+  if (f->eval_count > 0)
+    {
+# ifdef CONFIG_WITH_COMPILER
+      if (f->evalprog)
+        printf (_("#  Makefile evaluated %u times - compiled\n"), f->eval_count);
+      else
+# endif
+        printf (_("#  Makefile evaluated %u times\n"), f->eval_count);
+    }
+#endif
+
   puts (f->tried_implicit
         ? _("#  Implicit rule search has been done.")
         : _("#  Implicit rule search has not been done."));
diff --git a/src/kmk/filedef.h b/src/kmk/filedef.h
index a4eeb35..c7357fa 100644
--- a/src/kmk/filedef.h
+++ b/src/kmk/filedef.h
@@ -73,6 +73,10 @@ struct file
     struct file *multi_next;
 #endif
 
+#ifdef CONFIG_WITH_COMPILER
+    struct kmk_cc_evalprog *evalprog; /* Pointer to evalval/evalctx "program". */
+#endif
+
     short int update_status;	/* Status of the last attempt to update,
 				   or -1 if none has been made.  */
 
@@ -119,6 +123,9 @@ struct file
                                   can receive this is decided at parse time,
                                   and the expanding done in snap_deps. */
 #endif
+#if defined (CONFIG_WITH_COMPILER) || defined (CONFIG_WITH_MAKE_STATS)
+    unsigned int eval_count:14; /* Times evaluated as a makefile. */
+#endif
   };
 
 
diff --git a/src/kmk/function.c b/src/kmk/function.c
index 6852a84..740d7ab 100644
--- a/src/kmk/function.c
+++ b/src/kmk/function.c
@@ -2060,7 +2060,7 @@ func_evalval (char *o, char **argv, const char *funcname)
           || (v->evalval_count == 3 && kmk_cc_compile_variable_for_eval (v)))
         {
           install_variable_buffer (&buf, &len); /* Really necessary? */
-          kmk_exec_evalval (v);
+          kmk_exec_eval_variable (v);
           restore_variable_buffer (buf, len);
         }
       else
diff --git a/src/kmk/kmk_cc_exec.c b/src/kmk/kmk_cc_exec.c
index f49951d..a584500 100644
--- a/src/kmk/kmk_cc_exec.c
+++ b/src/kmk/kmk_cc_exec.c
@@ -1,5 +1,5 @@
 #ifdef CONFIG_WITH_COMPILER
-/* $Id: kmk_cc_exec.c 2777 2015-02-03 21:06:31Z bird $ */
+/* $Id: kmk_cc_exec.c 2788 2015-09-06 15:43:10Z bird $ */
 /** @file
  * kmk_cc - Make "Compiler".
  */
@@ -25,9 +25,9 @@
  */
 
 
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
 #include "make.h"
 
 #include "dep.h"
@@ -42,9 +42,10 @@
 #include <stdarg.h>
 #include <assert.h>
 
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
 /** @def KMK_CC_WITH_STATS
  * Enables the collection of extra statistics. */
 #ifndef KMK_CC_WITH_STATS
@@ -74,9 +75,50 @@
     KMK_CC_ASSERT( ((a_uValue) & ((a_uAlignment) - 1)) == 0 )
 
 
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
+/** @def KMK_CC_OFFSETOF
+ * Offsetof for simple stuff.  */
+#if defined(__GNUC__)
+# define KMK_CC_OFFSETOF(a_Struct, a_Member)        __builtin_offsetof(a_Struct, a_Member)
+#else
+# define KMK_CC_OFFSETOF(a_Struct, a_Member)        ( (uintptr_t)&( ((a_Struct *)(void *)0)->a_Member) )
+#endif
+
+/** def KMK_CC_SIZEOF_MEMBER   */
+#define KMK_CC_SIZEOF_MEMBER(a_Struct, a_Member)    ( sizeof( ((a_Struct *)(void *)0x1000)->a_Member) )
+
+/** @def KMK_CC_SIZEOF_VAR_STRUCT
+ * Size of a struct with a variable sized array as the final member. */
+#define KMK_CC_SIZEOF_VAR_STRUCT(a_Struct, a_FinalArrayMember, a_cArray) \
+    ( KMK_CC_OFFSETOF(a_Struct, a_FinalArrayMember) + KMK_CC_SIZEOF_MEMBER(a_Struct, a_FinalArrayMember) * (a_cArray) )
+
+
+
+/** @def KMK_CC_STATIC_ASSERT_EX
+ * Compile time assertion with text.
+ */
+#ifdef _MSC_VER_
+# if _MSC_VER >= 1600
+#  define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) static_assert(a_Expr, a_szExpl)
+# else
+#  define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl) typedef int RTASSERTVAR[(a_Expr) ? 1 : 0]
+# endif
+#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl)     static_assert(a_Expr, a_szExpl)
+#elif !defined(__GNUC__) && !defined(__IBMC__) && !defined(__IBMCPP__)
+# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl)  typedef int KMK_CC_STATIC_ASSERT_EX_TYPE[(a_Expr) ? 1 : 0]
+#else
+# define KMK_CC_STATIC_ASSERT_EX(a_Expr, a_szExpl)  extern int KMK_CC_STATIC_ASSERT_EX_VAR[(aExpr) ? 1 : 0]
+extern int KMK_CC_STATIC_ASSERT_EX_VAR[1];
+#endif
+/** @def KMK_CC_STATIC_ASSERT
+ * Compile time assertion, simple variant.
+ */
+#define KMK_CC_STATIC_ASSERT(a_Expr)                KMK_CC_STATIC_ASSERT_EX(a_Expr, #a_Expr)
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
 /**
  * Block of expand instructions.
  *
@@ -95,6 +137,10 @@ typedef struct kmk_cc_block
 } KMKCCBLOCK;
 typedef KMKCCBLOCK *PKMKCCBLOCK;
 
+
+/** @name String Expansion
+ * @{*/
+
 /**
  * String expansion statistics.
  */
@@ -130,19 +176,20 @@ typedef enum KMKCCEXPINSTR
     kKmkCcExpInstr_Return,
     /** The end of valid instructions (exclusive). */
     kKmkCcExpInstr_End
-} KMKCCEXPANDINSTR;
+} KMKCCEXPINSTR;
 
 /** Instruction core. */
 typedef struct kmk_cc_exp_core
 {
-    /** The instruction opcode number (KMKCCEXPANDINSTR). */
-    KMKCCEXPANDINSTR        enmOpCode;
+    /** The instruction opcode number (KMKCCEXPINSTR). */
+    KMKCCEXPINSTR           enmOpCode;
 } KMKCCEXPCORE;
 typedef KMKCCEXPCORE *PKMKCCEXPCORE;
 
 /**
- * String expansion sub program.
+ * String expansion subprogram.
  */
+#pragma pack(1) /* save some precious bytes */
 typedef struct kmk_cc_exp_subprog
 {
     /** Pointer to the first instruction. */
@@ -150,7 +197,48 @@ typedef struct kmk_cc_exp_subprog
     /** Statistics. */
     KMKCCEXPSTATS           Stats;
 } KMKCCEXPSUBPROG;
+#pragma pack()
 typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG;
+KMK_CC_STATIC_ASSERT(sizeof(KMKCCEXPSUBPROG) == 12 || sizeof(void *) != 8);
+
+
+/**
+ * String expansion subprogram or plain string.
+ */
+#pragma pack(1) /* save some precious bytes */
+typedef struct kmk_cc_exp_subprog_or_string
+{
+    /** Either a plain string pointer or a subprogram.   */
+    union
+    {
+        /** Subprogram for expanding this argument. */
+        KMKCCEXPSUBPROG     Subprog;
+        /** Pointer to the plain string. */
+        struct
+        {
+            /** Pointer to the string. */
+            const char     *psz;
+            /** String length. */
+            uint32_t        cch;
+        } Plain;
+    } u;
+    /** Set if subprogram (u.Subprog), clear if plain string (u.Plain). */
+    uint8_t                 fSubprog;
+    /** Set if the plain string is kept in the variable_strcache.
+     * @remarks Here rather than in u.Plain to make use of alignment padding. */
+    uint8_t                 fPlainIsInVarStrCache;
+    /** Context/user specific. */
+    uint8_t                 bUser;
+    /** Context/user specific #2. */
+    uint8_t                 bUser2;
+} KMKCCEXPSUBPROGORPLAIN;
+#pragma pack()
+typedef KMKCCEXPSUBPROGORPLAIN *PKMKCCEXPSUBPROGORPLAIN;
+KMK_CC_STATIC_ASSERT(  sizeof(void *) == 8
+                     ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 16
+                     : sizeof(void *) == 4
+                     ? sizeof(KMKCCEXPSUBPROGORPLAIN) == 12
+                     : 1);
 
 /**
  * kKmkCcExpInstr_CopyString instruction format.
@@ -185,11 +273,11 @@ typedef struct kmk_cc_exp_dynamic_variable
 {
     /** The core instruction. */
     KMKCCEXPCORE            Core;
+    /** The subprogram that will give us the variable name. */
+    KMKCCEXPSUBPROG         Subprog;
     /** Where to continue after this instruction.  (This is necessary since the
      * instructions of the subprogram are emitted after this instruction.) */
     PKMKCCEXPCORE           pNext;
-    /** The subprogram that will give us the variable name. */
-    KMKCCEXPSUBPROG         SubProg;
 } KMKCCEXPDYNVAR;
 typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR;
 
@@ -225,7 +313,7 @@ typedef struct kmk_cc_exp_function_core
     /** The core instruction. */
     KMKCCEXPCORE            Core;
     /** Number of arguments. */
-    uint32_t                cArgs;
+    uint32_t                cArgs; /**< @todo uint16_t to save 7 bytes of unecessary alignment padding on 64-bit systems, or merge fDirty into this member. */
     /** Set if the function could be modifying the input arguments. */
     uint8_t                 fDirty;
     /** Where to continue after this instruction.  (This is necessary since the
@@ -251,7 +339,7 @@ typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE;
 typedef struct kmk_cc_exp_plain_function
 {
     /** The bits comment to both plain and dynamic functions. */
-    KMKCCEXPFUNCCORE        Core;
+    KMKCCEXPFUNCCORE        FnCore;
     /** Variable sized argument list (cArgs + 1 in length, last entry is NULL).
      * The string pointers are to memory following this instruction, to memory in
      * the next block or to memory in the variable / makefile we're working on
@@ -259,8 +347,9 @@ typedef struct kmk_cc_exp_plain_function
     const char             *apszArgs[1];
 } KMKCCEXPPLAINFUNC;
 typedef KMKCCEXPPLAINFUNC *PKMKCCEXPPLAINFUNC;
-/** Calculates the size of an KMKCCEXPPLAINFUNC with a_cArgs. */
-#define KMKCCEXPPLAINFUNC_SIZE(a_cArgs)  (sizeof(KMKCCEXPFUNCCORE) + (a_cArgs + 1) * sizeof(const char *))
+/** Calculates the size of an KMKCCEXPPLAINFUNC structure with the apszArgs
+ * member holding a_cArgs entries plus a NULL terminator. */
+#define KMKCCEXPPLAINFUNC_SIZE(a_cArgs) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, (a_cArgs) + 1)
 
 /**
  * Instruction format for kKmkCcExpInstr_DynamicFunction.
@@ -268,33 +357,16 @@ typedef KMKCCEXPPLAINFUNC *PKMKCCEXPPLAINFUNC;
 typedef struct kmk_cc_exp_dyn_function
 {
     /** The bits comment to both plain and dynamic functions. */
-    KMKCCEXPFUNCCORE        Core;
-    /** Variable sized argument list (cArgs + 1 in length, last entry is NULL).
-     * The string pointers are to memory following this instruction, to memory in
-     * the next block or to memory in the variable / makefile we're working on
-     * (if zero terminated appropriately). */
-    struct
-    {
-        /** Set if plain string argument, clear if sub program. */
-        uint8_t             fPlain;
-        union
-        {
-            /** Sub program for expanding this argument. */
-            KMKCCEXPSUBPROG     SubProg;
-            struct
-            {
-                /** Pointer to the plain argument string.
-                 * This is allocated in the same manner as the
-                 * string pointed to by KMKCCEXPPLAINFUNC::apszArgs. */
-                const char      *pszArg;
-            } Plain;
-        } u;
-    }                       aArgs[1];
+    KMKCCEXPFUNCCORE        FnCore;
+    /** Variable sized argument list (FnCore.cArgs in length).
+     * The subprograms / strings are allocated after this array (or in the next
+     * block). */
+    KMKCCEXPSUBPROGORPLAIN  aArgs[1];
 } KMKCCEXPDYNFUNC;
 typedef KMKCCEXPDYNFUNC *PKMKCCEXPDYNFUNC;
-/** Calculates the size of an KMKCCEXPPLAINFUNC with a_cArgs. */
-#define KMKCCEXPDYNFUNC_SIZE(a_cArgs)  (  sizeof(KMKCCEXPFUNCCORE) \
-                                        + (a_cArgs) * sizeof(((PKMKCCEXPDYNFUNC)(uintptr_t)42)->aArgs[0]) )
+/** Calculates the size of an KMKCCEXPDYNFUNC structure with the apszArgs
+ * member holding a_cArgs entries (no zero terminator). */
+#define KMKCCEXPDYNFUNC_SIZE(a_cArgs)  KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEXPDYNFUNC, aArgs, a_cArgs)
 
 /**
  * Instruction format for kKmkCcExpInstr_Jump.
@@ -330,10 +402,427 @@ typedef struct kmk_cc_expandprog
 /** Pointer to a string expansion program. */
 typedef KMKCCEXPPROG *PKMKCCEXPPROG;
 
+/** @} */
+
+
+/** @name Makefile Evaluation
+ * @{  */
+
+/** Pointer to a makefile evaluation program. */
+typedef struct kmk_cc_evalprog *PKMKCCEVALPROG;
+
+/**
+ * Makefile evaluation instructions.
+ */
+typedef enum KMKCCEVALINSTR
+{
+    /** Jump instruction - KMKCCEVALJUMP. */
+    kKmkCcEvalInstr_jump = 0,
+
+    /** [local|override|export] variable  = value - KMKCCEVALASSIGN.
+     * @note Can be used for target-specific variables. */
+    kKmkCcEvalInstr_assign_recursive,
+    /** [local|override|export] variable := value - KMKCCEVALASSIGN.
+     * @note Can be used for target-specific variables. */
+    kKmkCcEvalInstr_assign_simple,
+    /** [local|override|export] variable += value - KMKCCEVALASSIGN.
+     * @note Can be used for target-specific variables. */
+    kKmkCcEvalInstr_assign_append,
+    /** [local|override|export] variable -= value - KMKCCEVALASSIGN.
+     * @note Can be used for target-specific variables. */
+    kKmkCcEvalInstr_assign_prepend,
+    /** [local|override|export] variable ?= value - KMKCCEVALASSIGN.
+     * @note Can be used for target-specific variables. */
+    kKmkCcEvalInstr_assign_if_new,
+    /** [local|override|export] define variable ... endef - KMKCCEVALASSIGNDEF. */
+    kKmkCcEvalInstr_assign_define,
+
+    /** export variable1 [variable2...] - KMKCCEVALEXPORT. */
+    kKmkCcEvalInstr_export,
+    /** unexport variable1 [variable2...] - KMKCCEVALEXPORT. */
+    kKmkCcEvalInstr_unexport,
+    /** export - KMKCCEVALCORE. */
+    kKmkCcEvalInstr_export_all,
+    /** unexport - KMKCCEVALCORE. */
+    kKmkCcEvalInstr_unexport_all,
+
+    /** [else] ifdef variable - KMKCCEVALIFDEFPLAIN. */
+    kKmkCcEvalInstr_ifdef_plain,
+    /** [else] ifndef variable - KMKCCEVALIFDEFPLAIN. */
+    kKmkCcEvalInstr_ifndef_plain,
+    /** [else] ifdef variable - KMKCCEVALIFDEFDYNAMIC. */
+    kKmkCcEvalInstr_ifdef_dynamic,
+    /** [else] ifndef variable - KMKCCEVALIFDEFDYNAMIC. */
+    kKmkCcEvalInstr_ifndef_dynamic,
+    /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */
+    kKmkCcEvalInstr_ifeq,
+    /** [else] ifeq (a,b) - KMKCCEVALIFEQ. */
+    kKmkCcEvalInstr_ifneq,
+    /** [else] if1of (set-a,set-b) - KMKCCEVALIF1OF. */
+    kKmkCcEvalInstr_if1of,
+    /** [else] ifn1of (set-a,set-b) - KMKCCEVALIF1OF. */
+    kKmkCcEvalInstr_ifn1of,
+    /** [else] if expr - KMKCCEVALIFEXPR. */
+    kKmkCcEvalInstr_if,
+
+    /** include file1 [file2...] - KMKCCEVALINCLUDE. */
+    kKmkCcEvalInstr_include,
+    /** [sinclude|-include] file1 [file2...]  - KMKCCEVALINCLUDE. */
+    kKmkCcEvalInstr_include_silent,
+    /** includedep file1 [file2...] - KMKCCEVALINCLUDE. */
+    kKmkCcEvalInstr_includedep,
+    /** includedep-queue file1 [file2...] - KMKCCEVALINCLUDE. */
+    kKmkCcEvalInstr_includedep_queue,
+    /** includedep-flush file1 [file2...] - KMKCCEVALINCLUDE. */
+    kKmkCcEvalInstr_includedep_flush,
+
+    /** Recipe without commands (defines dependencies) - KMKCCEVALRECIPE. */
+    kKmkCcEvalInstr_recipe_no_commands,
+    /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
+    kKmkCcEvalInstr_recipe_start_normal,
+    /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
+    kKmkCcEvalInstr_recipe_start_double_colon,
+    /** Recipe with commands (defines dependencies) - KMKCCEVALRECIPE. */
+    kKmkCcEvalInstr_recipe_start_pattern,
+    /** Adds more commands to the current recipe - KMKCCEVALRECIPECOMMANDS. */
+    kKmkCcEvalInstr_recipe_commands,
+    /** Adds more commands to the current recipe - KMKCCEVALRECIPECOMMANDS. */
+    kKmkCcEvalInstr_recipe_vari,
+    /** Special instruction for indicating the end of the recipe commands - KMKCCEVALCORE. */
+    kKmkCcEvalInstr_recipe_end,
+    /** Cancel previously defined pattern rule - KMKCCEVALRECIPE.  */
+    kKmkCcEvalInstr_recipe_cancel_pattern,
+
+    /** vpath pattern directories - KMKCCEVALVPATH. */
+    kKmkCcEvalInstr_vpath,
+    /** vpath pattern directories - KMKCCEVALVPATH. */
+    kKmkCcEvalInstr_vpath_clear_pattern,
+    /** vpath - KMKCCEVALCORE. */
+    kKmkCcEvalInstr_vpath_clear_all,
+
+    /** The end of valid instructions (exclusive). */
+    kKmkCcEvalInstr_End
+} KMKCCEVALINSTR;
+
+/**
+ * Instruction core common to all instructions.
+ */
+typedef struct kmk_cc_eval_core
+{
+    /** The instruction opcode number (KMKCCEVALINSTR). */
+    KMKCCEVALINSTR          enmOpCode;
+    /** The line number in the source this statement is associated with. */
+    unsigned                iLine;
+} KMKCCEVALCORE;
+/** Pointer to an instruction core structure. */
+typedef KMKCCEVALCORE *PKMKCCEVALCORE;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_jump.
+ */
+typedef struct kmk_cc_eval_jump
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** Where to jump to (new instruction block or endif, typically). */
+    PKMKCCEVALCORE          pNext;
+} KMKCCEVALJUMP;
+typedef KMKCCEVALJUMP *PKMKCCEVALJUMP;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_assign_recursive,
+ * kKmkCcEvalInstr_assign_simple, kKmkCcEvalInstr_assign_append,
+ * kKmkCcEvalInstr_assign_prepend and kKmkCcEvalInstr_assign_if_new.
+ */
+typedef struct kmk_cc_eval_assign
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** Whether the 'export' directive was used. */
+    uint8_t                 fExport;
+    /** Whether the 'override' directive was used. */
+    uint8_t                 fOverride;
+    /** Whether the 'local' directive was used. */
+    uint8_t                 fLocal;
+    /** The variable name.
+     * @remarks Plain text names are in variable_strcache. */
+    KMKCCEXPSUBPROGORPLAIN  Variable;
+    /** The value or value expression. */
+    KMKCCEXPSUBPROGORPLAIN  Value;
+    /** Pointer to the next instruction. */
+    PKMKCCEVALCORE          pNext;
+} KMKCCEVALASSIGN;
+typedef KMKCCEVALASSIGN *PKMKCCEVALASSIGN;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_assign_define.
+ */
+typedef struct kmk_cc_eval_assign_define
+{
+    /** The assignment core structure. */
+    KMKCCEVALASSIGN         AssignCore;
+    /** Makefile evaluation program compiled from the define.
+     * NULL if it does not compile.
+     * @todo Let's see if this is actually doable... */
+    PKMKCCEVALPROG          pEvalProg;
+} KMKCCEVALASSIGNDEF;
+typedef KMKCCEVALASSIGNDEF *PKMKCCEVALASSIGNDEF;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_export and kKmkCcEvalInstr_unexport.
+ */
+typedef struct kmk_cc_eval_export
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** The number of variables named in aVars. */
+    uint32_t                cVars;
+    /** Pointer to the next instruction. */
+    PKMKCCEVALCORE          pNext;
+    /** The variable names.
+     * Expressions will be expanded and split on space.
+     * @remarks Plain text names are in variable_strcache. */
+    KMKCCEXPSUBPROGORPLAIN  aVars[1];
+} KMKCCEVALEXPORT;
+typedef KMKCCEVALEXPORT *PKMKCCEVALEXPORT;
+/** Calculates the size of an KMKCCEVALEXPORT structure for @a a_cVars. */
+#define KMKCCEVALEXPORT_SIZE(a_cVars) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aVars, a_cVars)
+
+/**
+ * Core structure for all conditionals (kKmkCcEvalInstr_if*).
+ */
+typedef struct kmk_cc_eval_if_core
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** Condition true: Pointer to the next instruction. */
+    PKMKCCEVALCORE          pNextTrue;
+    /** Condition false: Pointer to the next instruction (i.e. 'else if*'
+     * or whatever follows 'else' / 'endif'. */
+    PKMKCCEVALCORE          pNextFalse;
+    /** Pointer to the previous conditional for 'else if*' directives.
+     * This is to assist the compilation process. */
+    PKMKCCEVALCORE          pPrevCond;
+} KMKCCEVALIFCORE;
+typedef KMKCCEVALIFCORE *PKMKCCEVALIFCORE;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_ifdef_plain and
+ * kKmkCcEvalInstr_ifndef_plain.
+ * The variable name is known at compilation time.
+ */
+typedef struct kmk_cc_eval_ifdef_plain
+{
+    /** The 'if' core structure. */
+    KMKCCEVALIFCORE         IfCore;
+    /** The name of the variable (points into variable_strcache). */
+    const char             *pszName;
+} KMKCCEVALIFDEFPLAIN;
+typedef KMKCCEVALIFDEFPLAIN *PKMKCCEVALIFDEFPLAIN;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_ifdef_dynamic and
+ * kKmkCcEvalInstr_ifndef_dynamic.
+ * The variable name is dynamically expanded at run time.
+ */
+typedef struct kmk_cc_eval_ifdef_dynamic
+{
+    /** The 'if' core structure. */
+    KMKCCEVALIFCORE         IfCore;
+    /** The subprogram that will give us the variable name. */
+    KMKCCEXPSUBPROG         NameSubProg;
+} KMKCCEVALIFDEFDYNAMIC;
+KMK_CC_STATIC_ASSERT(sizeof(KMKCCEVALIFDEFDYNAMIC) == 48 || sizeof(void *) != 8);
+typedef KMKCCEVALIFDEFDYNAMIC *PKMKCCEVALIFDEFDYNAMIC;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_ifeq and kKmkCcEvalInstr_ifneq.
+ */
+typedef struct kmk_cc_eval_ifeq
+{
+    /** The 'if' core structure. */
+    KMKCCEVALIFCORE         IfCore;
+    /** The left hand side string expression (dynamic or plain). */
+    KMKCCEXPSUBPROGORPLAIN  Left;
+    /** The rigth hand side string expression (dynamic or plain). */
+    KMKCCEXPSUBPROGORPLAIN  Right;
+} KMKCCEVALIFEQ;
+typedef KMKCCEVALIFEQ *PKMKCCEVALIFEQ;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_if1of and kKmkCcEvalInstr_ifn1of.
+ *
+ * @todo This can be optimized further by pre-hashing plain text items.  One of
+ *       the sides are usually plain text.
+ */
+typedef struct kmk_cc_eval_if1of
+{
+    /** The 'if' core structure. */
+    KMKCCEVALIFCORE         IfCore;
+    /** The left hand side string expression (dynamic or plain). */
+    KMKCCEXPSUBPROGORPLAIN  Left;
+    /** The rigth hand side string expression (dynamic or plain). */
+    KMKCCEXPSUBPROGORPLAIN  Right;
+} KMKCCEVALIF1OF;
+typedef KMKCCEVALIF1OF *PKMKCCEVALIF1OF;
+
+/**
+ * Instruction format for kKmkCcEvalInstr_if.
+ *
+ * @todo Parse and compile the expression.  At least strip whitespace in it.
+ */
+typedef struct kmk_cc_eval_if_expr
+{
+    /** The 'if' core structure. */
+    KMKCCEVALIFCORE         IfCore;
+    /** The expression string length. */
+    uint16_t                cchExpr;
+    /** The expression string. */
+    char                    szExpr[1];
+} KMKCCEVALIFEXPR;
+typedef KMKCCEVALIFEXPR *PKMKCCEVALIFEXPR;
+/** Calculates the size of an KMKCCEVALIFEXPR structure for @a a_cchExpr long
+ * expression string (terminator is automatically added).  */
+#define KMKCCEVALIFEXPR_SIZE(a_cchExpr) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALIFEXPR, szExpr, (a_cchExpr) + 1)
+
+/**
+ * Instruction format for kKmkCcEvalInstr_include,
+ * kKmkCcEvalInstr_include_silent, kKmkCcEvalInstr_includedep,
+ * kKmkCcEvalInstr_includedep_queue, kKmkCcEvalInstr_includedep_flush.
+ */
+typedef struct kmk_cc_eval_include
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** The number of files. */
+    uint32_t                cFiles;
+    /** Pointer to the next instruction (subprogs and strings after this one). */
+    PKMKCCEVALCORE          pNext;
+    /** The files to be included.
+     * Expressions will be expanded and split on space.
+     * @todo Plain text file name could be replaced by file string cache entries. */
+    KMKCCEXPSUBPROGORPLAIN  aFiles[1];
+} KMKCCEVALINCLUDE;
+typedef KMKCCEVALINCLUDE *PKMKCCEVALINCLUDE;
+/** Calculates the size of an KMKCCEVALINCLUDE structure for @a a_cFiles files. */
+#define KMKCCEVALINCLUDE_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALINCLUDE, aFiles, a_cFiles)
+
+/**
+ * Instruction format for kKmkCcEvalInstr_recipe_no_commands,
+ * kKmkCcEvalInstr_recipe_start_normal,
+ * kKmkCcEvalInstr_recipe_start_double_colon, kKmkCcEvalInstr_includedep_queue,
+ * kKmkCcEvalInstr_recipe_start_pattern.
+ */
+typedef struct kmk_cc_eval_recipe
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** The total number of files and dependencies in aFilesAndDeps. */
+    uint16_t                cFilesAndDeps;
+
+    /** Number of targets (from index 0).
+     * This is always 1 if this is an explicit multitarget or pattern recipe,
+     * indicating the main target. */
+    uint16_t                cTargets;
+    /** Explicit multitarget & patterns: First always made target. */
+    uint16_t                iFirstAlwaysMadeTargets;
+    /** Explicit multitarget & patterns: Number of always targets. */
+    uint16_t                cAlwaysMadeTargets;
+    /** Explicit multitarget: First maybe made target. */
+    uint16_t                iFirstMaybeTarget;
+    /** Explicit multitarget: Number of maybe made targets. */
+    uint16_t                cMaybeTargets;
+
+    /** First dependency. */
+    uint16_t                iFirstDep;
+    /** Number of ordinary dependnecies. */
+    uint16_t                cDeps;
+    /** First order only dependency. */
+    uint16_t                iFirstOrderOnlyDep;
+    /** Number of ordinary dependnecies. */
+    uint16_t                cOrderOnlyDeps;
+
+    /** Pointer to the next instruction (subprogs and strings after this one). */
+    PKMKCCEVALCORE          pNext;
+    /** The .MUST_MAKE variable value, if present.
+     * If not present, this is a zero length plain string. */
+    KMKCCEXPSUBPROGORPLAIN  MustMake;
+    /** The target files and dependencies.
+     * This is sorted into several sections, as defined by the above indexes and
+     * counts.  Expressions will be expanded and split on space.
+     *
+     * The KMKCCEXPSUBPROGORPLAIN::bUser member is used to indicate secondary
+     * expansion for a plain text entry.
+     *
+     * @todo Plain text file name could be replaced by file string cache entries. */
+    KMKCCEXPSUBPROGORPLAIN  aFilesAndDeps[1];
+} KMKCCEVALRECIPE;
+typedef KMKCCEVALRECIPE *PKMKCCEVALRECIPE;
+/** Calculates the size of an KMKCCEVALRECIPE structure for @a a_cFiles
+ *  files. */
+#define KMKCCEVALRECIPE_SIZE(a_cFilesAndDeps) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPE, aFilesAndDeps, a_cFilesAndDeps)
+
+/**
+ * Instruction format for kKmkCcEvalInstr_recipe_commands.
+ */
+typedef struct kmk_cc_eval_recipe_commands
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** The number of search directories. */
+    uint32_t                cCommands;
+    /** Pointer to the next instruction (subprogs and strings after this one). */
+    PKMKCCEVALCORE          pNext;
+    /** Commands to add to the current recipe.
+     * Expressions will be expanded and split on space. */
+    KMKCCEXPSUBPROGORPLAIN  aCommands[1];
+} KMKCCEVALRECIPECOMMANDS;
+typedef KMKCCEVALRECIPECOMMANDS *PKMKCCEVALRECIPECOMMANDS;
+/** Calculates the size of an KMKCCEVALRECIPECOMMANDS structure for
+ * @a a_cCommands commands. */
+#define KMKCCEVALRECIPECOMMANDS_SIZE(a_cCommands) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALRECIPECOMMANDS, aCommands, a_cCommands)
 
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
+/**
+ * Instruction format for kKmkCcEvalInstr_vpath and
+ * kKmkCcEvalInstr_vpath_clear_pattern.
+ */
+typedef struct kmk_cc_eval_vpath
+{
+    /** The core instruction. */
+    KMKCCEVALCORE           Core;
+    /** The number of search directories.
+     * This will be zero for kKmkCcEvalInstr_vpath_clear_pattern. */
+    uint32_t                cDirs;
+    /** Pointer to the next instruction (subprogs and strings after this one). */
+    PKMKCCEVALCORE          pNext;
+    /** The pattern. */
+    KMKCCEXPSUBPROGORPLAIN  Pattern;
+    /** The directory. Expressions will be expanded and split on space. */
+    KMKCCEXPSUBPROGORPLAIN  aDirs[1];
+} KMKCCEVALVPATH;
+typedef KMKCCEVALVPATH *PKMKCCEVALVPATH;
+/** Calculates the size of an KMKCCEVALVPATH structure for @a a_cFiles files. */
+#define KMKCCEVALVPATH_SIZE(a_cFiles) KMK_CC_SIZEOF_VAR_STRUCT(KMKCCEVALVPATH, aDirs, a_cDirs)
+
+
+/**
+ * Makefile evaluation program.
+ */
+typedef struct kmk_cc_evalprog
+{
+    /** Pointer to the first instruction for this program. */
+    PKMKCCEVALCORE          pFirstInstr;
+    /** List of blocks for this program (LIFO). */
+    PKMKCCBLOCK             pBlockTail;
+
+} KMKCCEVALPROG;
+
+/** @} */
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
 static uint32_t g_cVarForExpandCompilations = 0;
 static uint32_t g_cVarForExpandExecs = 0;
 #ifdef KMK_CC_WITH_STATS
@@ -348,9 +837,9 @@ static uint32_t g_cbUnusedMemExpProgs = 0;
 #endif
 
 
-/*******************************************************************************
-*   Internal Functions                                                         *
-*******************************************************************************/
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg);
 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcch);
 
@@ -372,7 +861,7 @@ void kmk_cc_print_stats(void)
 
     printf(_("# Variables compiled for string expansion: %6u\n"), g_cVarForExpandCompilations);
     printf(_("# Variables string expansion runs:         %6u\n"), g_cVarForExpandExecs);
-    printf(_("# String expansion runs per compile:       %6u\n"), g_cVarForExpandExecs / g_cVarForExpandExecs);
+    printf(_("# String expansion runs per compile:       %6u\n"), g_cVarForExpandExecs / g_cVarForExpandCompilations);
 #ifdef KMK_CC_WITH_STATS
     printf(_("#          Single alloc block exp progs:   %6u (%u%%)\n"
              "#             Two alloc block exp progs:   %6u (%u%%)\n"
@@ -734,8 +1223,7 @@ static void kmk_cc_block_free_list(PKMKCCBLOCK pBlockTail)
     }
 }
 
-
-/*
+   /*
  *
  * The string expansion compiler.
  * The string expansion compiler.
@@ -825,11 +1313,11 @@ static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *ps
      */
     uint32_t            cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs;
     PKMKCCEXPDYNFUNC    pInstr  = (PKMKCCEXPDYNFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPDYNFUNC_SIZE(cActualArgs));
-    pInstr->Core.Core.enmOpCode = kKmkCcExpInstr_DynamicFunction;
-    pInstr->Core.cArgs          = cActualArgs;
-    pInstr->Core.pfnFunction    = pfnFunction;
-    pInstr->Core.pszFuncName    = pszFunction;
-    pInstr->Core.fDirty         = kmk_cc_is_dirty_function(pszFunction);
+    pInstr->FnCore.Core.enmOpCode = kKmkCcExpInstr_DynamicFunction;
+    pInstr->FnCore.cArgs          = cActualArgs;
+    pInstr->FnCore.pfnFunction    = pfnFunction;
+    pInstr->FnCore.pszFuncName    = pszFunction;
+    pInstr->FnCore.fDirty         = kmk_cc_is_dirty_function(pszFunction);
 
     /*
      * Parse the arguments.  Plain arguments gets duplicated in the program
@@ -864,20 +1352,21 @@ static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *ps
             cchThisArg++;
         }
 
-        pInstr->aArgs[iArg].fPlain = !fDollar;
+        pInstr->aArgs[iArg].fSubprog = fDollar;
         if (fDollar)
         {
             /* Compile it. */
             int rc;
             kmk_cc_block_realign(ppBlockTail);
-            rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchArgs, cchThisArg, &pInstr->aArgs[iArg].u.SubProg);
+            rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchArgs, cchThisArg, &pInstr->aArgs[iArg].u.Subprog);
             if (rc != 0)
                 return rc;
         }
         else
         {
             /* Duplicate it. */
-            pInstr->aArgs[iArg].u.Plain.pszArg = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg);
+            pInstr->aArgs[iArg].u.Plain.psz = kmk_cc_block_strdup(ppBlockTail, pchArgs, cchThisArg);
+            pInstr->aArgs[iArg].u.Plain.cch = cchThisArg;
         }
         iArg++;
         if (ch != ',')
@@ -891,7 +1380,7 @@ static int kmk_cc_exp_emit_dyn_function(PKMKCCBLOCK *ppBlockTail, const char *ps
      * Realign the allocator and take down the address of the next instruction.
      */
     kmk_cc_block_realign(ppBlockTail);
-    pInstr->Core.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
+    pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
     return 0;
 }
 
@@ -925,11 +1414,11 @@ static void kmk_cc_exp_emit_plain_function(PKMKCCBLOCK *ppBlockTail, const char
      */
     uint32_t            cActualArgs = cArgs <= cMaxArgs || !cMaxArgs ? cArgs : cMaxArgs;
     PKMKCCEXPPLAINFUNC  pInstr  = (PKMKCCEXPPLAINFUNC)kmk_cc_block_alloc_exp(ppBlockTail, KMKCCEXPPLAINFUNC_SIZE(cActualArgs));
-    pInstr->Core.Core.enmOpCode = kKmkCcExpInstr_PlainFunction;
-    pInstr->Core.cArgs          = cActualArgs;
-    pInstr->Core.pfnFunction    = pfnFunction;
-    pInstr->Core.pszFuncName    = pszFunction;
-    pInstr->Core.fDirty         = kmk_cc_is_dirty_function(pszFunction);
+    pInstr->FnCore.Core.enmOpCode = kKmkCcExpInstr_PlainFunction;
+    pInstr->FnCore.cArgs          = cActualArgs;
+    pInstr->FnCore.pfnFunction    = pfnFunction;
+    pInstr->FnCore.pszFuncName    = pszFunction;
+    pInstr->FnCore.fDirty         = kmk_cc_is_dirty_function(pszFunction);
 
     /*
      * Parse the arguments.  Plain arguments gets duplicated in the program
@@ -975,7 +1464,7 @@ static void kmk_cc_exp_emit_plain_function(PKMKCCBLOCK *ppBlockTail, const char
      * Realign the allocator and take down the address of the next instruction.
      */
     kmk_cc_block_realign(ppBlockTail);
-    pInstr->Core.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
+    pInstr->FnCore.pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
 }
 
 
@@ -998,7 +1487,7 @@ static int kmk_cc_exp_emit_dyn_variable(PKMKCCBLOCK *ppBlockTail, const char *pc
     pInstr = (PKMKCCEXPDYNVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr));
     pInstr->Core.enmOpCode = kKmkCcExpInstr_DynamicVariable;
 
-    rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchNameExpr, cchNameExpr, &pInstr->SubProg);
+    rc = kmk_cc_exp_compile_subprog(ppBlockTail, pchNameExpr, cchNameExpr, &pInstr->Subprog);
 
     pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail);
     return rc;
@@ -1409,7 +1898,7 @@ static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats)
 
 
 /**
- * Compiles a string expansion sub program.
+ * Compiles a string expansion subprogram.
  *
  * The caller typically make a call to kmk_cc_block_get_next_ptr after this
  * function returns to figure out where to continue executing.
@@ -1421,7 +1910,7 @@ static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats)
  *                              lifetime of the program).
  * @param   cchStr              The length of the string to compile. Expected to
  *                              be at least on char long.
- * @param   pSubProg            The sub program structure to initialize.
+ * @param   pSubProg            The subprogram structure to initialize.
  */
 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg)
 {
@@ -1464,7 +1953,7 @@ static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr)
 #endif
 
         /*
-         * Join forces with the sub program compilation code.
+         * Join forces with the subprogram compilation code.
          */
         if (kmk_cc_exp_compile_common(&pProg->pBlockTail, pchStr, cchStr) == 0)
         {
@@ -1492,18 +1981,6 @@ static PKMKCCEXPPROG kmk_cc_exp_compile(const char *pchStr, uint32_t cchStr)
 
 
 /**
- * Compiles a variable direct evaluation as is, setting v->evalprog on success.
- *
- * @returns Pointer to the program on success, NULL if no program was created.
- * @param   pVar        Pointer to the variable.
- */
-struct kmk_cc_evalprog   *kmk_cc_compile_variable_for_eval(struct variable *pVar)
-{
-    return NULL;
-}
-
-
-/**
  * Updates the recursive_without_dollar member of a variable structure.
  *
  * This avoid compiling string expansion programs without only a CopyString
@@ -1620,7 +2097,7 @@ static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrC
                 PKMKCCEXPDYNVAR  pInstr = (PKMKCCEXPDYNVAR)pInstrCore;
                 struct variable *pVar;
                 uint32_t         cchName;
-                char            *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->SubProg, &cchName);
+                char            *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->Subprog, &cchName);
                 char            *pszColon = (char *)memchr(pszName, ':', cchName);
                 char            *pszEqual;
                 if (   pszColon == NULL
@@ -1716,20 +2193,20 @@ static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrC
             {
                 PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)pInstrCore;
                 uint32_t iArg;
-                if (!pInstr->Core.fDirty)
+                if (!pInstr->FnCore.fDirty)
                 {
 #ifdef KMK_CC_STRICT
                     uint32_t uCrcBefore = 0;
                     uint32_t uCrcAfter = 0;
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pInstr->apszArgs[iArg]);
 #endif
 
-                    pchDst = pInstr->Core.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->Core.pszFuncName);
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName);
 
 #ifdef KMK_CC_STRICT
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, pInstr->apszArgs[iArg]);
                     KMK_CC_ASSERT(uCrcBefore == uCrcAfter);
@@ -1737,92 +2214,92 @@ static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrC
                 }
                 else
                 {
-                    char **papszShadowArgs = xmalloc((pInstr->Core.cArgs * 2 + 1) * sizeof(papszShadowArgs[0]));
-                    char **papszArgs = &papszShadowArgs[pInstr->Core.cArgs];
+                    char **papszShadowArgs = xmalloc((pInstr->FnCore.cArgs * 2 + 1) * sizeof(papszShadowArgs[0]));
+                    char **papszArgs = &papszShadowArgs[pInstr->FnCore.cArgs];
 
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     papszArgs[iArg] = NULL;
                     while (iArg-- > 0)
                         papszArgs[iArg] = papszShadowArgs[iArg] = xstrdup(pInstr->apszArgs[iArg]);
 
-                    pchDst = pInstr->Core.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->Core.pszFuncName);
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName);
 
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         free(papszShadowArgs[iArg]);
                     free(papszShadowArgs);
                 }
 
-                pInstrCore = pInstr->Core.pNext;
+                pInstrCore = pInstr->FnCore.pNext;
                 break;
             }
 
             case kKmkCcExpInstr_DynamicFunction:
             {
                 PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)pInstrCore;
-                char           **papszArgsShadow = xmalloc( (pInstr->Core.cArgs * 2 + 1) * sizeof(char *));
-                char           **papszArgs = &papszArgsShadow[pInstr->Core.cArgs];
+                char           **papszArgsShadow = xmalloc( (pInstr->FnCore.cArgs * 2 + 1) * sizeof(char *));
+                char           **papszArgs = &papszArgsShadow[pInstr->FnCore.cArgs];
                 uint32_t         iArg;
 
-                if (!pInstr->Core.fDirty)
+                if (!pInstr->FnCore.fDirty)
                 {
 #ifdef KMK_CC_STRICT
                     uint32_t    uCrcBefore = 0;
                     uint32_t    uCrcAfter = 0;
 #endif
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     papszArgs[iArg] = NULL;
                     while (iArg-- > 0)
                     {
                         char *pszArg;
-                        if (!pInstr->aArgs[iArg].fPlain)
-                            pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.SubProg, NULL);
+                        if (pInstr->aArgs[iArg].fSubprog)
+                            pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL);
                         else
-                            pszArg = (char *)pInstr->aArgs[iArg].u.Plain.pszArg;
+                            pszArg = (char *)pInstr->aArgs[iArg].u.Plain.psz;
                         papszArgsShadow[iArg] = pszArg;
                         papszArgs[iArg]       = pszArg;
 #ifdef KMK_CC_STRICT
                         uCrcBefore = kmk_cc_debug_string_hash(uCrcBefore, pszArg);
 #endif
                     }
-                    pchDst = pInstr->Core.pfnFunction(pchDst, papszArgs, pInstr->Core.pszFuncName);
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
 
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                     {
 #ifdef KMK_CC_STRICT
                         KMK_CC_ASSERT(papszArgsShadow[iArg] == papszArgs[iArg]);
                         uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]);
 #endif
-                        if (!pInstr->aArgs[iArg].fPlain)
+                        if (pInstr->aArgs[iArg].fSubprog)
                             free(papszArgsShadow[iArg]);
                     }
                     KMK_CC_ASSERT(uCrcBefore == uCrcAfter);
                 }
                 else
                 {
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     papszArgs[iArg] = NULL;
                     while (iArg-- > 0)
                     {
                         char *pszArg;
-                        if (!pInstr->aArgs[iArg].fPlain)
-                            pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.SubProg, NULL);
+                        if (pInstr->aArgs[iArg].fSubprog)
+                            pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.Subprog, NULL);
                         else
-                            pszArg = xstrdup(pInstr->aArgs[iArg].u.Plain.pszArg);
+                            pszArg = xstrdup(pInstr->aArgs[iArg].u.Plain.psz);
                         papszArgsShadow[iArg] = pszArg;
                         papszArgs[iArg]       = pszArg;
                     }
 
-                    pchDst = pInstr->Core.pfnFunction(pchDst, papszArgs, pInstr->Core.pszFuncName);
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
 
-                    iArg = pInstr->Core.cArgs;
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         free(papszArgsShadow[iArg]);
                 }
                 free(papszArgsShadow);
 
-                pInstrCore = pInstr->Core.pNext;
+                pInstrCore = pInstr->FnCore.pNext;
                 break;
             }
 
@@ -1862,10 +2339,10 @@ void kmk_cc_exp_stats_update(PKMKCCEXPSTATS pStats, uint32_t cchResult)
 
 
 /**
- * Execute a string expansion sub-program, outputting to a new heap buffer.
+ * Execute a string expansion subprogram, outputting to a new heap buffer.
  *
  * @returns Pointer to the output buffer (hand to free when done).
- * @param   pSubProg          The sub-program to execute.
+ * @param   pSubProg          The subprogram to execute.
  * @param   pcchResult        Where to return the size of the result. Optional.
  */
 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcchResult)
@@ -1878,7 +2355,7 @@ static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t
 
     /*
      * Temporarily replace the variable buffer while executing the instruction
-     * stream for this sub program.
+     * stream for this subprogram.
      */
     pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf,
                                                pSubProg->Stats.cchAvg ? pSubProg->Stats.cchAvg + 32 : 256);
@@ -1937,11 +2414,107 @@ static char *kmk_exec_expand_prog_to_var_buf(PKMKCCEXPPROG pProg, char *pchDst)
 
 
 /**
+ * Expands a variable into a variable buffer using its expandprog.
+ *
+ * @returns The new variable buffer position.
+ * @param   pVar        Pointer to the variable.  Must have a program.
+ * @param   pchDst      Pointer to the current variable buffer position.
+ */
+char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst)
+{
+    KMK_CC_ASSERT(pVar->expandprog);
+    KMK_CC_ASSERT(pVar->expandprog->uInputHash == kmk_cc_debug_string_hash(0, pVar->value));
+    return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst);
+}
+
+
+
+
+
+/*
+ *
+ * Makefile evaluation programs.
+ * Makefile evaluation programs.
+ * Makefile evaluation programs.
+ *
+ */
+/*#define KMK_CC_EVAL_ENABLE*/
+
+
+/**
+ * Compiles a variable direct evaluation as is, setting v->evalprog on success.
+ *
+ * @returns Pointer to the program on success, NULL if no program was created.
+ * @param   pVar        Pointer to the variable.
+ */
+struct kmk_cc_evalprog   *kmk_cc_compile_variable_for_eval(struct variable *pVar)
+{
+    return NULL;
+}
+
+
+/**
+ * Compiles a makefile for
+ *
+ * @returns Pointer to the program on success, NULL if no program was created.
+ * @param   pVar        Pointer to the variable.
+ */
+struct kmk_cc_evalprog   *kmk_cc_compile_file_for_eval(FILE *pFile, const char *pszFilename)
+{
+#ifdef KMK_CC_EVAL_ENABLE
+    /*
+     * Read the entire file into a zero terminate memory buffer.
+     */
+    size_t      cchContent = 0;
+    char       *pszContent = NULL;
+    struct stat st;
+    if (!fstat(fileno(pFile), &st))
+    {
+        if (   st.st_size > (off_t)16*1024*1024
+            && st.st_size < 0)
+            fatal(NULL, _("Makefile too large to compile: %ld bytes (%#lx) - max 16MB"), (long)st.st_size, (long)st.st_size);
+        cchContent = (size_t)st.st_size;
+        pszContent = (char *)xmalloc(cchContent + 1);
+
+        cchContent = fread(pszContent, 1, cchContent, pFile);
+        if (ferror(pFile))
+            fatal(NULL, _("Read error: %s"), strerror(errno));
+    }
+    else
+    {
+        size_t cbAllocated = 2048;
+        do
+        {
+            cbAllocated *= 2;
+            if (cbAllocated > 16*1024*1024)
+                fatal(NULL, _("Makefile too large to compile: max 16MB"));
+            pszContent = (char *)xrealloc(pszContent, cbAllocated);
+            cchContent += fread(&pszContent[cchContent], 1, cbAllocated - 1 - cchContent, pFile);
+            if (ferror(pFile))
+                fatal(NULL, _("Read error: %s"), strerror(errno));
+        } while (!feof(pFile));
+    }
+    pszContent[cchContent] = '\0';
+
+    /*
+     * Call common function to do the compilation.
+     */
+    //kmk_cc_eval_compile_common()
+
+    free(pszContent);
+    return NULL;
+#else
+    return NULL;
+#endif
+}
+
+
+/**
  * Equivalent of eval_buffer, only it's using the evalprog of the variable.
  *
  * @param   pVar        Pointer to the variable. Must have a program.
  */
-void kmk_exec_evalval(struct variable *pVar)
+void kmk_exec_eval_variable(struct variable *pVar)
 {
     KMK_CC_ASSERT(pVar->evalprog);
     assert(0);
@@ -1949,20 +2522,27 @@ void kmk_exec_evalval(struct variable *pVar)
 
 
 /**
- * Expands a variable into a variable buffer using its expandprog.
+ * Worker for eval_makefile.
  *
- * @returns The new variable buffer position.
- * @param   pVar        Pointer to the variable.  Must have a program.
- * @param   pchDst      Pointer to the current variable buffer position.
+ * @param   pEvalProg   The program pointer.
  */
-char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst)
+void kmk_exec_eval_file(struct kmk_cc_evalprog *pEvalProg)
 {
-    KMK_CC_ASSERT(pVar->expandprog);
-    KMK_CC_ASSERT(pVar->expandprog->uInputHash == kmk_cc_debug_string_hash(0, pVar->value));
-    return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst);
+    KMK_CC_ASSERT(pEvalProg);
+    assert(0);
 }
 
 
+
+/*
+ *
+ * Program destruction hooks.
+ * Program destruction hooks.
+ * Program destruction hooks.
+ *
+ */
+
+
 /**
  * Called when a variable with expandprog or/and evalprog changes.
  *
@@ -2023,5 +2603,10 @@ void  kmk_cc_variable_deleted(struct variable *pVar)
 }
 
 
+
+
+
+
+
 #endif /* CONFIG_WITH_COMPILER */
 
diff --git a/src/kmk/kmk_cc_exec.h b/src/kmk/kmk_cc_exec.h
index 846d90f..dfa92a0 100644
--- a/src/kmk/kmk_cc_exec.h
+++ b/src/kmk/kmk_cc_exec.h
@@ -1,4 +1,4 @@
-/* $Id: kmk_cc_exec.h 2773 2015-02-03 12:59:54Z bird $ */
+/* $Id: kmk_cc_exec.h 2788 2015-09-06 15:43:10Z bird $ */
 /** @file
  * kmk_cc - Make "Compiler".
  */
@@ -27,16 +27,19 @@
 #define ___kmk_cc_and_exech
 #ifdef CONFIG_WITH_COMPILER
 
+#include <stdio.h>
 
 
 void  kmk_cc_init(void);
 void  kmk_cc_print_stats(void);
 
 struct variable;
-extern struct kmk_cc_evalprog   *kmk_cc_compile_variable_for_eval(struct variable *pVar);
 extern struct kmk_cc_expandprog *kmk_cc_compile_variable_for_expand(struct variable *pVar);
+extern struct kmk_cc_evalprog   *kmk_cc_compile_variable_for_eval(struct variable *pVar);
+extern struct kmk_cc_evalprog   *kmk_cc_compile_file_for_eval(FILE *pFile, const char *pszFilename);
 extern char *kmk_exec_expand_to_var_buf(struct variable *pVar, char *pchDst);
-extern void kmk_exec_evalval(struct variable *pVar);
+extern void kmk_exec_eval_file(struct kmk_cc_evalprog *pProg);
+extern void kmk_exec_eval_variable(struct variable *pVar);
 extern void kmk_cc_variable_changed(struct variable *pVar);
 extern void kmk_cc_variable_deleted(struct variable *pVar);
 
diff --git a/src/kmk/main.c b/src/kmk/main.c
index a748da4..b3c46bb 100644
--- a/src/kmk/main.c
+++ b/src/kmk/main.c
@@ -3841,11 +3841,7 @@ print_stats ()
   when = time ((time_t *) 0);
   printf (_("\n# Make statistics, printed on %s"), ctime (&when));
 
-  print_variable_stats ();
-  print_file_stats ();
-# ifdef KMK
-  print_kbuild_define_stats ();
-# endif
+  /* Aallocators: */
 # ifndef CONFIG_WITH_STRCACHE2
   strcache_print_stats ("#");
 # else
@@ -3856,6 +3852,16 @@ print_stats ()
 # endif
   print_heap_stats ();
 
+  /* Make stuff: */
+  print_variable_stats ();
+  print_file_stats ();
+# ifdef KMK
+  print_kbuild_define_stats ();
+# endif
+# ifdef CONFIG_WITH_COMPILER
+  kmk_cc_print_stats ();
+# endif
+
   when = time ((time_t *) 0);
   printf (_("\n# Finished Make statistics on %s\n"), ctime (&when));
 }
diff --git a/src/kmk/read.c b/src/kmk/read.c
index 86a3544..ef1fb4e 100644
--- a/src/kmk/read.c
+++ b/src/kmk/read.c
@@ -497,6 +497,28 @@ eval_makefile (const char *filename, int flags)
   do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file,
                           f_append, 0);
 
+#ifdef CONFIG_WITH_COMPILER
+  /* Execute compiled version if repeatedly evaluating this file.
+     ASSUMES file content is unmodified since compilation. */
+  deps->file->eval_count++;
+  if (   deps->file->evalprog
+      || (   deps->file->eval_count == 3
+          && (deps->file->evalprog = kmk_cc_compile_file_for_eval (ebuf.fp, filename)) != NULL) )
+    {
+      curfile = reading_file;
+      reading_file = &ebuf.floc;
+
+      kmk_exec_eval_file (deps->file->evalprog);
+
+      reading_file = curfile;
+      fclose (ebuf.fp);
+      alloca (0);
+      return 1;
+    }
+#elif defined (CONFIG_WITH_MAKE_STATS)
+  deps->file->eval_count++;
+#endif
+
 #ifdef KMK
   /* Buffer the entire file or at least 256KB (footer.kmk) of it. */
   {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-virtualbox/kbuild.git



More information about the Pkg-virtualbox-commits mailing list