Index: trunk/src/kmk/dep.h
===================================================================
--- trunk/src/kmk/dep.h	(revision 1826)
+++ trunk/src/kmk/dep.h	(revision 1827)
@@ -76,5 +76,9 @@
 void free_ns_chain (struct nameseq *n);
 struct dep *read_all_makefiles (const char **makefiles);
+#ifndef CONFIG_WITH_VALUE_LENGTH
 int eval_buffer (char *buffer);
+#else
+int eval_buffer (char *buffer, char *eos);
+#endif
 int update_goal_chain (struct dep *goals);
 void uniquize_deps (struct dep *);
Index: trunk/src/kmk/expand.c
===================================================================
--- trunk/src/kmk/expand.c	(revision 1826)
+++ trunk/src/kmk/expand.c	(revision 1827)
@@ -108,5 +108,10 @@
 
 char *
+#ifndef CONFIG_WITH_VALUE_LENGTH
 recursively_expand_for_file (struct variable *v, struct file *file)
+#else
+recursively_expand_for_file (struct variable *v, struct file *file,
+                             unsigned int *value_lenp)
+#endif
 {
   char *value;
@@ -149,8 +154,19 @@
 
   v->expanding = 1;
+#ifndef CONFIG_WITH_VALUE_LENGTH
   if (v->append)
     value = allocated_variable_append (v);
   else
     value = allocated_variable_expand (v->value);
+#else  /* CONFIG_WITH_VALUE_LENGTH */
+  if (!v->append)
+    value = allocated_variable_expand_2 (v->value, v->value_length, value_lenp);
+  else
+    {
+      value = allocated_variable_append (v);
+      if (value_lenp)
+        *value_lenp = strlen (value);
+    }
+#endif /* CONFIG_WITH_VALUE_LENGTH */
   v->expanding = 0;
 
@@ -187,13 +203,13 @@
 
 #ifdef CONFIG_WITH_VALUE_LENGTH
+  assert ((unsigned int)v->value_length == strlen (v->value));
   if (!v->recursive)
-    {
-      assert (v->value_length == strlen (v->value));
-      o = variable_buffer_output (o, v->value, v->value_length);
-    }
+    o = variable_buffer_output (o, v->value, v->value_length);
   else
    {
-     value = recursively_expand (v);
-     o = variable_buffer_output (o, value, strlen (value));
+     unsigned int value_len;
+
+     value = recursively_expand_for_file (v, NULL, &value_len);
+     o = variable_buffer_output (o, value, value_len);
      free (value);
    }
@@ -211,4 +227,5 @@
 
 
+#ifndef CONFIG_WITH_VALUE_LENGTH /* Only using variable_expand_string_2! */
 /* Scan STRING for variable references and expansion-function calls.  Only
    LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
@@ -228,7 +245,4 @@
   char *o;
   unsigned int line_offset;
-#ifdef CONFIG_WITH_VALUE_LENGTH
-  const char *eos;
-#endif
 
   if (!line)
@@ -239,27 +253,7 @@
   if (length == 0)
     {
-#ifdef KMK /* this is a bug fix. The 2 vs 1 thing is the strlen + 1 in the loop below. */
-      variable_buffer_output (o, "\0", 2);
-      return (variable_buffer + line_offset);
-#else
       variable_buffer_output (o, "", 1);
       return (variable_buffer);
-#endif
-    }
-
-#ifdef CONFIG_WITH_VALUE_LENGTH
-  /* Simple first, 50% of the kBuild calls to this function does
-     not need any expansion at all. Should be worth a special case. */
-  if (length < 0)
-    length = strlen (string);
-  p1 = (const char *)memchr (string, '$', length);
-  if (p1 == 0)
-    {
-      o = variable_buffer_output (o, string, length);
-      variable_buffer_output (o, "\0", 2);
-      return (variable_buffer + line_offset);
-    }
-  eos = string + length;
-#endif /* CONFIG_WITH_VALUE_LENGTH */
+    }
 
   /* If we want a subset of the string, allocate a temporary buffer for it.
@@ -270,8 +264,4 @@
       memcpy(abuf, string, length);
       abuf[length] = '\0';
-#ifdef CONFIG_WITH_VALUE_LENGTH
-      p1 += abuf - string;
-      eos += abuf - string;
-#endif /* CONFIG_WITH_VALUE_LENGTH */
       string = abuf;
     }
@@ -284,7 +274,5 @@
 	 at the next $ or the end of the input.  */
 
-#ifndef CONFIG_WITH_VALUE_LENGTH
       p1 = strchr (p, '$');
-#endif
 
       o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1);
@@ -327,9 +315,5 @@
 	       If so, expand it before expanding the entire reference.  */
 
-#ifndef CONFIG_WITH_VALUE_LENGTH
 	    end = strchr (beg, closeparen);
-#else
-	    end = memchr (beg, closeparen, eos - beg);
-#endif
 	    if (end == 0)
               /* Unterminated variable reference.  */
@@ -470,7 +454,4 @@
       else
 	++p;
-#ifdef CONFIG_WITH_VALUE_LENGTH
-      p1 = memchr (p, '$', eos - p);
-#endif
     }
 
@@ -481,20 +462,22 @@
   return (variable_buffer + line_offset);
 }
