Index: /trunk/src/kmk/Makefile.am
===================================================================
--- /trunk/src/kmk/Makefile.am	(revision 985)
+++ /trunk/src/kmk/Makefile.am	(revision 986)
@@ -109,4 +109,5 @@
 	-DCONFIG_WITH_MATH \
 	-DCONFIG_WITH_XARGS \
+	-DCONFIG_WITH_NANOTS \
 	-DCONFIG_PRETTY_COMMAND_PRINTING \
 	\
Index: /trunk/src/kmk/Makefile.kmk
===================================================================
--- /trunk/src/kmk/Makefile.kmk	(revision 985)
+++ /trunk/src/kmk/Makefile.kmk	(revision 986)
@@ -111,4 +111,5 @@
 	CONFIG_WITH_MATH \
 	CONFIG_WITH_XARGS \
+	CONFIG_WITH_NANOTS \
 	CONFIG_PRETTY_COMMAND_PRINTING \
 	\
Index: /trunk/src/kmk/function.c
===================================================================
--- /trunk/src/kmk/function.c	(revision 985)
+++ /trunk/src/kmk/function.c	(revision 986)
@@ -42,4 +42,20 @@
 #endif
 #include <assert.h> /* bird */
+
+#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS) /* bird */
+# include <ctype.h>
+# ifdef _MSC_VER
+typedef __int64 math_int;
+# else
+#  include <stdint.h>
+typedef int64_t math_int;
+# endif
+#endif
+
+#ifdef CONFIG_WITH_NANOTS /* bird */
+# ifdef WINDOWS32
+#  include <Windows.h>
+# endif
+#endif
 
 
@@ -2664,6 +2680,6 @@
 func_stack_push (char *o, char **argv, const char *funcname)
 {
-    do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */);
-    return o;
+  do_variable_definition(NILF, argv[0], argv[1], o_file, f_append, 0 /* !target_var */);
+  return o;
 }
 
@@ -2673,47 +2689,80 @@
 func_stack_pop_top (char *o, char **argv, const char *funcname)
 {
-    struct variable *stack_var;
-    const char *stack = argv[0];
-    const int return_item = argv[0][sizeof("stack-pop") - 1] == '\0';
-
-    stack_var = lookup_variable (stack, strlen (stack) );
-    if (stack_var)
-      {
-        unsigned int len;
-        const char *iterator = stack_var->value;
-        char *lastitem = NULL;
-        char *cur;
-
-        while ((cur = find_next_token (&iterator, &len)))
-          lastitem = cur;
-
-        if (lastitem != NULL)
-          {
-            if (strcmp (funcname, "stack-popv") != 0)
-              o = variable_buffer_output (o, lastitem, len);
-            if (strcmp (funcname, "stack-top") != 0)
-              {
-                *lastitem = '\0';
-                while (lastitem > stack_var->value && isspace (lastitem[-1]))
-                  *--lastitem = '\0';
+  struct variable *stack_var;
+  const char *stack = argv[0];
+  const int return_item = argv[0][sizeof("stack-pop") - 1] == '\0';
+
+  stack_var = lookup_variable (stack, strlen (stack) );
+  if (stack_var)
+    {
+      unsigned int len;
+      const char *iterator = stack_var->value;
+      char *lastitem = NULL;
+      char *cur;
+
+      while ((cur = find_next_token (&iterator, &len)))
+        lastitem = cur;
+
+      if (lastitem != NULL)
+        {
+          if (strcmp (funcname, "stack-popv") != 0)
+            o = variable_buffer_output (o, lastitem, len);
+          if (strcmp (funcname, "stack-top") != 0)
+            {
+              *lastitem = '\0';
+              while (lastitem > stack_var->value && isspace (lastitem[-1]))
+                *--lastitem = '\0';
 #ifdef CONFIG_WITH_VALUE_LENGTH
-                stack_var->value_length = lastitem - stack_var->value;
-#endif
-              }
-          }
-      }
-    return o;
+              stack_var->value_length = lastitem - stack_var->value;
+#endif
+            }
+        }
+    }
+  return o;
 }
 #endif /* CONFIG_WITH_STACK */
 
