Index: trunk/src/kmk/file.c
===================================================================
--- trunk/src/kmk/file.c	(revision 2786)
+++ trunk/src/kmk/file.c	(revision 2788)
@@ -1217,4 +1217,16 @@
   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.")
Index: trunk/src/kmk/filedef.h
===================================================================
--- trunk/src/kmk/filedef.h	(revision 2786)
+++ trunk/src/kmk/filedef.h	(revision 2788)
@@ -72,4 +72,8 @@
     /* Pointer to next target of an explicit multi target rule. */
     struct file *multi_next;
+#endif
+
+#ifdef CONFIG_WITH_COMPILER
+    struct kmk_cc_evalprog *evalprog; /* Pointer to evalval/evalctx "program". */
 #endif
 
@@ -120,4 +124,7 @@
                                   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
   };
 
Index: trunk/src/kmk/function.c
===================================================================
--- trunk/src/kmk/function.c	(revision 2786)
+++ trunk/src/kmk/function.c	(revision 2788)
@@ -2070,5 +2070,5 @@
         {
           install_variable_buffer (&buf, &len); /* Really necessary? */
-          kmk_exec_evalval (v);
+          kmk_exec_eval_variable (v);
           restore_variable_buffer (buf, len);
         }
Index: trunk/src/kmk/kmk_cc_exec.c
===================================================================
--- trunk/src/kmk/kmk_cc_exec.c	(revision 2786)
+++ trunk/src/kmk/kmk_cc_exec.c	(revision 2788)
@@ -26,7 +26,7 @@
 
 
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
 #include "make.h"
 
@@ -43,7 +43,8 @@
 #include <assert.h>
 
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
 /** @def KMK_CC_WITH_STATS
  * Enables the collection of extra statistics. */
@@ -75,7 +76,48 @@
 
 
-/*******************************************************************************
-*   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,4 +137,8 @@
 } KMKCCBLOCK;
 typedef KMKCCBLOCK *PKMKCCBLOCK;
+
+
+/** @name String Expansion
+ * @{*/
 
 /**
@@ -131,17 +177,18 @@
     /** 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
 {
@@ -151,5 +198,46 @@
     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);
 
 /**
@@ -186,9 +274,9 @@
     /** 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;
@@ -226,5 +314,5 @@
     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;
@@ -252,5 +340,5 @@
 {
     /** 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
@@ -260,6 +348,7 @@
 } 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)
 
 /**
@@ -269,31 +358,14 @@
 {
     /** 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)
 
 /**
@@ -331,8 +403,425 @@
 typedef KMKCCEXPPROG *PKMKCCEXPPROG;
 
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
+/** @} */
+
+
+/** @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)
+
+/**
+ * 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;
@@ -349,7 +838,7 @@
 
 
-/*******************************************************************************
-*   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);
@@ -373,5 +862,5 @@
     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"
@@ -735,6 +1224,5 @@
 }
 
-
-/*
+   /*
  *
  * The string expansion compiler.
@@ -826,9 +1314,9 @@
     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);
 
     /*
@@ -865,5 +1353,5 @@
         }
 
-        pInstr->aArgs[iArg].fPlain = !fDollar;
+        pInstr->aArgs[iArg].fSubprog = fDollar;
         if (fDollar)
         {
@@ -871,5 +1359,5 @@
             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;
@@ -878,5 +1366,6 @@
         {
             /* 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++;
@@ -892,5 +1381,5 @@
      */
     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;
 }
@@ -926,9 +1415,9 @@
     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);
 
     /*
@@ -976,5 +1465,5 @@
      */
     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);
 }
 
@@ -999,5 +1488,5 @@
     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);