-#ifdef CONFIG_WITH_VALUE_LENGTH
-
-
-/* Same as variable_expand_string except that the pointer at EOL will
-   point to the end of the returned string. */
+
+#else /* CONFIG_WITH_VALUE_LENGTH */
+/* Scan STRING for variable references and expansion-function calls.  Only
+   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until
+   a null byte is found.
+
+   Write the results to LINE, which must point into `variable_buffer'.  If
+   LINE is NULL, start at the beginning of the buffer.
+   Return a pointer to LINE, or to the beginning of the buffer if LINE is
+   NULL. Set EOLP to point to the string terminator.
+ */
 char *
-variable_expand_string_2 (char *line, const char *string, long length, char **eol)
+variable_expand_string_2 (char *line, const char *string, long length, char **eolp)
 {
   struct variable *v;
-  const char *p, *p1;
-  char *abuf = NULL;
+  const char *p, *p1, *eos;
   char *o;
   unsigned int line_offset;
-#ifdef CONFIG_WITH_VALUE_LENGTH
-  const char *eos;
-#endif
 
   if (!line)
@@ -503,20 +486,18 @@
   line_offset = line - variable_buffer;
 
-  if (length == 0)
-    {
-      o = variable_buffer_output (o, "\0", 2);
-      *eol = o - 2;
-#ifdef KMK /* this is a bug fix. */
-      return (variable_buffer + line_offset);
-#else
-      return (variable_buffer);
-#endif
-    }
-
-#ifdef CONFIG_WITH_VALUE_LENGTH
-  /* Simple first, 50% of the kBuild calls to this function does
-     not need any expansion at all. Should be worth a special case. */
   if (length < 0)
     length = strlen (string);
+
+  /* Simple 1: Emptry string. */
+
+  if (length == 0)
+    {
+      o = variable_buffer_output (o, "\0", 2);
+      *eolp = o - 2;
+      return (variable_buffer + line_offset);
+    }
+
+  /* Simple 2: Nothing to expand. ~50% if the kBuild calls. */
+
   p1 = (const char *)memchr (string, '$', length);
   if (p1 == 0)
@@ -524,24 +505,10 @@
       o = variable_buffer_output (o, string, length);
       o = variable_buffer_output (o, "\0", 2);
-      *eol = o - 2;
+      *eolp = o - 2;
       return (variable_buffer + line_offset);
     }
-  eos = string + length;
-#endif /* CONFIG_WITH_VALUE_LENGTH */
-
-  /* If we want a subset of the string, allocate a temporary buffer for it.
-     Most of the functions we use here don't work with length limits.  */
-  if (length > 0 && string[length] != '\0')
-    {
-      abuf = xmalloc(length+1);
-      memcpy(abuf, string, length);
-      abuf[length] = '\0';
-#ifdef CONFIG_WITH_VALUE_LENGTH
-      p1 += abuf - string;
-      eos += abuf - string;
-#endif
-      string = abuf;
-    }
+
   p = string;
+  eos = p + length;
 
   while (1)
@@ -551,10 +518,5 @@
 	 at the next $ or the end of the input.  */
 
-#ifndef CONFIG_WITH_VALUE_LENGTH
-      p1 = strchr (p, '$');
-#endif
-
-      /*o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1); - why +1 ? */
-      o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p));
+      o = variable_buffer_output (o, p, p1 != 0 ? (p1 - p) : (eos - p));
 
       if (p1 == 0)
@@ -585,5 +547,5 @@
 	    op = o;
 	    begp = p;
-	    if (handle_function (&op, &begp))
+	    if (handle_function (&op, &begp, eos))
 	      {
 		o = op;
@@ -595,9 +557,5 @@
 	       If so, expand it before expanding the entire reference.  */
 
-#ifndef CONFIG_WITH_VALUE_LENGTH
-	    end = strchr (beg, closeparen);
-#else
 	    end = memchr (beg, closeparen, eos - beg);
-#endif
 	    if (end == 0)
               /* Unterminated variable reference.  */
@@ -609,5 +567,5 @@
 		   Count parens or braces until it is matched.  */
 		int count = 0;
-		for (p = beg; *p != '\0'; ++p)
+		for (p = beg; p < eos; ++p)
 		  {
 		    if (*p == openparen)
@@ -621,7 +579,14 @@
 		if (count < 0)
 		  {
-		    abeg = expand_argument (beg, p); /* Expand the name.  */
-		    beg = abeg;
-		    end = strchr (beg, '\0');
+                    unsigned int len;
+                    char saved;
+
+                     /* Expand the name.  */
+                    saved = *p;
+                    *(char *)p = '\0'; /* XXX: proove that this is safe! */
+                    abeg = allocated_variable_expand_2 (beg, p - beg, &len);
+                    beg = abeg;
+                    end = beg + len;
+                    *(char *)p = saved;
 		  }
 	      }
@@ -721,8 +686,9 @@
 
 	case '\0':
-	  break;
+          assert (p == eos);
+          break;
 
 	default:
-	  if (isblank ((unsigned char)p[-1]))
+	  if (isblank ((unsigned char)p[-1])) /* XXX: This looks incorrect, previous is '$' */
 	    break;
 
@@ -734,18 +700,11 @@
 	}
 