+#if defined (CONFIG_WITH_MATH) || defined (CONFIG_WITH_NANOTS)
+/* outputs the number (as a string) into the variable buffer. */
+static char *
+math_int_to_variable_buffer (char *o, math_int num)
+{
+  static const char xdigits[17] = "0123456789abcdef";
+  int negative;
+  char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20
+                              or 20 dec + sign + term => 22 */
+  char *str = &strbuf[sizeof (strbuf) - 1];
+
+  negative = num < 0;
+  if (negative)
+    num = -num;
+
+  *str = '\0';
+
+  do
+    {
+#ifdef HEX_MATH_NUMBERS
+      *--str = xdigits[num & 0xf];
+      num >>= 4;
+#else
+      *--str = xdigits[num % 10];
+      num /= 10;
+#endif
+    }
+  while (num);
+
+#ifdef HEX_MATH_NUMBERS
+  *--str = 'x';
+  *--str = '0';
+#endif
+
+  if (negative)
+    *--str = '-';
+
+  return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
+}
+#endif /* CONFIG_WITH_MATH || CONFIG_WITH_NANOTS */
+
 #ifdef CONFIG_WITH_MATH
-
-#include <ctype.h>
-#ifdef _MSC_VER
-typedef __int64 math_int;
-#else
-# include <stdint.h>
-typedef int64_t math_int;
-#endif
 
 /* Converts a string to an integer, causes an error if the format is invalid. */
