Index: trunk/src/kmk/kbuild-read.c
===================================================================
--- trunk/src/kmk/kbuild-read.c	(revision 2548)
+++ trunk/src/kmk/kbuild-read.c	(revision 2549)
@@ -76,9 +76,18 @@
     /** The kind of define. */
     enum kBuildDef              enmKind;
-    /** Pointer to the element below us on the stack. */
-    struct kbuild_eval_data    *pDown;
-
     /** The bare name of the define. */
     char                       *pszName;
+    /** The file location where this define was declared. */
+    struct floc                 FileLoc;
+
+    /** Pointer to the next element in the global list. */
+    struct kbuild_eval_data    *pGlobalNext;
+    /** Pointer to the element below us on the stack. */
+    struct kbuild_eval_data    *pStackDown;
+
+    /** The variable set associated with this define. */
+    struct variable_set_list   *pVariables;
+    /** The saved current variable set, for restoring in kBuild-endef. */
+    struct variable_set_list   *pVariablesSaved;
 
     /** The parent name, NULL if none. */
@@ -86,13 +95,57 @@
     /** The inheritance method. */
     enum kBuildExtendBy         enmExtendBy;
+    /** Pointer to the parent. Resolved lazily, so it can be NULL even if we have
+     *  a parent. */
+    struct kbuild_eval_data    *pParent;
 
     /** The template, NULL if none. Only applicable to targets. */
     char                       *pszTemplate;
-
-    /** The variable prefix*/
+    /** Pointer to the template. Resolved lazily, so it can be NULL even if we have
+     *  a parent. */
+    struct kbuild_eval_data    *pTemplate;
+
+    /** The variable prefix.  */
     char                       *pszVarPrefix;
     /** The length of the variable prefix. */
     size_t                      cchVarPrefix;
 };
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+/** Linked list (LIFO) of kBuild defines.
+ * @todo use a hash! */
+struct kbuild_eval_data *g_pHeadKbDefs = NULL;
+/** Stack of kBuild defines. */
+struct kbuild_eval_data *g_pTopKbDef = NULL;
+
+
+struct variable_set *
+get_top_kbuild_variable_set(void)
+{
+    struct kbuild_eval_data *pTop = g_pTopKbDef;
+    assert(pTop != NULL);
+    return pTop->pVariables->set;
+}
+
+
+char *
+kbuild_prefix_variable(const char *pszName, unsigned int *pcchName)
+{
+    struct kbuild_eval_data *pTop = g_pTopKbDef;
+    char        *pszPrefixed;
+    unsigned int cchPrefixed;
+
+    assert(pTop != NULL);
+
+    cchPrefixed = pTop->cchVarPrefix + *pcchName;
+    pszPrefixed = xmalloc(cchPrefixed + 1);
+    memcpy(pszPrefixed, pTop->pszVarPrefix, pTop->cchVarPrefix);
+    memcpy(&pszPrefixed[pTop->cchVarPrefix], pszName, *pcchName);
+    pszPrefixed[cchPrefixed] = '\0';
+    *pcchName = cchPrefixed;
+    return pszPrefixed;
+}
 
 
@@ -112,4 +165,64 @@
 }
 
+static char *
+allocate_expanded_next_token(const char **ppszCursor, const char *pszEos, unsigned int *pcchToken, int fStrip)
+{
+    unsigned int cchToken;
+    char *pszToken = find_next_token_eos(ppszCursor, pszEos, &cchToken);
+    if (pszToken)
+    {
+        pszToken = allocated_variable_expand_2(pszToken, cchToken, &cchToken);
+        if (pszToken)
+        {
+            if (fStrip)
+            {
+                unsigned int off = 0;
+                while (MY_IS_BLANK(pszToken[off]))
+                    off++;
+                if (off)
+                {
+                    cchToken -= off;
+                    memmove(pszToken, &pszToken[off], cchToken + 1);
+                }
+
+                while (cchToken > 0 && MY_IS_BLANK(pszToken[cchToken - 1]))
+                    pszToken[--cchToken] = '\0';
+            }
+
+            assert(cchToken == strlen(pszToken));
+            if (pcchToken)
+                *pcchToken = cchToken;
+        }
+    }
+    return pszToken;
+}
+
+static struct kbuild_eval_data *
+eval_kbuild_resolve_parent(struct kbuild_eval_data *pData)
+{
+    if (   !pData->pParent
+        && pData->pszParent)
+    {
+        struct kbuild_eval_data *pCur = g_pHeadKbDefs;
+        while (pCur)
+        {
+            if (   pCur->enmKind == pData->enmKind
+                && !strcmp(pCur->pszName, pData->pszParent))
+            {
+                if (    pCur->pszParent
+                    &&  (   pCur->pParent == pData
+                         || !strcmp(pCur->pszParent, pData->pszName)) )
+                    fatal(&pData->FileLoc, _("'%s' and '%s' are both trying to be each other children..."),
+                          pData->pszName, pCur->pszName);
+
+                pData->pParent = pCur;
+                pData->pVariables->next = pData->pVariables;
+                break;
+            }
+            pCur = pCur->pGlobalNext;
+        }
+    }
+    return pData->pParent;
+}
 
 static int