-      if (*p == '\0')
+      if (++p >= eos)
 	break;
-      else
-	++p;
-#ifdef CONFIG_WITH_VALUE_LENGTH
       p1 = memchr (p, '$', eos - p);
-#endif
-    }
-
-  if (abuf)
-    free (abuf);
+    }
 
   o = variable_buffer_output (o, "\0", 2); /* KMK: compensate for the strlen + 1 that was removed above. */
-  *eol = o - 2;
+  *eolp = o - 2;
   return (variable_buffer + line_offset);
 }
@@ -761,5 +720,17 @@
 variable_expand (const char *line)
 {
+#ifndef CONFIG_WITH_VALUE_LENGTH
   return variable_expand_string(NULL, line, (long)-1);
+#else
+  char *s;
+
+  /* this function is abused a lot like this: variable_expand(""). */
+  if (!*line)
+    {
+      s = variable_buffer_output (initialize_variable_output (), "\0", 2);
+      return s - 2;
+    }
+  return variable_expand_string_2 (NULL, line, (long)-1, &s);
+#endif
 }
 
@@ -779,6 +750,13 @@
     return xstrdup("");
 
+#ifndef CONFIG_WITH_VALUE_LENGTH
   if (!end || *end == '\0')
     return allocated_variable_expand (str);
+#else
+  if (!end)
+      return allocated_variable_expand_2 (str, ~0U, NULL);
+  if (*end == '\0')
+    return allocated_variable_expand_2 (str, end - str, NULL);
+#endif
 
 #ifdef CONFIG_WITH_OPTIMIZATION_HACKS
@@ -786,5 +764,9 @@
     const char saved_char = *end;
     *(char *)end = '\0';
+# ifndef CONFIG_WITH_VALUE_LENGTH
     tmp = allocated_variable_expand ((char *)str);
+# else
+    tmp = allocated_variable_expand_2 ((char *)str, end - str, NULL);
+# endif
     *(char *)end = saved_char;
     return tmp;
@@ -795,5 +777,9 @@
   tmp[end - str] = '\0';
 
+# ifndef CONFIG_WITH_VALUE_LENGTH
   return allocated_variable_expand (tmp);
+# else
+  return allocated_variable_expand_2 (tmp, end - str, NULL);
+# endif
 #endif
 }
@@ -839,7 +825,8 @@
   struct variable_set_list *save;
   const struct floc *reading_file_saved;
+  char *eol;
 
   if (file == 0)
-    return variable_expand_string (o, line, (long)-1);
+    return variable_expand_string_2 (o, line, (long)-1, &eol);
 
   save = current_variable_set_list;
@@ -850,5 +837,5 @@
   else
     reading_file = 0;
-  result = variable_expand_string (o, line, (long)-1);
+  result = variable_expand_string_2 (o, line, (long)-1, &eol);
   current_variable_set_list = save;
   reading_file = reading_file_saved;
@@ -893,5 +880,5 @@
     buf = variable_buffer_output (buf, " ", 1);
 #ifdef CONFIG_WITH_VALUE_LENGTH
-  assert (v->value_length == strlen (v->value));
+  assert ((unsigned int)v->value_length == strlen (v->value)); /* FIXME */
 #endif
 
