Index: trunk/src/kmk/kbuild.c
===================================================================
--- trunk/src/kmk/kbuild.c	(revision 1831)
+++ trunk/src/kmk/kbuild.c	(revision 1832)
@@ -51,4 +51,12 @@
 # define va_copy(dst, src) do {(dst) = (src);} while (0)
 #endif
+#ifdef _MSC_VER
+# define MY_INLINE  _inline static
+#elif defined(__GNUC__)
+# define MY_INLINE  static __inline__
+#else
+# define MY_INLINE  static
+#endif
+
 
 
@@ -418,5 +426,39 @@
 }
 
-
+/**
+ * Gets a variable that must exist.
+ * Will cause a fatal failure if the variable doesn't exist.
+ *
+ * @returns Pointer to the variable.
+ * @param   pszName     The variable name.
+ * @param   cchName     The name length.
+ */
+MY_INLINE struct variable *
+kbuild_get_variable_n(const char *pszName, size_t cchName)
+{
+#ifndef NDEBUG
+    int i;
+#endif
+    struct variable *pVar = lookup_variable(pszName, cchName);
+    if (!pVar)
+        fatal(NILF, _("variable `%.*s' isn't defined!"), (int)cchName, pszName);
+    if (pVar->recursive)
+        fatal(NILF, _("variable `%.*s' is defined as `recursive' instead of `simple'!"), (int)cchName, pszName);
+#ifndef NDEBUG
+    i = strlen(pVar->value);
+    if (i != pVar->value_length)
+    {
+        printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
+# ifdef _MSC_VER
+        __debugbreak();
+# endif
+        assert(0);
+    }
+#endif
+    return pVar;
+}
+
+
+#if 0 /* unused */
 /**
  * Gets a variable that must exist.
@@ -429,25 +471,7 @@
 kbuild_get_variable(const char *pszName)
 {
-#ifndef NDEBUG
-    int i;
-#endif
-    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
-    if (!pVar)
-        fatal(NILF, _("variable `%s' isn't defined!"), pszName);
-    if (pVar->recursive)
-        fatal(NILF, _("variable `%s' is defined as `recursive' instead of `simple'!"), pszName);
-#ifndef NDEBUG
-    i = strlen(pVar->value);
-    if (i != pVar->value_length)
-    {
-        printf("%d != %d %s\n", pVar->value_length, i, pVar->name);
-# ifdef _MSC_VER
-        __debugbreak();
-# endif
-        assert(0);
-    }
-#endif
-    return pVar;
-}
+    return kbuild_get_variable_n(pszName, strlen(pszName));
+}
+#endif
 
 
@@ -543,9 +567,10 @@
  * @returns Pointer to the variable. NULL if not found.
  * @param   pszName     The variable name.
+ * @param   cchName     The name length.
  */
