Index: trunk/src/kmk/Makefile.kmk
===================================================================
--- trunk/src/kmk/Makefile.kmk	(revision 2457)
+++ trunk/src/kmk/Makefile.kmk	(revision 2462)
@@ -585,4 +585,7 @@
 	$(MAKE) -f $(kmk_DEFPATH)/testcase-includedep.kmk
 
+test_root:
+	$(MAKE) -f $(kmk_DEFPATH)/testcase-root.kmk
+
 test_2ndtargetexp:
 	$(MAKE) -f $(kmk_DEFPATH)/testcase-2ndtargetexp.kmk
@@ -606,5 +609,15 @@
 
 
-test_all:	test_math test_stack test_shell test_if1of test_local test_includedep test_2ndtargetexp test_30_continued_on_failure test_lazy_deps_vars
-
-
+test_all: \
+        test_math \
+        test_stack \
+        test_shell \
+        test_if1of \
+        test_local \
+        test_root \
+        test_includedep \
+        test_2ndtargetexp \
+        test_30_continued_on_failure \
+        test_lazy_deps_vars
+
+
Index: trunk/src/kmk/function.c
===================================================================
--- trunk/src/kmk/function.c	(revision 2457)
+++ trunk/src/kmk/function.c	(revision 2462)
@@ -809,4 +809,5 @@
 
 #ifdef CONFIG_WITH_ROOT_FUNC
+
 /*
  $(root path)
@@ -882,5 +883,5 @@
       if (p2 != NULL)
         {
-          /* Include all subsequent path seperators. */
+          /* Include all subsequent path separators. */
 
           while (len > 0 && IS_PATHSEP(*p2))
@@ -898,4 +899,85 @@
   return o;
 }
+
+/*
+ $(notroot path)
+
+ This is mainly for dealing with drive letters and UNC paths on Windows
+ and OS/2.
+ */
+static char *
+func_notroot (char *o, char **argv, const char *funcname UNUSED)
+{
+  const char  *paths = argv[0] ? argv[0] : "";
+  int          doneany = 0;
+  const char  *p;
+  unsigned int len;
+
+  while ((p = find_next_token (&paths, &len)) != 0)
+    {
+      const char *p2 = p;
+
+#ifdef HAVE_DOS_PATHS
+      if (   len >= 2
+          && p2[1] == ':'
+          && (   (p2[0] >= 'A' && p2[0] <= 'Z')
+              || (p2[0] >= 'a' && p2[0] <= 'z')))
+        {
+          p2 += 2;
+          len -= 2;
+        }
+      else if (len >= 4 && IS_PATHSEP(p2[0]) && IS_PATHSEP(p2[1])
+               && !IS_PATHSEP(p2[2]))
+        {
+          /* Min recognized UNC: "//./" - find the next slash
+             Typical root: "//srv/shr/" */
+          /* XXX: Check if //./ needs special handling. */
+          unsigned int saved_len = len;
+
+          p2 += 3;
+          len -= 3;
+          while (len > 0 && !IS_PATHSEP(*p2))
+            p2++, len--;
+
+          if (len && IS_PATHSEP(p2[0]) && (len == 1 || !IS_PATHSEP(p2[1])))
+            {
+              p2++;
+              len--;
+
+              if (len) /* optional share */
+                while (len > 0 && !IS_PATHSEP(*p2))
+                  p2++, len--;
+            }
+          else
+            {
+              p2 = p;
+              len = saved_len;
+            }
+        }
+
+#elif defined (VMS) || defined (AMGIA)
+      /* XXX: VMS and AMGIA */
+      fatal (NILF, _("$(root ) is not implemented on this platform"));
+#endif
+
+      /* Exclude all subsequent / leading path separators. */
+
+      while (len > 0 && IS_PATHSEP(*p2))
+        p2++, len--;
+      if (len > 0)
+        o = variable_buffer_output (o, p2, len);
+      else
+        o = variable_buffer_output (o, ".", 1);
+      o = variable_buffer_output (o, " ", 1);
+      doneany = 1;
+    }
+
+  if (doneany)
+    /* Kill last space.  */
+    --o;
+
+  return o;
+}
+
 #endif /* CONFIG_WITH_ROOT_FUNC */
 
@@ -5065,4 +5147,5 @@
 #ifdef CONFIG_WITH_ROOT_FUNC
   { STRING_SIZE_TUPLE("root"),          0,  1,  1,  func_root},
+  { STRING_SIZE_TUPLE("notroot"),       0,  1,  1,  func_notroot},
 #endif
   { STRING_SIZE_TUPLE("subst"),         3,  3,  1,  func_subst},
Index: trunk/src/kmk/testcase-root.kmk
===================================================================
--- trunk/src/kmk/testcase-root.kmk	(revision 2462)
+++ trunk/src/kmk/testcase-root.kmk	(revision 2462)
@@ -0,0 +1,30 @@
+#
+# The $(root ...) and $(notroot ) functions.
+#
+
+
+
+x := $(root /a)
+y := $(notroot /a)
+ifneq ($x,/)
+ $(error x=$x)
+endif
+ifneq ($y,a)
+ $(error y=$y)
+endif
+
+x := $(root /a /b /)
+y := $(notroot /a /b /)
+ifneq ($x,/ / /)
+ $(error x=$x)
+endif
+ifneq ($y,a b .)
+ $(error y=$y)
+endif
+
+
+# dummy
+all:
+	echo The root and notroot functions works.
+
+