@@ -117,35 +230,55 @@
                         const char *pszLine, const char *pszEos, int fIgnoring, enum kBuildDef enmKind)
 {
-    unsigned int             cch;
-    char                    *psz;
+    unsigned int            cch;
+    unsigned int            cchName;
+    char                    ch;
+    char                   *psz;
+    const char             *pszPrefix;
     struct kbuild_eval_data *pData;
 
-    /*
-     * Create a new kBuild eval data item unless we're in ignore-mode.
-     */
     if (fIgnoring)
         return 0;
 
+    /*
+     * Create a new kBuild eval data item.
+     */
     pData = xmalloc(sizeof(*pData));
-    pData->enmKind      = enmKind;
-    pData->pszName      = NULL;
-    pData->pszParent    = NULL;
-    pData->enmExtendBy  = kBuildExtendBy_NoParent;
-    pData->pszTemplate  = NULL;
-    pData->pszVarPrefix = NULL;
-    pData->cchVarPrefix = 0;
-    pData->pDown        = *ppData;
-    *ppData             = pData;
+    pData->enmKind          = enmKind;
+    pData->pszName          = NULL;
+    pData->FileLoc          = *pFileLoc;
+
+    pData->pGlobalNext      = g_pHeadKbDefs;
+    g_pHeadKbDefs           = pData;
+
+    pData->pStackDown       = *ppData;
+    *ppData = g_pTopKbDef   = pData;
+    pData->pVariables       = create_new_variable_set();
+    pData->pVariablesSaved  = NULL;
+
+    pData->pszParent        = NULL;
+    pData->enmExtendBy      = kBuildExtendBy_NoParent;
+    pData->pParent          = NULL;
+
+    pData->pszTemplate      = NULL;
+    pData->pTemplate        = NULL;
+
+    pData->pszVarPrefix     = NULL;
+    pData->cchVarPrefix     = 0;
 
     /*
      * The first word is the name.
      */
-    pData->pszName = find_next_token_eos(&pszLine, pszEos, &cch);
-    if (!pData->pszName)
-    {
-        error(pFileLoc, _("The kBuild define requires a name"));
-        return 0;
-    }
-    pData->pszName = allocated_variable_expand_2(pData->pszName, cch, &cch);
+    pData->pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*strip*/);
+    if (!pData->pszName || !*pData->pszName)
+        fatal(pFileLoc, _("The kBuild define requires a name"));
+
+    psz = pData->pszName;
+    while ((ch = *psz++) != '\0')
+        if (!isgraph(ch))
+        {
+            error(pFileLoc, _("The 'kBuild-define-%s' name '%s' contains one or more invalid characters"),
+                  eval_kbuild_kind_to_string(enmKind), pData->pszName);
+            break;
+        }
 
     /*
@@ -160,7 +293,5 @@
             if (pData->pszParent != NULL)
                 fatal(pFileLoc, _("'extending' can only occure once"));
-            pData->pszParent = find_next_token_eos(&pszLine, pszEos, &cch);
-            if (pData->pszParent)
-                pData->pszParent = allocated_variable_expand_2(pData->pszParent, cch, &cch);
+            pData->pszParent = allocate_expanded_next_token(&pszLine, pszEos, &cch, 1 /*strip*/);
             if (!pData->pszParent || !*pData->pszParent)
                 fatal(pFileLoc, _("'extending' requires a parent name"));
@@ -187,13 +318,13 @@
             }
         }