@@ -1410,5 +1899,5 @@
 
 /**
- * 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
@@ -1422,5 +1911,5 @@
  * @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)
@@ -1465,5 +1954,5 @@
 
         /*
-         * 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)
@@ -1493,16 +1982,4 @@
 
 /**
- * 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.
  *
@@ -1621,5 +2098,5 @@
                 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;
@@ -1717,18 +2194,18 @@
                 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]);
@@ -1738,15 +2215,15 @@
                 else
                 {
-                    char **papszShadowArgs = xmalloc((pInstr->Core.cArgs * 2 + 1) * sizeof(papszShadowArgs[0]));
-                    char **papszArgs = &papszShadowArgs[pInstr->Core.cArgs];
-
-                    iArg = pInstr->Core.cArgs;
+                    char **papszShadowArgs = xmalloc((pInstr->FnCore.cArgs * 2 + 1) * sizeof(papszShadowArgs[0]));
+                    char **papszArgs = &papszShadowArgs[pInstr->FnCore.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);
-
-                    iArg = pInstr->Core.cArgs;
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->FnCore.pszFuncName);
+
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         free(papszShadowArgs[iArg]);
@@ -1754,5 +2231,5 @@
                 }
 
-                pInstrCore = pInstr->Core.pNext;
+                pInstrCore = pInstr->FnCore.pNext;
                 break;
             }
@@ -1761,9 +2238,9 @@
             {
                 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
@@ -1771,13 +2248,13 @@
                     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;
@@ -1786,7 +2263,7 @@
 #endif
                     }
-                    pchDst = pInstr->Core.pfnFunction(pchDst, papszArgs, pInstr->Core.pszFuncName);
-
-                    iArg = pInstr->Core.cArgs;
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
+
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                     {
@@ -1795,5 +2272,5 @@
                         uCrcAfter = kmk_cc_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]);
 #endif
-                        if (!pInstr->aArgs[iArg].fPlain)
+                        if (pInstr->aArgs[iArg].fSubprog)
                             free(papszArgsShadow[iArg]);
                     }
@@ -1802,20 +2279,20 @@
                 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);
-
-                    iArg = pInstr->Core.cArgs;
+                    pchDst = pInstr->FnCore.pfnFunction(pchDst, papszArgs, pInstr->FnCore.pszFuncName);
+
+                    iArg = pInstr->FnCore.cArgs;
                     while (iArg-- > 0)
                         free(papszArgsShadow[iArg]);
@@ -1823,5 +2300,5 @@
                 free(papszArgsShadow);
 
-                pInstrCore = pInstr->Core.pNext;
+                pInstrCore = pInstr->FnCore.pNext;
                 break;
             }
@@ -1863,8 +2340,8 @@
 
 /**
- * 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.
  */
@@ -1879,5 +2356,5 @@
     /*
      * 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,
@@ -1938,16 +2415,4 @@
 
 /**
- * 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)
-{
-    KMK_CC_ASSERT(pVar->evalprog);
-    assert(0);
-}
-
-
-/**
  * Expands a variable into a variable buffer using its expandprog.
  *
@@ -1962,4 +2427,119 @@
     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_eval_variable(struct variable *pVar)
+{
+    KMK_CC_ASSERT(pVar->evalprog);
+    assert(0);
+}
+
+
+/**
+ * Worker for eval_makefile.
+ *
+ * @param   pEvalProg   The program pointer.
+ */
+void kmk_exec_eval_file(struct kmk_cc_evalprog *pEvalProg)
+{
+    KMK_CC_ASSERT(pEvalProg);
+    assert(0);
+}
+
+
+
+/*
+ *
+ * Program destruction hooks.
+ * Program destruction hooks.
+ * Program destruction hooks.
+ *
+ */
 
 
@@ -2024,4 +2604,9 @@
 
 
+
+
+
+
+
 #endif /* CONFIG_WITH_COMPILER */
 
Index: trunk/src/kmk/kmk_cc_exec.h
===================================================================
--- trunk/src/kmk/kmk_cc_exec.h	(revision 2786)
+++ trunk/src/kmk/kmk_cc_exec.h	(revision 2788)
@@ -28,4 +28,5 @@
 #ifdef CONFIG_WITH_COMPILER
 
+#include <stdio.h>
 
 
@@ -34,8 +35,10 @@
 
 struct variable;
+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_expandprog *kmk_cc_compile_variable_for_expand(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);
Index: trunk/src/kmk/main.c
===================================================================
--- trunk/src/kmk/main.c	(revision 2786)
+++ trunk/src/kmk/main.c	(revision 2788)
@@ -3849,9 +3849,5 @@
   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 ("#");
@@ -3863,4 +3859,14 @@
 # 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);
Index: trunk/src/kmk/read.c
===================================================================
--- trunk/src/kmk/read.c	(revision 2786)
+++ trunk/src/kmk/read.c	(revision 2788)
@@ -500,4 +500,26 @@
   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