-static struct variable *
-kbuild_lookup_variable(const char *pszName)
-{
-    struct variable *pVar = lookup_variable(pszName, strlen(pszName));
+MY_INLINE struct variable *
+kbuild_lookup_variable_n(const char *pszName, size_t cchName)
+{
+    struct variable *pVar = lookup_variable(pszName, cchName);
     if (pVar)
     {
@@ -570,4 +595,37 @@
 
 /**
+ * Looks up a variable.
+ * The value_length field is valid upon successful return.
+ *
+ * @returns Pointer to the variable. NULL if not found.
+ * @param   pszName     The variable name.
+ */
+MY_INLINE struct variable *
+kbuild_lookup_variable(const char *pszName)
+{
+    return kbuild_lookup_variable_n(pszName, strlen(pszName));
+}
+
+
+/**
+ * Looks up a variable and applies default a path to all relative paths.
+ * The value_length field is valid upon successful return.
+ *
+ * @returns Pointer to the variable. NULL if not found.
+ * @param   pDefPath    The default path.
+ * @param   pszName     The variable name.
+ * @param   cchName     The name length.
+ */
+MY_INLINE struct variable *
+kbuild_lookup_variable_defpath_n(struct variable *pDefPath, const char *pszName, size_t cchName)
+{
+    struct variable *pVar = kbuild_lookup_variable_n(pszName, cchName);
+    if (pVar && pDefPath)
+        kbuild_apply_defpath(pDefPath, &pVar->value, &pVar->value_length, &pVar->value_alloc_len, 1);
+    return pVar;
+}
+
+
+/**
  * Looks up a variable and applies default a path to all relative paths.
  * The value_length field is valid upon successful return.
@@ -577,5 +635,5 @@
  * @param   pszName     The variable name.
  */
-static struct variable *
+MY_INLINE struct variable *
 kbuild_lookup_variable_defpath(struct variable *pDefPath, const char *pszName)
 {
@@ -589,5 +647,5 @@
 /** Same as kbuild_lookup_variable except that a '%s' in the name string
  * will be substituted with the values of the variables in the va list. */
-static struct variable *
+struct variable *
 kbuild_lookup_variable_fmt_va(struct variable *pDefPath, size_t cchName, const char *pszNameFmt, va_list va)
 {
@@ -618,5 +676,5 @@
         assert(*pszFmt == '%');
     };
-    pszName = alloca(cchName);
+    pszName = alloca(cchName + 1);
 
     /* second pass format it. */
@@ -646,25 +704,24 @@
 
     if (pDefPath)
-        return kbuild_lookup_variable_defpath(pDefPath, pszName);
-    return kbuild_lookup_variable(pszName);
-}
-
-
-/** Helper for use with kbuild_lookup_variable_fmt. */
-#define ST(strconst) sizeof(strconst), strconst
+        return kbuild_lookup_variable_defpath_n(pDefPath, pszName, psz - pszName - 1);
+    return kbuild_lookup_variable_n(pszName, psz - pszName - 1);
+}
+
+
+/** Helper for passing a string constant to kbuild_lookup_variable_fmt or
+ *  kbuild_lookup_variable_NN. */
+#define ST(strconst) strconst, sizeof(strconst) - 1
+/** Helper for passing a variable to kbuild_lookup_variable_NN. */
+#define VT(var)      (var)->value_length, (var)->value
 
 
 /** Same as kbuild_lookup_variable except that a '%s' in the name string
  * will be substituted with the values of the variables in the ellipsis.  */
-#ifdef _MSC_VER
-_inline struct variable *
-#else
-static __inline__ struct variable *
-#endif
-kbuild_lookup_variable_fmt(struct variable *pDefPath, size_t cchNameFmt, const char *pszNameFmt, ...)
+MY_INLINE struct variable *
+kbuild_lookup_variable_fmt(struct variable *pDefPath, const char *pszNameFmt, size_t cchNameFmt, ...)
 {
     struct variable *pVar;
     va_list va;
-    va_start(va, pszNameFmt);
+    va_start(va, cchNameFmt);
     pVar = kbuild_lookup_variable_fmt_va(pDefPath, cchNameFmt, pszNameFmt, va);
     va_end(va);
@@ -680,48 +737,307 @@
                   struct variable *pTool, struct variable *pType,
                   struct variable *pBldTrg, struct variable *pBldTrgArch,
-                  const char *pszPropF1, const char *pszPropF2, const char *pszVarName)
+                  const char *pszPropF1, char cchPropF1,
+                  const char *pszPropF2, char cchPropF2,
+                  const char *pszVarName)
 {
     struct variable *pVar;
-    struct variable PropF1, PropF2;
-
-    PropF1.value = (char *)pszPropF1;
-    PropF1.value_length = strlen(pszPropF1);
-
-    PropF2.value = (char *)pszPropF2;
-    PropF2.value_length = strlen(pszPropF2);
-
-    if (    (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%%.%.%"),pTarget, pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%%.%"),  pTarget, pSource, pType, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%%"),    pTarget, pSource, pType, &PropF2))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%.%.%"), pTarget, pSource, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%.%"),   pTarget, pSource, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%_%"),     pTarget, pSource, &PropF2))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%.%.%"),  pSource, pType, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%.%"),    pSource, pType, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%"),      pSource, pType, &PropF2))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%.%.%"),   pSource, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%.%"),     pSource, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%"),       pSource, &PropF2))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%.%.%"),  pTarget, pType, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%.%"),    pTarget, pType, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%%"),      pTarget, pType, &PropF2))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%.%.%"),   pTarget, &PropF2, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%.%"),     pTarget, &PropF2, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%_%"),       pTarget, &PropF2))
-
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%%.%.%"),   pTool, pType, &PropF2, pBldTrg, pBldTrgArch)))
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%%.%"),     pTool, pType, &PropF2, pBldTrg)))
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%%"),       pTool, pType, &PropF2)))
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%.%.%"),    pTool, &PropF2, pBldTrg, pBldTrgArch)))
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%.%"),      pTool, &PropF2, pBldTrg)))
-        ||  (pTool && (pVar = kbuild_lookup_variable_fmt(NULL, ST("TOOL_%_%"),        pTool, &PropF2)))
-
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%%.%.%"),    pType, &PropF1, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%%.%"),      pType, &PropF1, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%%"),        pType, &PropF1))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%.%.%"),     &PropF1, pBldTrg, pBldTrgArch))
-        ||  (pVar = kbuild_lookup_variable_fmt(NULL, ST("%.%"),       &PropF1, pBldTrg))
-        ||  (pVar = kbuild_lookup_variable(pszPropF1))
-       )
+    size_t cchBuf;
+    char *pszBuf;
+    char *psz, *psz1, *psz2, *psz3, *psz4;
+
+    /* calc and allocate a too big name buffer. */
+    cchBuf = cchPropF2 + 1
+           + cchPropF1 + 1
+           + pTarget->value_length + 1
+           + pSource->value_length + 1
+           + (pTool ? pTool->value_length + 1 : 0)
+           + pType->value_length + 1
+           + pBldTrg->value_length + 1
+           + pBldTrgArch->value_length + 1;
+    pszBuf = xmalloc(cchBuf);
+
+#if 1
+# define my_memcpy(dst, src, len) \
+    do { \
+        if (len > 4) \
+            memcpy(dst, src, len); \
+        else \
+            switch (len) \
+            { \
+                case 8: dst[7] = src[7]; \
+                case 7: dst[6] = src[6]; \
+                case 6: dst[5] = src[5]; \
+                case 5: dst[4] = src[4]; \
+                case 4: dst[3] = src[3]; \
+                case 3: dst[2] = src[2]; \
+                case 2: dst[1] = src[1]; \
+                case 1: dst[0] = src[0]; \
+                case 0: break; \
+            } \
+    } while (0)
+#elif defined(__GNUC__)
+# define my_memcpy __builtin_memcpy
+#elif defined(_MSC_VER)
+# pragma instrinic(memcpy)
+# define my_memcpy memcpy
+#endif
+#define ADD_VAR(pVar)           do { my_memcpy(psz, (pVar)->value, (pVar)->value_length); psz += (pVar)->value_length; } while (0)
+#define ADD_STR(pszStr, cchStr) do { my_memcpy(psz, (pszStr), (cchStr)); psz += (cchStr); } while (0)
+#define ADD_CSTR(pszStr)        do { my_memcpy(psz, pszStr, sizeof(pszStr) - 1); psz += sizeof(pszStr) - 1; } while (0)
+#define ADD_CH(ch)              do { *psz++ = (ch); } while (0)
+
+    /*
+     * $(target)_$(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
+     */
+    psz = pszBuf;
+    ADD_VAR(pTarget);
+    ADD_CH('_');
+    ADD_VAR(pSource);
+    ADD_CH('_');
+    psz2 = psz;
+    ADD_VAR(pType);
+    ADD_STR(pszPropF2, cchPropF2);
+    psz3 = psz;
+    ADD_CH('.');
+    ADD_VAR(pBldTrg);
+    psz4 = psz;
+    ADD_CH('.');
+    ADD_VAR(pBldTrgArch);
+    pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+    /* $(target)_$(source)_$(type)$(propf2).$(bld_trg) */
+    if (!pVar)
+        pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+    /* $(target)_$(source)_$(type)$(propf2) */
+    if (!pVar)
+        pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+
+    /*
+     * $(target)_$(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
+     */
+    if (!pVar)
+    {
+        psz = psz2;
+        ADD_STR(pszPropF2, cchPropF2);
+        psz3 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrg);
+        psz4 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrgArch);
+        pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+        /* $(target)_$(source)_$(propf2).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* $(target)_$(source)_$(propf2) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+    }
+
+
+    /*
+     * $(source)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
+     */
+    if (!pVar)
+    {
+        psz = pszBuf;
+        ADD_VAR(pSource);
+        ADD_CH('_');
+        psz2 = psz;
+        ADD_VAR(pType);
+        ADD_STR(pszPropF2, cchPropF2);
+        psz3 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrg);
+        psz4 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrgArch);
+        pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+        /* $(source)_$(type)$(propf2).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* $(source)_$(type)$(propf2) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+
+        /*
+         * $(source)_$(propf2).$(bld_trg).$(bld_trg_arch)
+         */
+        if (!pVar)
+        {
+            psz = psz2;
+            ADD_STR(pszPropF2, cchPropF2);
+            psz3 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrg);
+            psz4 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrgArch);
+            pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+            /* $(source)_$(propf2).$(bld_trg) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+            /* $(source)_$(propf2) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+        }
+    }
+
+    /*
+     * $(target)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
+     */
+    if (!pVar)
+    {
+        psz = pszBuf;
+        ADD_VAR(pTarget);
+        ADD_CH('_');
+        psz2 = psz;
+        ADD_VAR(pType);
+        ADD_STR(pszPropF2, cchPropF2);
+        psz3 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrg);
+        psz4 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrgArch);
+        pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+        /* $(target)_$(type)$(propf2).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* $(target)_$(type)$(propf2) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+
+        /* $(target)_$(propf2).$(bld_trg).$(bld_trg_arch) */
+        if (!pVar)
+        {
+            psz = psz2;
+            ADD_STR(pszPropF2, cchPropF2);
+            psz3 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrg);
+            psz4 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrgArch);
+            pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+        }
+
+        /* $(target)_$(propf2).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* $(target)_$(propf2) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+    }
+
+    /*
+     * TOOL_$(tool)_$(type)$(propf2).$(bld_trg).$(bld_trg_arch)
+     */
+    if (!pVar && pTool)
+    {
+        psz = pszBuf;
+        ADD_CSTR("TOOL_");
+        ADD_VAR(pTool);
+        ADD_CH('_');
+        psz2 = psz;
+        ADD_VAR(pType);
+        ADD_STR(pszPropF2, cchPropF2);
+        psz3 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrg);
+        psz4 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrgArch);
+        pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+        /* TOOL_$(tool)_$(type)$(propf2).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* TOOL_$(tool)_$(type)$(propf2) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+
+        /* TOOL_$(tool)_$(propf2).$(bld_trg).$(bld_trg_arch) */
+        if (!pVar)
+        {
+            psz = psz2;
+            ADD_STR(pszPropF2, cchPropF2);
+            psz3 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrg);
+            psz4 = psz;
+            ADD_CH('.');
+            ADD_VAR(pBldTrgArch);
+            pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+            /* TOOL_$(tool)_$(propf2).$(bld_trg) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+            /* TOOL_$(tool)_$(propf2) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+        }
+    }
+
+    /*
+     * $(type)$(propf1).$(bld_trg).$(bld_trg_arch)
+     */
+    if (!pVar)
+    {
+        psz = pszBuf;
+        ADD_VAR(pType);
+        ADD_STR(pszPropF1, cchPropF1);
+        psz3 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrg);
+        psz4 = psz;
+        ADD_CH('.');
+        ADD_VAR(pBldTrgArch);
+        pVar = kbuild_lookup_variable_n(pszBuf, psz - pszBuf);
+
+        /* $(type)$(propf1).$(bld_trg) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz4 - pszBuf);
+
+        /* $(type)$(propf1) */
+        if (!pVar)
+            pVar = kbuild_lookup_variable_n(pszBuf, psz3 - pszBuf);
+
+        /*
+         * $(propf1).$(bld_trg).$(bld_trg_arch)
+         */
+        if (!pVar)
+        {
+            psz1 = pszBuf + pType->value_length;
+            pVar = kbuild_lookup_variable_n(psz1, psz - psz1);
+
+            /* $(propf1).$(bld_trg) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(psz1, psz4 - psz1);
+
+            /* $(propf1) */
+            if (!pVar)
+                pVar = kbuild_lookup_variable_n(pszPropF1, cchPropF1);
+        }
+    }
+    free(pszBuf);
+#undef ADD_VAR
+#undef ADD_STR
+#undef ADD_CSTR
+#undef ADD_CH
+
+    if (pVar)
     {
         /* strip it */
@@ -779,5 +1095,7 @@
 {
     struct variable *pVar = kbuild_first_prop(pTarget, pSource, NULL, pType, pBldTrg, pBldTrgArch,
-                                              "TOOL", "TOOL", pszVarName);
+                                              "TOOL", sizeof("TOOL") - 1,
+                                              "TOOL", sizeof("TOOL") - 1,
+                                              pszVarName);
     if (!pVar)
         fatal(NILF, _("no tool for source `%s' in target `%s'!"), pSource->value, pTarget->value);
@@ -790,9 +1108,9 @@
 func_kbuild_source_tool(char *o, char **argv, const char *pszFuncName)
 {
-    struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable("target"),
-                                                   kbuild_get_variable("source"),
-                                                   kbuild_get_variable("type"),
-                                                   kbuild_get_variable("bld_trg"),
-                                                   kbuild_get_variable("bld_trg_arch"),
+    struct variable *pVar = kbuild_get_source_tool(kbuild_get_variable_n(ST("target")),
+                                                   kbuild_get_variable_n(ST("source")),
+                                                   kbuild_get_variable_n(ST("type")),
+                                                   kbuild_get_variable_n(ST("bld_trg")),
+                                                   kbuild_get_variable_n(ST("bld_trg_arch")),
                                                    argv[0]);
     if (pVar)
@@ -826,5 +1144,7 @@
 {
     struct variable *pVar = kbuild_first_prop(pTarget, pSource, pTool, pType, pBldTrg, pBldTrgArch,
-                                              "SUFF_OBJ", "OBJSUFF", pszVarName);
+                                              "SUFF_OBJ", sizeof("SUFF_OBJ") - 1,
+                                              "OBJSUFF",  sizeof("OBJSUFF")  - 1,
+                                              pszVarName);
     if (!pVar)
         fatal(NILF, _("no OBJSUFF attribute or SUFF_OBJ default for source `%s' in target `%s'!"), pSource->value, pTarget->value);
@@ -837,10 +1157,10 @@
 func_kbuild_object_suffix(char *o, char **argv, const char *pszFuncName)
 {
-    struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable("target"),
-                                                     kbuild_get_variable("source"),
-                                                     kbuild_get_variable("tool"),
-                                                     kbuild_get_variable("type"),
-                                                     kbuild_get_variable("bld_trg"),
-                                                     kbuild_get_variable("bld_trg_arch"),
+    struct variable *pVar = kbuild_get_object_suffix(kbuild_get_variable_n(ST("target")),
+                                                     kbuild_get_variable_n(ST("source")),
+                                                     kbuild_get_variable_n(ST("tool")),
+                                                     kbuild_get_variable_n(ST("type")),
+                                                     kbuild_get_variable_n(ST("bld_trg")),
+                                                     kbuild_get_variable_n(ST("bld_trg_arch")),
                                                      argv[0]);
     if (pVar)
@@ -865,7 +1185,7 @@
 kbuild_get_object_base(struct variable *pTarget, struct variable *pSource, const char *pszVarName)
 {
-    struct variable *pPathTarget = kbuild_get_variable("PATH_TARGET");
-    struct variable *pPathRoot   = kbuild_get_variable("PATH_ROOT");
-    struct variable *pPathSubCur = kbuild_get_variable("PATH_SUB_CURRENT");
+    struct variable *pPathTarget = kbuild_get_variable_n(ST("PATH_TARGET"));
+    struct variable *pPathRoot   = kbuild_get_variable_n(ST("PATH_ROOT"));
+    struct variable *pPathSubCur = kbuild_get_variable_n(ST("PATH_SUB_CURRENT"));
     const char *pszSrcPrefix = NULL;
     size_t      cchSrcPrefix = 0;
@@ -1283,5 +1603,7 @@
                            struct variable *pBldTrg, struct variable *pBldTrgArch, struct variable *pBldTrgCpu,
                            struct variable *pDefPath,
-                           const char *pszProp, const char *pszVarName, int iDirection)
+                           const char *pszProp, size_t cchProp,
+                           const char *pszVarName, size_t cchVarName,
+                           int iDirection)
 {
     struct variable *pVar;
@@ -1299,5 +1621,5 @@
     struct variable Prop = {0};
     Prop.value = (char *)pszProp;
-    Prop.value_length = strlen(pszProp);
+    Prop.value_length = cchProp;
 
     assert(iDirection == 1 || iDirection == -1);
@@ -1524,5 +1846,5 @@
     cchTotal = psz - pszResult;
 
-    pVar = define_variable_vl(pszVarName, strlen(pszVarName), pszResult, cchTotal,
+    pVar = define_variable_vl(pszVarName, cchVarName, pszResult, cchTotal,
                               0 /* take pszResult */ , o_local, 0 /* !recursive */);
     return pVar;
@@ -1534,13 +1856,13 @@
 func_kbuild_source_prop(char *o, char **argv, const char *pszFuncName)
 {
-    struct variable *pTarget = kbuild_get_variable("target");
-    struct variable *pSource = kbuild_get_variable("source");
+    struct variable *pTarget = kbuild_get_variable_n(ST("target"));
+    struct variable *pSource = kbuild_get_variable_n(ST("source"));
     struct variable *pDefPath = NULL;
-    struct variable *pType = kbuild_get_variable("type");
-    struct variable *pTool = kbuild_get_variable("tool");
-    struct variable *pBldType = kbuild_get_variable("bld_type");
-    struct variable *pBldTrg = kbuild_get_variable("bld_trg");
-    struct variable *pBldTrgArch = kbuild_get_variable("bld_trg_arch");
-    struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
+    struct variable *pType = kbuild_get_variable_n(ST("type"));
+    struct variable *pTool = kbuild_get_variable_n(ST("tool"));
+    struct variable *pBldType = kbuild_get_variable_n(ST("bld_type"));
+    struct variable *pBldTrg = kbuild_get_variable_n(ST("bld_trg"));
+    struct variable *pBldTrgArch = kbuild_get_variable_n(ST("bld_trg_arch"));
+    struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
     struct variable *pVar;
     struct kbuild_sdks Sdks;
@@ -1558,5 +1880,5 @@
             psz++;
         if (*psz)
-            pDefPath = kbuild_get_variable("defpath");
+            pDefPath = kbuild_get_variable_n(ST("defpath"));
     }
 
@@ -1566,5 +1888,7 @@
                                       pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu,
                                       pDefPath,
-                                      argv[0], argv[1], iDirection);
+                                      argv[0], strlen(argv[0]),
+                                      argv[1], strlen(argv[1]),
+                                      iDirection);
     if (pVar)
          o = variable_buffer_output(o, pVar->value, pVar->value_length);
@@ -1588,5 +1912,5 @@
                                                                  struct variable **ppDirDep)
 {
-    struct variable *pDepSuff = kbuild_get_variable("SUFF_DEP");
+    struct variable *pDepSuff = kbuild_get_variable_n(ST("SUFF_DEP"));
     struct variable *pObj;
     size_t cch = pOutBase->value_length + pObjSuff->value_length + pDepSuff->value_length + 1;
@@ -1699,12 +2023,12 @@
 {
     static int s_fNoCompileCmdsDepsDefined = -1;
-    struct variable *pTarget    = kbuild_get_variable("target");
-    struct variable *pSource    = kbuild_get_variable("source");
-    struct variable *pDefPath   = kbuild_get_variable("defpath");
-    struct variable *pType      = kbuild_get_variable("type");
-    struct variable *pBldType   = kbuild_get_variable("bld_type");
-    struct variable *pBldTrg    = kbuild_get_variable("bld_trg");
-    struct variable *pBldTrgArch= kbuild_get_variable("bld_trg_arch");
-    struct variable *pBldTrgCpu = kbuild_get_variable("bld_trg_cpu");
+    struct variable *pTarget    = kbuild_get_variable_n(ST("target"));
+    struct variable *pSource    = kbuild_get_variable_n(ST("source"));
+    struct variable *pDefPath   = kbuild_get_variable_n(ST("defpath"));
+    struct variable *pType      = kbuild_get_variable_n(ST("type"));
+    struct variable *pBldType   = kbuild_get_variable_n(ST("bld_type"));
+    struct variable *pBldTrg    = kbuild_get_variable_n(ST("bld_trg"));
+    struct variable *pBldTrgArch= kbuild_get_variable_n(ST("bld_trg_arch"));
+    struct variable *pBldTrgCpu = kbuild_get_variable_n(ST("bld_trg_cpu"));
     struct variable *pTool      = kbuild_get_source_tool(pTarget, pSource, pType, pBldTrg, pBldTrgArch, "tool");
     struct variable *pOutBase   = kbuild_get_object_base(pTarget, pSource, "outbase");
@@ -1714,5 +2038,5 @@
     char *pszDstVar, *pszDst, *pszSrcVar, *pszSrc, *pszVal, *psz;
     char *pszSavedVarBuf;
-    unsigned cchSavedVarBuf, cchVal;
+    unsigned cchSavedVarBuf;
     size_t cch;
     struct kbuild_sdks Sdks;
@@ -1761,13 +2085,13 @@
         pDefPath = NULL;
     pDefs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
-                                            "DEFS", "defs", 1/* left-to-right */);
+                                            ST("DEFS"),  ST("defs"), 1/* left-to-right */);
     pIncs      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
-                                            "INCS", "incs", -1/* right-to-left */);
+                                            ST("INCS"),  ST("incs"), -1/* right-to-left */);
     pFlags     = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, NULL,