@@ -1026,5 +1013,5 @@
 char *
 allocated_variable_expand_2 (const char *line, unsigned int length,
-                             unsigned int *value_len)
+                             unsigned int *value_lenp)
 {
   char *value;
@@ -1032,15 +1019,11 @@
   unsigned int olen = variable_buffer_length;
   long len = length == ~0U ? -1L : (long)length;
+  char *eol;
 
   variable_buffer = 0;
 
-  if (!value_len)
-    value = variable_expand_string (NULL, line, len);
-  else
-    {
-      char *eol;
-      value = variable_expand_string_2 (NULL, line, len, &eol);
-      *value_len = eol - value;
-    }
+  value = variable_expand_string_2 (NULL, line, len, &eol);
+  if (value_lenp)
+    *value_lenp = eol - value;
 
   variable_buffer = obuf;
Index: trunk/src/kmk/function.c
===================================================================
--- trunk/src/kmk/function.c	(revision 1826)
+++ trunk/src/kmk/function.c	(revision 1827)
@@ -323,37 +323,97 @@
 
 
-#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
 /* The maximum length of a function, once reached there is
    it can't be function and we can skip the hash lookup drop out. */
 
-# ifdef KMK
-#  define MAX_FUNCTION_LENGTH 12
-# else
-#  define MAX_FUNCTION_LENGTH 10
-# endif
-#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+# define MAX_FUNCTION_LENGTH 12
+# define MIN_FUNCTION_LENGTH 2
+
+/* char map containing the valid function name characters. */
+static char func_char_map[256];
+
+/* Do the hash table lookup. */
+
+__inline static const struct function_table_entry *
+lookup_function_in_hash_tab (const char *s, unsigned char len)
+{
+    struct function_table_entry function_table_entry_key;
+    function_table_entry_key.name = s;
+    function_table_entry_key.len = len;
+
+    return hash_find_item (&function_table, &function_table_entry_key);
+}
 
 /* Look up a function by name.  */
 
-#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
-__inline
-#endif /* CONFIG_WITH_OPTIMIZATION_HACKS */
+__inline static const struct function_table_entry *
+lookup_function (const char *s, unsigned int len)
+{
+  unsigned char ch;
+# if 0 /* insane loop unroll */
+
+  if (len > MAX_FUNCTION_LENGTH)
+      len = MAX_FUNCTION_LENGTH + 1;
+
+#  define X(idx) \
+        if (!func_char_map[ch = s[idx]]) \
+          { \
+            if (isblank (ch)) \
+              return lookup_function_in_hash_tab (s, idx); \
+            return 0; \
+          }
+#  define Z(idx) \
+        return lookup_function_in_hash_tab (s, idx);
+
+  switch (len)
+    {
+      default:
+        assert (0);
+      case  0: return 0;
+      case  1: return 0;
+      case  2: X(0); X(1); Z(2);
+      case  3: X(0); X(1); X(2); Z(3);
+      case  4: X(0); X(1); X(2); X(3); Z(4);
+      case  5: X(0); X(1); X(2); X(3); X(4); Z(5);
+      case  6: X(0); X(1); X(2); X(3); X(4); X(5); Z(6);
+      case  7: X(0); X(1); X(2); X(3); X(4); X(5); X(6); Z(7);
+      case  8: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); Z(8);
+      case  9: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); Z(9);
+      case 10: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); Z(10);
+      case 11: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); Z(11);
+      case 12: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); Z(12);
+      case 13: X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); X(8); X(9); X(10); X(11); X(12);
+        if ((ch = s[12]) == '\0' || isblank (ch))
+          return lookup_function_in_hash_tab (s, 12);
+        return 0;
+    }
+#  undef Z
+#  undef X
+
+# else   /* normal loop */
+  const char *e = s;
+  if (len > MAX_FUNCTION_LENGTH)
+      len = MAX_FUNCTION_LENGTH;
+  while (func_char_map[ch = *e])
+    {
+      if (!len--)
+        return 0;
+      e++;
+    }
+  if (ch == '\0' || isblank ((unsigned char) ch))
+    return lookup_function_in_hash_tab (s, e - s);
+  return 0;
+# endif /* normal loop */
+}
+
+#else  /* original code */
+/* Look up a function by name.  */
+
 static const struct function_table_entry *
 lookup_function (const char *s)
 {
   const char *e = s;
-#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
-  int left = MAX_FUNCTION_LENGTH;
-  int ch;
-  while (((ch = *e) >= 'a' && ch <='z') || ch == '-')
-    {
-      if (!left--)
-        return 0;
-      e++;
-    }
-#else
   while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-'))
     e++;
-#endif
   if (*e == '\0' || isblank ((unsigned char) *e))
     {
@@ -366,4 +426,5 @@
   return 0;
 }
+#endif /* original code */
 
 
@@ -1512,5 +1573,9 @@
   install_variable_buffer (&buf, &len);
 
+#ifndef CONFIG_WITH_VALUE_LENGTH
   eval_buffer (argv[0]);
+#else
+  eval_buffer (argv[0], strchr (argv[0], '\0'));
+#endif
 
   restore_variable_buffer (buf, len);
@@ -1536,5 +1601,5 @@
   push_new_variable_scope ();
 
-  eval_buffer (argv[0]);
+  eval_buffer (argv[0], strchr (argv[0], '\0'));
 
   pop_variable_scope ();
@@ -1565,7 +1630,6 @@
 
       off = o - variable_buffer;
-      o = variable_buffer_output (o, v->value, v->value_length + 1);
+      variable_buffer_output (o, v->value, v->value_length + 1);
       o = variable_buffer + off;
-      assert (!o[v->value_length]);
 
       /* Eval the value.  Pop the current variable buffer setting so that the
@@ -1579,5 +1643,6 @@
         reading_file = &v->fileinfo;
 
-      eval_buffer (o);
+      assert (!o[v->value_length]);
+      eval_buffer (o, o + v->value_length);
 
       reading_file = reading_file_saved;
@@ -1601,5 +1666,7 @@
 #ifdef CONFIG_WITH_VALUE_LENGTH
     o = variable_buffer_output (o, v->value,
-                                v->value_length >= 0 ? v->value_length : strlen(v->value));
+                                v->value_length >= 0
+                                ? (unsigned int)v->value_length /* FIXME */
+                                : strlen(v->value));
 #else
     o = variable_buffer_output (o, v->value, strlen(v->value));
@@ -3061,5 +3128,5 @@
                   const char *src = comp;
                   const char *end = strchr (comp, PATH_SEPARATOR_CHAR);
-                  size_t comp_len = end ? end - comp : strlen (comp);
+                  size_t comp_len = end ? (size_t)(end - comp) : strlen (comp);
                   if (!comp_len)
                     {
@@ -4197,6 +4264,8 @@
 }
 
-int
-handle_function (char **op, const char **stringp) /* bird split it up */
+
+int  /* bird split it up */
+#ifndef CONFIG_WITH_VALUE_LENGTH
+handle_function (char **op, const char **stringp)
 {
   const struct function_table_entry *entry_p = lookup_function (*stringp + 1);
@@ -4205,4 +4274,14 @@
   return handle_function2 (entry_p, op, stringp);
 }