-        else if (   WORD_IS(psz, cch, "using")
-                 && enmKind == kBuildDef_Tool)
+        else if (WORD_IS(psz, cch, "using"))
         {
             /* Template directive. */
-            if (pData->pszTemplate != NULL )
+            if (enmKind != kBuildDef_Tool)
+                fatal(pFileLoc, _("'using <template>' can only be used with 'kBuild-define-target'"));
+            if (pData->pszTemplate != NULL)
                 fatal(pFileLoc, _("'using' can only occure once"));
-            pData->pszTemplate = find_next_token_eos(&pszLine, pszEos, &cch);
-            if (pData->pszTemplate)
-                pData->pszTemplate = allocated_variable_expand_2(pData->pszTemplate, cch, &cch);
+
+            pData->pszTemplate = allocate_expanded_next_token(&pszLine, pszEos, &cch, 1 /*fStrip*/);
             if (!pData->pszTemplate || !*pData->pszTemplate)
                 fatal(pFileLoc, _("'using' requires a template name"));
@@ -209,7 +340,27 @@
      * Calc the variable prefix.
      */
-
-    /** @todo continue here...  */
-
+    switch (enmKind)
+    {
+        case kBuildDef_Target:      pszPrefix = ""; break;
+        case kBuildDef_Template:    pszPrefix = "TEMPLATE_"; break;
+        case kBuildDef_Tool:        pszPrefix = "TOOL_"; break;
+        case kBuildDef_Sdk:         pszPrefix = "SDK_"; break;
+        case kBuildDef_Unit:        pszPrefix = "UNIT_"; break;
+        default:
+            fatal(pFileLoc, _("enmKind=%d"), enmKind);
+            return -1;
+    }
+    cch = strlen(pszPrefix);
+    pData->cchVarPrefix = cch + cchName;
+    pData->pszVarPrefix = xmalloc(pData->cchVarPrefix + 1);
+    memcpy(pData->pszVarPrefix, pszPrefix, cch);
+    memcpy(&pData->pszVarPrefix[cch], pData->pszName, cchName);
+
+    /*
+     * Try resolve the parent and change the current variable set.
+     */
+    eval_kbuild_resolve_parent(pData);
+    pData->pVariablesSaved = current_variable_set_list;
+    current_variable_set_list = pData->pVariables;
 
     return 0;
@@ -242,9 +393,6 @@
      */
     if (pData->enmKind != enmKind)
-    {
         error(pFileLoc, _("'kBuild-endef-%s' does not match 'kBuild-define-%s %s'"),
               eval_kbuild_kind_to_string(enmKind), eval_kbuild_kind_to_string(pData->enmKind), pData->pszName);
-        return 0;
-    }
 
     /*
@@ -252,8 +400,7 @@
      * It should match the name given to the kBuild-define.
      */
-    pszName = find_next_token_eos(&pszLine, pszEos, &cchName);
+    pszName = allocate_expanded_next_token(&pszLine, pszEos, &cchName, 1 /*fStrip*/);
     if (pszName)
     {
-        pszName = allocated_variable_expand_2(pszName, cchName, &cchName);
         if (strcmp(pszName, pData->pszName))
             error(pFileLoc, _("'kBuild-endef-%s %s' does not match 'kBuild-define-%s %s'"),
@@ -266,10 +413,9 @@
      * Pop a define off the stack.
      */
-    *ppData = pData->pDown;
-    free(pData->pszName);
-    free(pData->pszParent);
-    free(pData->pszTemplate);
-    free(pData->pszVarPrefix);
-    free(pData);
+    assert(pData == g_pTopKbDef);
+    *ppData = g_pTopKbDef  = pData->pStackDown;
+    pData->pStackDown      = NULL;
+    current_variable_set_list = pData->pVariablesSaved;
+    pData->pVariablesSaved = NULL;
 
     return 0;
@@ -326,2 +472,40 @@
 }
 
+void print_kbuild_data_base(void)
+{
+    struct kbuild_eval_data *pCur;
+
+    puts(_("\n# kBuild defines"));
+
+    for (pCur = g_pHeadKbDefs; pCur; pCur = pCur->pGlobalNext)
+    {
+        printf("\nkBuild-define-%s %s",
+               eval_kbuild_kind_to_string(pCur->enmKind), pCur->pszName);
+        if (pCur->pszParent)
+        {
+            printf(" extending %s", pCur->pszParent);
+            switch (pCur->enmExtendBy)
+            {
+                case kBuildExtendBy_Overriding: break;
+                case kBuildExtendBy_Appending:  printf(" by appending"); break;
+                case kBuildExtendBy_Prepending: printf(" by prepending"); break;
+                default:                        printf(" by ?!?");
+            }
+        }
+        if (pCur->pszTemplate)
+            printf(" using %s", pCur->pszTemplate);
+        putchar('\n');
+
+        print_variable_set(pCur->pVariables->set, "");
+
+        printf("kBuild-endef-%s  %s\n",
+               eval_kbuild_kind_to_string(pCur->enmKind), pCur->pszName);
+    }
+    /** @todo hash stats. */
+}
+
+void print_kbuild_define_stats(void)
+{
+    /* later when hashing stuff */
+}
+
Index: trunk/src/kmk/kbuild.h
===================================================================
--- trunk/src/kmk/kbuild.h	(revision 2548)
+++ trunk/src/kmk/kbuild.h	(revision 2549)
@@ -40,4 +40,7 @@
 
 struct kbuild_eval_data;
+extern struct kbuild_eval_data *g_pTopKbDef;
+struct variable_set *get_top_kbuild_variable_set(void);
+char *kbuild_prefix_variable(const char *pszName, unsigned int *pcchName);
 
 int eval_kbuild_define(struct kbuild_eval_data **kdata, const struct floc *flocp,
@@ -46,4 +49,7 @@
                       const char *word, unsigned int wlen, const char *line, const char *eos, int ignoring);
 
+void print_kbuild_data_base(void);
+void print_kbuild_define_stats(void);
+
 #endif
 
Index: trunk/src/kmk/main.c
===================================================================
--- trunk/src/kmk/main.c	(revision 2548)
+++ trunk/src/kmk/main.c	(revision 2549)
@@ -3726,4 +3726,7 @@
   print_file_data_base ();
   print_vpath_data_base ();
+#ifdef KMK
+  print_kbuild_data_base ();
+#endif
 #ifndef CONFIG_WITH_STRCACHE2
   strcache_print_stats ("#");
@@ -3750,4 +3753,7 @@
   print_variable_stats ();
   print_file_stats ();
+# ifdef KMK
+  print_kbuild_define_stats ();
+# endif
 # ifndef CONFIG_WITH_STRCACHE2
   strcache_print_stats ("#");
Index: trunk/src/kmk/testcase-kBuild-define.kmk
===================================================================
--- trunk/src/kmk/testcase-kBuild-define.kmk	(revision 2548)
+++ trunk/src/kmk/testcase-kBuild-define.kmk	(revision 2549)
@@ -29,8 +29,10 @@
 kBuild-define-target MyTarget
 
-TEMPLATE = MyTemplate
-SOURCES = MySourceFile.c
+_TEMPLATE = MyTemplate
+_SOURCES  = MySourceFile.c
 
 kBuild-endef-target  MyTarget
+$(if "$(MyTarget_TEMPLATE)" == "MyTemplate",,$(error MyTarget's _TEMPLATE wasn't set correctly in the global space))
+$(if "$(MyTarget_SOURCES)" == "MySourceFile.c",,$(error MyTarget's _TEMPLATE wasn't set correctly in the global space))
 
 
@@ -38,8 +40,9 @@
 kBuild-define-target $(call INDIRECT_NAME, 2)
 
-TEMPLATE = MyTemplate2
-SOURCES = MySourceFile2.c
+local _TEMPLATE = MyTemplate2
+_SOURCES  = MySourceFile2.c
 
 kBuild-endef-target  $(call INDIRECT_NAME, 2)
+$(if "$(_TEMPLATE)" == "",,$(error _TEMPLATE has leaked out into the global space))
 
 
@@ -47,5 +50,5 @@
 
 all_recursive:
-	$(ECHO) "kBuild-define-xxxx works fine"
+	#$(ECHO) "kBuild-define-xxxx works fine"
 
 
Index: trunk/src/kmk/variable.c
===================================================================
--- trunk/src/kmk/variable.c	(revision 2548)
+++ trunk/src/kmk/variable.c	(revision 2549)
@@ -215,6 +215,35 @@
   struct variable var_key;
 
+#ifndef KMK
   if (set == NULL)
     set = &global_variable_set;
+#else
+  if (set == NULL)
+    {
+      /* underscore prefixed variables are automatically local in
+         kBuild-define-* scopes.  They also get a global definition with
+         the current scope prefix. */
+      if (g_pTopKbDef && length > 0 && name[0] == '_')
+        {
+          char         *prefixed_nm;
+          unsigned int  prefixed_nm_len;
+
+          set = get_top_kbuild_variable_set();
+          v = define_variable_in_set(name, length, value, value_len,
+                                     1 /* duplicate_value */,
+                                     origin, recursive, set, flocp);
+
+          prefixed_nm_len = length;
+          prefixed_nm = kbuild_prefix_variable(name, &prefixed_nm_len);
+          define_variable_in_set(prefixed_nm, prefixed_nm_len,
+                                 value, value_len, duplicate_value,
+                                 origin, recursive, &global_variable_set,
+                                 flocp);
+          free(prefixed_nm);
+          return v;
+        }
+      set = &global_variable_set;
+    }
+#endif
 
 #ifndef CONFIG_WITH_STRCACHE2