-                                            "FLAGS", "flags", 1/* left-to-right */);
+                                            ST("FLAGS"), ST("flags"), 1/* left-to-right */);
     pDeps      = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
-                                            "DEPS", "deps", 1/* left-to-right */);
+                                            ST("DEPS"),  ST("deps"), 1/* left-to-right */);
     pOrderDeps = kbuild_collect_source_prop(pTarget, pSource, pTool, &Sdks, pType, pBldType, pBldTrg, pBldTrgArch, pBldTrgCpu, pDefPath,
-                                            "ORDERDEPS", "orderdeps", 1/* left-to-right */);
+                                            ST("ORDERDEPS"), ST("orderdeps"), 1/* left-to-right */);
 
     /*
@@ -1787,5 +2111,5 @@
      */
     if (s_fNoCompileCmdsDepsDefined == -1)
-        s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable("NO_COMPILE_CMDS_DEPS") != NULL;
+        s_fNoCompileCmdsDepsDefined = kbuild_lookup_variable_n(ST("NO_COMPILE_CMDS_DEPS")) != NULL;
     if (!s_fNoCompileCmdsDepsDefined)
     {
@@ -1870,5 +2194,5 @@
     */
     /** @todo use append? */
-    pVar = kbuild_get_variable("_OUT_FILES");
+    pVar = kbuild_get_variable_n(ST("_OUT_FILES"));
     psz = pszVal = xmalloc(pVar->value_length + 1 + pOutput->value_length + 1 + pOutputMaybe->value_length + 1);
     memcpy(psz, pVar->value, pVar->value_length); psz += pVar->value_length;
@@ -1893,15 +2217,16 @@
     */
     pVar = kbuild_get_recursive_variable("def_target_source_rule");
-    pszVal = allocated_variable_expand_2(pVar->value, pVar->value_length, &cchVal); /** @todo we can use the variable buffer here. */
+    pszVal = variable_expand_string_2 (o, pVar->value, pVar->value_length, &psz);
+    assert (!((size_t)pszVal & 3));
 
     install_variable_buffer(&pszSavedVarBuf, &cchSavedVarBuf);
-    eval_buffer(pszVal, pszVal + cchVal);
+    eval_buffer(pszVal, psz);
     restore_variable_buffer(pszSavedVarBuf, cchSavedVarBuf);
-
-    free(pszVal);
 
     kbuild_put_sdks(&Sdks);
     (void)pszFuncName;
-    return variable_buffer_output(o, "", 1) - 1; /** @todo why? */
+
+    *pszVal = '\0';
+    return pszVal;
 }
 