@@ -2721,112 +2770,81 @@
 math_int_from_string (const char *str)
 {
-    const char *start;
-    unsigned base = 0;
-    int      negative = 0;
-    math_int num = 0;
-
-    /* strip spaces */
-    while (isspace (*str))
-      str++;
-    if (!*str)
-      {
-        error (NILF, _("bad number: empty\n"));
-        return 0;
-      }
-    start = str;
-
-    /* check for +/- */
-    while (*str == '+' || *str == '-' || isspace (*str))
-        if (*str++ == '-')
-          negative = !negative;
-
-    /* check for prefix - we do not accept octal numbers, sorry. */
-    if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
-      {
-        base = 16;
-        str += 2;
-      }
-    else
-      {
-        /* look for a hex digit, if not found treat it as decimal */
-        const char *p2 = str;
-        for ( ; *p2; p2++)
-          if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
-            {
-              base = 16;
-              break;
-            }
-        if (base == 0)
-          base = 10;
-      }
-
-    /* must have at least one digit! */
-    if (    !isascii (*str)
-        ||  !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
-      {
-        error (NILF, _("bad number: '%s'\n"), start);
-        return 0;
-      }
-
-    /* convert it! */
-    while (*str && !isspace (*str))
-      {
-        int ch = *str++;
-        if (ch >= '0' && ch <= '9')
-          ch -= '0';
-        else if (base == 16 && ch >= 'a' && ch <= 'f')
-          ch -= 'a' - 10;
-        else if (base == 16 && ch >= 'A' && ch <= 'F')
-          ch -= 'A' - 10;
-        else
+  const char *start;
+  unsigned base = 0;
+  int      negative = 0;
+  math_int num = 0;
+
+  /* strip spaces */
+  while (isspace (*str))
+    str++;
+  if (!*str)
+    {
+      error (NILF, _("bad number: empty\n"));
+      return 0;
+    }
+  start = str;
+
+  /* check for +/- */
+  while (*str == '+' || *str == '-' || isspace (*str))
+      if (*str++ == '-')
+        negative = !negative;
+
+  /* check for prefix - we do not accept octal numbers, sorry. */
+  if (*str == '0' && (str[1] == 'x' || str[1] == 'X'))
+    {
+      base = 16;
+      str += 2;
+    }
+  else
+    {
+      /* look for a hex digit, if not found treat it as decimal */
+      const char *p2 = str;
+      for ( ; *p2; p2++)
+        if (isxdigit (*p2) && !isdigit (*p2) && isascii (*p2) )
           {
-            error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
-            return 0;
+            base = 16;
+            break;
           }
-        num *= base;
-        num += ch;
-      }
-
-    /* check trailing spaces. */
-    while (isspace (*str))
-      str++;
-    if (*str)
-      {
-        error (NILF, _("bad number: '%s'\n"), start);
-        return 0;
-      }
-
-    return negative ? -num : num;
-}
-
-/* outputs the number (as a string) into the variable buffer. */
-static char *
-math_int_to_variable_buffer (char *o, math_int num)
-{
-    static const char xdigits[17] = "0123456789abcdef";
-    int negative;
-    char strbuf[24]; /* 16 hex + 2 prefix + sign + term => 20 */
-    char *str = &strbuf[sizeof (strbuf) - 1];
-
-    negative = num < 0;
-    if (negative)
-      num = -num;
-
-    *str-- = '\0';
-
-    do
-      {
-        *str-- = xdigits[num & 0xf];
-        num >>= 4;
-      }
-    while (num);
-
-    *str-- = 'x';
-    *str = '0';
-
-    if (negative)
-        *--str = '-';
-
-    return variable_buffer_output (o, str, &strbuf[sizeof (strbuf) - 1] - str);
+      if (base == 0)
+        base = 10;
+    }
+
+  /* must have at least one digit! */
+  if (    !isascii (*str)
+      ||  !(base == 16 ? isxdigit (*str) : isdigit (*str)) )
+    {
+      error (NILF, _("bad number: '%s'\n"), start);
+      return 0;
+    }
+
+  /* convert it! */
+  while (*str && !isspace (*str))
+    {
+      int ch = *str++;
+      if (ch >= '0' && ch <= '9')
+        ch -= '0';
+      else if (base == 16 && ch >= 'a' && ch <= 'f')
+        ch -= 'a' - 10;
+      else if (base == 16 && ch >= 'A' && ch <= 'F')
+        ch -= 'A' - 10;
+      else
+        {
+          error (NILF, _("bad number: '%s' (base=%d, pos=%d)\n"), start, base, str - start);
+          return 0;
+        }
+      num *= base;
+      num += ch;
+    }
+
+  /* check trailing spaces. */
+  while (isspace (*str))
+    str++;
+  if (*str)
+    {
+      error (NILF, _("bad number: '%s'\n"), start);
+      return 0;
+    }
+
+  return negative ? -num : num;
 }
 
@@ -2835,12 +2853,12 @@
 func_int_add (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num += math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num += math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2849,12 +2867,12 @@
 func_int_sub (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num -= math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num -= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2863,12 +2881,12 @@
 func_int_mul (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num *= math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num *= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2877,21 +2895,21 @@
 func_int_div (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    math_int divisor;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      {
-        divisor = math_int_from_string (argv[i]);
-        if (!divisor)
-          {
-            error (NILF, _("divide by zero ('%s')\n"), argv[i]);
-            return math_int_to_variable_buffer (o, 0);
-          }
-        num /= divisor;
-      }
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  math_int divisor;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    {
+      divisor = math_int_from_string (argv[i]);
+      if (!divisor)
+        {
+          error (NILF, _("divide by zero ('%s')\n"), argv[i]);
+          return math_int_to_variable_buffer (o, 0);
+        }
+      num /= divisor;
+    }
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2901,17 +2919,17 @@
 func_int_mod (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    math_int divisor;
-
-    num = math_int_from_string (argv[0]);
-    divisor = math_int_from_string (argv[1]);
-    if (!divisor)
-      {
-        error (NILF, _("divide by zero ('%s')\n"), argv[1]);
-        return math_int_to_variable_buffer (o, 0);
-      }
-    num %= divisor;
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  math_int divisor;
+
+  num = math_int_from_string (argv[0]);
+  divisor = math_int_from_string (argv[1]);
+  if (!divisor)
+    {
+      error (NILF, _("divide by zero ('%s')\n"), argv[1]);
+      return math_int_to_variable_buffer (o, 0);
+    }
+  num %= divisor;
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2920,10 +2938,10 @@
 func_int_not (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-
-    num = math_int_from_string (argv[0]);
-    num = ~num;
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+
+  num = math_int_from_string (argv[0]);
+  num = ~num;
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2932,12 +2950,12 @@
 func_int_and (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num &= math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num &= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2946,12 +2964,12 @@
 func_int_or (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num |= math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num |= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2960,12 +2978,12 @@
 func_int_xor (char *o, char **argv, const char *funcname)
 {
-    math_int num;
-    int i;
-
-    num = math_int_from_string (argv[0]);
-    for (i = 1; argv[i]; i++)
-      num ^= math_int_from_string (argv[i]);
-
-    return math_int_to_variable_buffer (o, num);
+  math_int num;
+  int i;
+
+  num = math_int_from_string (argv[0]);
+  for (i = 1; argv[i]; i++)
+    num ^= math_int_from_string (argv[i]);
+
+  return math_int_to_variable_buffer (o, num);
 }
 
@@ -2999,4 +3017,64 @@
 
 #endif /* CONFIG_WITH_MATH */
+
+#ifdef CONFIG_WITH_NANOTS
+/* Returns the current timestamp as nano seconds. The time
+   source is a high res monotone one if the platform provides
+   this (and we know about it).
+
+   Tip. Use this with int-sub to profile makefile reading
+        and similar. */
+static char *
+func_nanots (char *o, char **argv, const char *funcname)
+{
+  math_int ts;
+
+#if defined (WINDOWS32)
+  static int s_state = -1;
+  static LARGE_INTEGER s_freq;
+
+  if (s_state == -1)
+    s_state = QueryPerformanceFrequency (&s_freq);
+  if (s_state)
+    {
+      LARGE_INTEGER pc;
+      if (!QueryPerformanceCounter (&pc))
+        {
+          s_state = 0;
+          return func_nanots (o, argv, funcname);
+        }
+      ts = (math_int)((long double)pc.QuadPart / (long double)s_freq.QuadPart * 1000000000);
+    }
+  else
+    {
+      /* fall back to low resolution system time. */
+      LARGE_INTEGER bigint;
+      FILETIME ft = {0,0};
+      GetSystemTimeAsFileTime (&ft);
+      bigint.u.LowPart = ft.dwLowDateTime;
+      bigint.u.HighPart = ft.dwLowDateTime;
+      ts = bigint.QuadPart * 10000;
+    }
+
+/* FIXME: Linux and others has the realtime clock_* api, detect and use it. */
+
+#elif HAVE_GETTIMEOF_DAY
+  struct timeval tv;
+  if (!gettimeofday (&tv, NULL))
+    ts = (math_int)tv.tv_sec * 1000000000
+       + tv.tv_usec * 1000;
+  else
+    {
+      error (NILF, _("$(nanots): gettimeofday failed"));
+      ts = 0;
+    }
+
+#else
+# error "PORTME"
+#endif
+
+  return math_int_to_variable_buffer (o, ts);
+}
+#endif
 
 
@@ -3098,4 +3176,7 @@
   { STRING_SIZE_TUPLE("int-le"),        2,  2,  1,  func_int_cmp},
 #endif
+#ifdef CONFIG_WITH_NANOTS
+  { STRING_SIZE_TUPLE("nanots"),        0,  0,  0,  func_nanots},
+#endif
 #ifdef KMK_HELPERS
   { STRING_SIZE_TUPLE("kb-src-tool"),   1,  1,  0,  func_kbuild_source_tool},