+#else  /* CONFIG_WITH_VALUE_LENGTH */
+handle_function (char **op, const char **stringp, const char *eol)
+{
+  const char *fname = *stringp + 1;
+  const struct function_table_entry *entry_p = lookup_function (fname, eol - fname);
+  if (!entry_p)
+    return 0;
+  return handle_function2 (entry_p, op, stringp);
+}
+#endif /* CONFIG_WITH_VALUE_LENGTH */
 
 
@@ -4246,5 +4325,9 @@
   /* Are we invoking a builtin function?  */
 
+#ifndef CONFIG_WITH_VALUE_LENGTH
   entry_p = lookup_function (fname);
+#else
+  entry_p = lookup_function (fname, cp - fname + 1);
+#endif
   if (entry_p)
     {
@@ -4295,6 +4378,10 @@
       char num[11];
 
+#ifndef CONFIG_WITH_VALUE_LENGTH
       sprintf (num, "%d", i);
       define_variable (num, strlen (num), "", o_automatic, 0);
+#else
+      define_variable (num, sprintf (num, "%d", i), "", o_automatic, 0);
+#endif
     }
 
@@ -4324,4 +4411,5 @@
     {
       const struct floc *reading_file_saved = reading_file;
+      char *eos;
 
       if (!strcmp (funcname, "evalcall"))
@@ -4331,5 +4419,5 @@
 
           size_t off = o - variable_buffer;
-          o = variable_buffer_output (o, v->value, v->value_length + 1);
+          eos = variable_buffer_output (o, v->value, v->value_length + 1) - 1;
           o = variable_buffer + off;
           if (v->fileinfo.filenm)
@@ -4341,10 +4429,10 @@
 
           v->exp_count = EXP_COUNT_MAX;
-          o = variable_expand_string (o, body, flen+3);
+          o = variable_expand_string_2 (o, body, flen+3, &eos);
           v->exp_count = 0;
         }
 
       install_variable_buffer (&buf, &len);
-      eval_buffer (o);
+      eval_buffer (o, eos);
       restore_variable_buffer (buf, len);
       reading_file = reading_file_saved;
@@ -4367,9 +4455,16 @@
   hash_load (&function_table, function_table_init,
 	     FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry));
-#ifdef CONFIG_WITH_OPTIMIZATION_HACKS
+#if defined (CONFIG_WITH_OPTIMIZATION_HACKS) || defined (CONFIG_WITH_VALUE_LENGTH)
   {
-    unsigned i;
+    unsigned int i;
+    for (i = 'a'; i <= 'z'; i++)
+      func_char_map[i] = 1;
+    func_char_map[(unsigned int)'-'] = 1;
+
     for (i = 0; i < FUNCTION_TABLE_ENTRIES; i++)
+      {
         assert (function_table_init[i].len <= MAX_FUNCTION_LENGTH);
+        assert (function_table_init[i].len >= MIN_FUNCTION_LENGTH);
+      }
   }
 #endif
Index: trunk/src/kmk/kbuild.c
===================================================================
--- trunk/src/kmk/kbuild.c	(revision 1826)
+++ trunk/src/kmk/kbuild.c	(revision 1827)
@@ -1714,5 +1714,5 @@
     char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
     char *pszSavedVarBuf;
-    unsigned cchSavedVarBuf;
+    unsigned cchSavedVarBuf, cchVal;
     size_t cch;
     struct kbuild_sdks Sdks;
@@ -1893,8 +1893,8 @@
     */
     pVar = kbuild_get_recursive_variable("def_target_source_rule");
-    pszVal = allocated_variable_expand_2(pVar->value, pVar->value_length, NULL);
+    pszVal = allocated_variable_expand_2(pVar->value, pVar->value_length, &cchVal); /** @todo we can use the variable buffer here. */
 
     install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
-    eval_buffer(pszVal);
+    eval_buffer(pszVal, pszVal + cchVal);
     restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
 
@@ -1903,5 +1903,5 @@
     kbuild_put_sdks(&Sdks);
     (void)pszFuncName;
-    return variable_buffer_output(o, "", 1);
+    return variable_buffer_output(o, "", 1); /** @todo not right. */
 }
 
Index: trunk/src/kmk/make.h
===================================================================
--- trunk/src/kmk/make.h	(revision 1826)
+++ trunk/src/kmk/make.h	(revision 1827)
@@ -287,5 +287,5 @@
 #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0)
 
-#if defined(__GNUC__) || defined(ENUM_BITFIELDS)
+#if (defined(__GNUC__) || defined(ENUM_BITFIELDS)) && !defined(NO_ENUM_BITFIELDS)
 # define ENUM_BITFIELD(bits)    :bits
 #else
Index: trunk/src/kmk/read.c
===================================================================
--- trunk/src/kmk/read.c	(revision 1826)
+++ trunk/src/kmk/read.c	(revision 1827)
@@ -469,5 +469,9 @@
 
 int
+#ifndef CONFIG_WITH_VALUE_LENGTH
 eval_buffer (char *buffer)
+#else
+eval_buffer (char *buffer, char *eos)
+#endif
 {
   struct ebuffer ebuf;
@@ -479,10 +483,13 @@
   /* Evaluate the buffer */
 
+#ifndef CONFIG_WITH_VALUE_LENGTH
   ebuf.size = strlen (buffer);
+#else
+  ebuf.size = eos - buffer;
+  ebuf.eol = eos;
+  assert(strchr(buffer, '\0') == eos);
+#endif
   ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer;
   ebuf.fp = NULL;
-#ifdef CONFIG_WITH_VALUE_LENGTH
-  ebuf.eol = ebuf.buffer + ebuf.size;
-#endif
 
   ebuf.floc = *reading_file;
@@ -1954,6 +1961,6 @@
       if ((size_t)buf_pos & 7)
         buf_pos = variable_buffer_output (buf_pos, "\0\0\0\0\0\0\0\0",
-                                          8 - (size_t)buf_pos & 7);
-      s2 = variable_expand_string (buf_pos, s2, l);
+                                          8 - ((size_t)buf_pos & 7));
+      s2 = variable_expand_string_2 (buf_pos, s2, l, &buf_pos);
 #endif
 #ifdef CONFIG_WITH_SET_CONDITIONALS
Index: trunk/src/kmk/variable.c
===================================================================
--- trunk/src/kmk/variable.c	(revision 1826)
+++ trunk/src/kmk/variable.c	(revision 1827)
@@ -132,35 +132,35 @@
     {
         default:
-        case 32: //UPDATE_HASH(uvar_end[-16]);
+        case 32: /*UPDATE_HASH(uvar_end[-16]);*/
         case 31: UPDATE_HASH(uvar_end[-15]);
-        case 30: //UPDATE_HASH(uvar_end[-14]);
+        case 30: /*UPDATE_HASH(uvar_end[-14]);*/
         case 29: UPDATE_HASH(uvar_end[-13]);
-        case 28: //UPDATE_HASH(uvar_end[-12]);
+        case 28: /*UPDATE_HASH(uvar_end[-12]);*/
         case 27: UPDATE_HASH(uvar_end[-11]);
-        case 26: //UPDATE_HASH(uvar_end[-10]);
+        case 26: /*UPDATE_HASH(uvar_end[-10]);*/
         case 25: UPDATE_HASH(uvar_end[-9]);
-        case 24: //UPDATE_HASH(uvar[15]);
+        case 24: /*UPDATE_HASH(uvar[15]);*/
         case 23: UPDATE_HASH(uvar[14]);
-        case 22: //UPDATE_HASH(uvar[13]);
+        case 22: /*UPDATE_HASH(uvar[13]);*/
         case 21: UPDATE_HASH(uvar[12]);
-        case 20: //UPDATE_HASH(uvar[11]);
+        case 20: /*UPDATE_HASH(uvar[11]);*/
         case 19: UPDATE_HASH(uvar[10]);
-        case 18: //UPDATE_HASH(uvar[9]);
+        case 18: /*UPDATE_HASH(uvar[9]);*/
         case 17: UPDATE_HASH(uvar[8]);
-        case 16: //UPDATE_HASH(uvar_end[-8]);
+        case 16: /*UPDATE_HASH(uvar_end[-8]);*/
         case 15: UPDATE_HASH(uvar_end[-7]);
-        case 14: //UPDATE_HASH(uvar_end[-6]);
+        case 14: /*UPDATE_HASH(uvar_end[-6]);*/
         case 13: UPDATE_HASH(uvar_end[-5]);
-        case 12: //UPDATE_HASH(uvar_end[-4]);
+        case 12: /*UPDATE_HASH(uvar_end[-4]);*/
         case 11: UPDATE_HASH(uvar_end[-3]);
-        case 10: //UPDATE_HASH(uvar_end[-2]);
+        case 10: /*UPDATE_HASH(uvar_end[-2]);*/
         case 9:  UPDATE_HASH(uvar_end[-1]);
-        case 8:  //UPDATE_HASH(uvar[7]);
+        case 8:  /*UPDATE_HASH(uvar[7]);*/
         case 7:  UPDATE_HASH(uvar[6]);
-        case 6:  //UPDATE_HASH(uvar[5]);
+        case 6:  /*UPDATE_HASH(uvar[5]);*/
         case 5:  UPDATE_HASH(uvar[4]);
-        case 4:  //UPDATE_HASH(uvar[3]);
+        case 4:  /*UPDATE_HASH(uvar[3]);*/
         case 3:  UPDATE_HASH(uvar[2]);
-        case 2:  //UPDATE_HASH(uvar[1]);
+        case 2:  /*UPDATE_HASH(uvar[1]);*/
         case 1:  UPDATE_HASH(uvar[0]);
         case 0:
@@ -193,68 +193,68 @@
 #if 0 /* seems to be a waste of time. */
         case 97: UPDATE_HASH(uvar_end[-77]);
-        case 96: //UPDATE_HASH(uvar_end[-76]);
-        case 95: //UPDATE_HASH(uvar_end[-75]);
-        case 94: //UPDATE_HASH(uvar_end[-74]);
+        case 96: /*UPDATE_HASH(uvar_end[-76]);*/
+        case 95: /*UPDATE_HASH(uvar_end[-75]);*/
+        case 94: /*UPDATE_HASH(uvar_end[-74]);*/
         case 93: UPDATE_HASH(uvar_end[-73]);
-        case 92: //UPDATE_HASH(uvar_end[-72]);
-        case 91: //UPDATE_HASH(uvar_end[-71]);
-        case 90: //UPDATE_HASH(uvar_end[-70]);
+        case 92: /*UPDATE_HASH(uvar_end[-72]);*/
+        case 91: /*UPDATE_HASH(uvar_end[-71]);*/
+        case 90: /*UPDATE_HASH(uvar_end[-70]);*/
         case 89: UPDATE_HASH(uvar_end[-69]);
-        case 88: //UPDATE_HASH(uvar_end[-68]);
-        case 87: //UPDATE_HASH(uvar_end[-67]);
-        case 86: //UPDATE_HASH(uvar_end[-66]);
+        case 88: /*UPDATE_HASH(uvar_end[-68]);*/
+        case 87: /*UPDATE_HASH(uvar_end[-67]);*/
+        case 86: /*UPDATE_HASH(uvar_end[-66]);*/
         case 85: UPDATE_HASH(uvar_end[-65]);
-        case 84: //UPDATE_HASH(uvar_end[-64]);
-        case 83: //UPDATE_HASH(uvar_end[-63]);
-        case 82: //UPDATE_HASH(uvar_end[-62]);
+        case 84: /*UPDATE_HASH(uvar_end[-64]);*/
+        case 83: /*UPDATE_HASH(uvar_end[-63]);*/
+        case 82: /*UPDATE_HASH(uvar_end[-62]);*/
         case 81: UPDATE_HASH(uvar_end[-61]);
-        case 80: //UPDATE_HASH(uvar_end[-60]);
-        case 79: //UPDATE_HASH(uvar_end[-59]);
-        case 78: //UPDATE_HASH(uvar_end[-58]);
+        case 80: /*UPDATE_HASH(uvar_end[-60]);*/
+        case 79: /*UPDATE_HASH(uvar_end[-59]);*/
+        case 78: /*UPDATE_HASH(uvar_end[-58]);*/
         case 77: UPDATE_HASH(uvar_end[-57]);
-        case 76: //UPDATE_HASH(uvar_end[-56]);
-        case 75: //UPDATE_HASH(uvar_end[-55]);
-        case 74: //UPDATE_HASH(uvar_end[-54]);
+        case 76: /*UPDATE_HASH(uvar_end[-56]);*/
+        case 75: /*UPDATE_HASH(uvar_end[-55]);*/
+        case 74: /*UPDATE_HASH(uvar_end[-54]);*/
         case 73: UPDATE_HASH(uvar_end[-53]);
-        case 72: //UPDATE_HASH(uvar_end[-52]);
-        case 71: //UPDATE_HASH(uvar_end[-51]);
-        case 70: //UPDATE_HASH(uvar_end[-50]);
+        case 72: /*UPDATE_HASH(uvar_end[-52]);*/
+        case 71: /*UPDATE_HASH(uvar_end[-51]);*/
+        case 70: /*UPDATE_HASH(uvar_end[-50]);*/
         case 69: UPDATE_HASH(uvar_end[-49]);
-        case 68: //UPDATE_HASH(uvar_end[-48]);
-        case 67: //UPDATE_HASH(uvar_end[-47]);
-        case 66: //UPDATE_HASH(uvar_end[-46]);
+        case 68: /*UPDATE_HASH(uvar_end[-48]);*/
+        case 67: /*UPDATE_HASH(uvar_end[-47]);*/
+        case 66: /*UPDATE_HASH(uvar_end[-46]);*/
         case 65: UPDATE_HASH(uvar_end[-49]);
-        case 64: //UPDATE_HASH(uvar_end[-48]);
-        case 63: //UPDATE_HASH(uvar_end[-47]);
-        case 62: //UPDATE_HASH(uvar_end[-46]);
+        case 64: /*UPDATE_HASH(uvar_end[-48]);*/
+        case 63: /*UPDATE_HASH(uvar_end[-47]);*/
+        case 62: /*UPDATE_HASH(uvar_end[-46]);*/
         case 61: UPDATE_HASH(uvar_end[-45]);
-        case 60: //UPDATE_HASH(uvar_end[-44]);
-        case 59: //UPDATE_HASH(uvar_end[-43]);
-        case 58: //UPDATE_HASH(uvar_end[-42]);
+        case 60: /*UPDATE_HASH(uvar_end[-44]);*/
+        case 59: /*UPDATE_HASH(uvar_end[-43]);*/
+        case 58: /*UPDATE_HASH(uvar_end[-42]);*/
         case 57: UPDATE_HASH(uvar_end[-41]);
-        case 56: //UPDATE_HASH(uvar_end[-40]);
-        case 55: //UPDATE_HASH(uvar_end[-39]);
-        case 54: //UPDATE_HASH(uvar_end[-38]);
+        case 56: /*UPDATE_HASH(uvar_end[-40]);*/
+        case 55: /*UPDATE_HASH(uvar_end[-39]);*/
+        case 54: /*UPDATE_HASH(uvar_end[-38]);*/
         case 53: UPDATE_HASH(uvar_end[-37]);
-        case 52: //UPDATE_HASH(uvar_end[-36]);
+        case 52: /*UPDATE_HASH(uvar_end[-36]);*/
         case 51: UPDATE_HASH(uvar_end[-35]);
-        case 50: //UPDATE_HASH(uvar_end[-34]);
+        case 50: /*UPDATE_HASH(uvar_end[-34]);*/
         case 49: UPDATE_HASH(uvar_end[-33]);
 #endif
-        case 48: //UPDATE_HASH(uvar_end[-32]);
+        case 48: /*UPDATE_HASH(uvar_end[-32]);*/
         case 47: UPDATE_HASH(uvar_end[-31]);
-        case 46: //UPDATE_HASH(uvar_end[-30]);
+        case 46: /*UPDATE_HASH(uvar_end[-30]);*/
         case 45: UPDATE_HASH(uvar_end[-29]);
-        case 44: //UPDATE_HASH(uvar_end[-28]);
+        case 44: /*UPDATE_HASH(uvar_end[-28]);*/
         case 43: UPDATE_HASH(uvar_end[-27]);
-        case 42: //UPDATE_HASH(uvar_end[-26]);
+        case 42: /*UPDATE_HASH(uvar_end[-26]);*/
         case 41: UPDATE_HASH(uvar_end[-25]);
-        case 40: //UPDATE_HASH(uvar_end[-24]);
+        case 40: /*UPDATE_HASH(uvar_end[-24]);*/
         case 39: UPDATE_HASH(uvar_end[-23]);
-        case 38: //UPDATE_HASH(uvar_end[-22]);
+        case 38: /*UPDATE_HASH(uvar_end[-22]);*/
         case 37: UPDATE_HASH(uvar_end[-21]);
-        case 36: //UPDATE_HASH(uvar_end[-20]);
+        case 36: /*UPDATE_HASH(uvar_end[-20]);*/
         case 35: UPDATE_HASH(uvar_end[-19]);
-        case 34: //UPDATE_HASH(uvar_end[-18]);
+        case 34: /*UPDATE_HASH(uvar_end[-18]);*/
         case 33: UPDATE_HASH(uvar_end[-17]);
 
@@ -1577,5 +1577,9 @@
 	    && v->origin != o_env && v->origin != o_env_override)
 	  {
+#ifndef CONFIG_WITH_VALUE_LENGTH
 	    char *value = recursively_expand_for_file (v, file);
+#else
+	    char *value = recursively_expand_for_file (v, file, NULL);
+#endif
 #ifdef WINDOWS32
 	    if (strcmp(v->name, "Path") == 0 ||
@@ -2193,5 +2197,5 @@
 
   vp = do_variable_definition_2 (flocp, v.name, v.value,
-                                 v.value_length != -1 ? v.value_length : ~0U,
+                                 v.value_length != -1 ? (unsigned int)v.value_length : ~0U, /* FIXME */
                                  0, NULL, origin, v.flavor, target_var);
 #endif
Index: trunk/src/kmk/variable.h
===================================================================
--- trunk/src/kmk/variable.h	(revision 1826)
+++ trunk/src/kmk/variable.h	(revision 1827)
@@ -142,11 +142,18 @@
 # define allocated_variable_expand(line) \
   allocated_variable_expand_2 (line, -1, NULL)
-char *allocated_variable_expand_2(const char *line, unsigned int length, unsigned int *value_len);
+char *allocated_variable_expand_2(const char *line, unsigned int length, unsigned int *value_lenp);
 #endif /* CONFIG_WITH_VALUE_LENGTH */
 char *expand_argument (const char *str, const char *end);
+#ifndef CONFIG_WITH_VALUE_LENGTH
 char *variable_expand_string (char *line, const char *string, long length);
-#ifdef CONFIG_WITH_VALUE_LENGTH
+#else  /* CONFIG_WITH_VALUE_LENGTH */
 char *variable_expand_string_2 (char *line, const char *string, long length, char **eol);
-#endif
+__inline static char *
+variable_expand_string (char *line, const char *string, long length)
+{
+    char *ignored;
+    return variable_expand_string_2 (line, string, length, &ignored);
+}
+#endif /* CONFIG_WITH_VALUE_LENGTH */
 void install_variable_buffer (char **bufp, unsigned int *lenp);
 void restore_variable_buffer (char *buf, unsigned int len);
@@ -157,5 +164,9 @@
 
 /* function.c */
+#ifndef CONFIG_WITH_VALUE_LENGTH
 int handle_function (char **op, const char **stringp);
+#else
+int handle_function (char **op, const char **stringp, const char *eol);
+#endif
 int pattern_matches (const char *pattern, const char *percent, const char *str);
 char *subst_expand (char *o, const char *text, const char *subst,
@@ -171,6 +182,12 @@
 
 /* expand.c */
+#ifndef CONFIG_WITH_VALUE_LENGTH
 char *recursively_expand_for_file (struct variable *v, struct file *file);
 #define recursively_expand(v)   recursively_expand_for_file (v, NULL)
+#else
+char *recursively_expand_for_file (struct variable *v, struct file *file,
+                                   unsigned int *value_lenp);
+#define recursively_expand(v)   recursively_expand_for_file (v, NULL, NULL)
+#endif
 
 /* variable.c */
