util: Pre-allocate buffer for ovs_lasterror_to_string().
[sliver-openvswitch.git] / lib / util.c
index c252886..911cc3e 100644 (file)
@@ -50,11 +50,13 @@ DEFINE_PER_THREAD_MALLOCED_DATA(char *, subprogram_name);
 /* --version option output. */
 static char *program_version;
 
-/* Buffer used by ovs_strerror(). */
+/* Buffer used by ovs_strerror() and ovs_format_message(). */
 DEFINE_STATIC_PER_THREAD_DATA(struct { char s[128]; },
                               strerror_buffer,
                               { "" });
 
+static char *xreadlink(const char *filename);
+
 void
 ovs_assert_failure(const char *where, const char *function,
                    const char *condition)
@@ -67,7 +69,7 @@ ovs_assert_failure(const char *where, const char *function,
     case 0:
         VLOG_ABORT("%s: assertion %s failed in %s()",
                    where, condition, function);
-        NOT_REACHED();
+        OVS_NOT_REACHED();
 
     case 1:
         fprintf(stderr, "%s: assertion %s failed in %s()",
@@ -323,6 +325,10 @@ ovs_retval_to_string(int retval)
             : ovs_strerror(retval));
 }
 
+/* This function returns the string describing the error number in 'error'
+ * for POSIX platforms.  For Windows, this function can be used for C library
+ * calls.  For socket calls that are also used in Windows, use sock_strerror()
+ * instead.  For WINAPI calls, look at ovs_lasterror_to_string(). */
 const char *
 ovs_strerror(int error)
 {
@@ -373,11 +379,22 @@ void
 set_program_name__(const char *argv0, const char *version, const char *date,
                    const char *time)
 {
-    const char *slash = strrchr(argv0, '/');
+#ifdef _WIN32
+    char *basename;
+    size_t max_len = strlen(argv0) + 1;
 
+    if (program_name) {
+        return;
+    }
+    basename = xmalloc(max_len);
+    _splitpath_s(argv0, NULL, 0, NULL, 0, basename, max_len, NULL, 0);
+    assert_single_threaded();
+    program_name = basename;
+#else
+    const char *slash = strrchr(argv0, '/');
     assert_single_threaded();
-
     program_name = slash ? slash + 1 : argv0;
+#endif
 
     free(program_version);
 
@@ -473,11 +490,11 @@ ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
       n = end - start;
 
       /* Print line. */
-      fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
+      fprintf(stream, "%08"PRIxMAX"  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
       for (i = 0; i < start; i++)
         fprintf(stream, "   ");
       for (; i < end; i++)
-        fprintf(stream, "%02hhx%c",
+        fprintf(stream, "%02x%c",
                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
       if (ascii)
         {
@@ -537,24 +554,6 @@ str_to_llong(const char *s, int base, long long *x)
     }
 }
 
-bool
-str_to_uint(const char *s, int base, unsigned int *u)
-{
-    return str_to_int(s, base, (int *) u);
-}
-
-bool
-str_to_ulong(const char *s, int base, unsigned long *ul)
-{
-    return str_to_long(s, base, (long *) ul);
-}
-
-bool
-str_to_ullong(const char *s, int base, unsigned long long *ull)
-{
-    return str_to_llong(s, base, (long long *) ull);
-}
-
 /* Converts floating-point string 's' into a double.  If successful, stores
  * the double in '*d' and returns true; on failure, stores 0 in '*d' and
  * returns false.
@@ -748,7 +747,7 @@ abs_file_name(const char *dir, const char *file_name)
 /* Like readlink(), but returns the link name as a null-terminated string in
  * allocated memory that the caller must eventually free (with free()).
  * Returns NULL on error, in which case errno is set appropriately. */
-char *
+static char *
 xreadlink(const char *filename)
 {
     size_t size;
@@ -780,10 +779,14 @@ xreadlink(const char *filename)
  *
  *     - Only symlinks in the final component of 'filename' are dereferenced.
  *
+ * For Windows platform, this function returns a string that has the same
+ * value as the passed string.
+ *
  * The caller must eventually free the returned string (with free()). */
 char *
 follow_symlinks(const char *filename)
 {
+#ifndef _WIN32
     struct stat s;
     char *fn;
     int i;
@@ -828,6 +831,7 @@ follow_symlinks(const char *filename)
 
     VLOG_WARN("%s: too many levels of symlinks", filename);
     free(fn);
+#endif
     return xstrdup(filename);
 }
 
@@ -848,57 +852,16 @@ english_list_delimiter(size_t index, size_t total)
             : " and ");
 }
 
-/* Given a 32 bit word 'n', calculates floor(log_2('n')).  This is equivalent
- * to finding the bit position of the most significant one bit in 'n'.  It is
- * an error to call this function with 'n' == 0. */
-int
-log_2_floor(uint32_t n)
-{
-    ovs_assert(n);
-
-#if !defined(UINT_MAX) || !defined(UINT32_MAX)
-#error "Someone screwed up the #includes."
-#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
-    return 31 - __builtin_clz(n);
-#else
-    {
-        int log = 0;
-
-#define BIN_SEARCH_STEP(BITS)                   \
-        if (n >= (1 << BITS)) {                 \
-            log += BITS;                        \
-            n >>= BITS;                         \
-        }
-        BIN_SEARCH_STEP(16);
-        BIN_SEARCH_STEP(8);
-        BIN_SEARCH_STEP(4);
-        BIN_SEARCH_STEP(2);
-        BIN_SEARCH_STEP(1);
-#undef BIN_SEARCH_STEP
-        return log;
-    }
-#endif
-}
-
-/* Given a 32 bit word 'n', calculates ceil(log_2('n')).  It is an error to
- * call this function with 'n' == 0. */
-int
-log_2_ceil(uint32_t n)
-{
-    return log_2_floor(n) + !is_pow2(n);
-}
-
 /* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
-#if !defined(UINT_MAX) || !defined(UINT32_MAX)
-#error "Someone screwed up the #includes."
-#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX
+#if __GNUC__ >= 4
 /* Defined inline in util.h. */
 #else
-static int
-raw_ctz(uint32_t n)
+/* Returns the number of trailing 0-bits in 'n'.  Undefined if 'n' == 0. */
+int
+raw_ctz(uint64_t n)
 {
-    unsigned int k;
-    int count = 31;
+    uint64_t k;
+    int count = 63;
 
 #define CTZ_STEP(X)                             \
     k = n << (X);                               \
@@ -906,6 +869,7 @@ raw_ctz(uint32_t n)
         count -= X;                             \
         n = k;                                  \
     }
+    CTZ_STEP(32);
     CTZ_STEP(16);
     CTZ_STEP(8);
     CTZ_STEP(4);
@@ -915,16 +879,33 @@ raw_ctz(uint32_t n)
 
     return count;
 }
-#endif
 
-/* Returns the number of 1-bits in 'x', between 0 and 32 inclusive. */
-unsigned int
-popcount(uint32_t x)
+/* Returns the number of leading 0-bits in 'n'.  Undefined if 'n' == 0. */
+int
+raw_clz64(uint64_t n)
 {
-    /* In my testing, this implementation is over twice as fast as any other
-     * portable implementation that I tried, including GCC 4.4
-     * __builtin_popcount(), although nonportable asm("popcnt") was over 50%
-     * faster. */
+    uint64_t k;
+    int count = 63;
+
+#define CLZ_STEP(X)                             \
+    k = n >> (X);                               \
+    if (k) {                                    \
+        count -= X;                             \
+        n = k;                                  \
+    }
+    CLZ_STEP(32);
+    CLZ_STEP(16);
+    CLZ_STEP(8);
+    CLZ_STEP(4);
+    CLZ_STEP(2);
+    CLZ_STEP(1);
+#undef CLZ_STEP
+
+    return count;
+}
+#endif
+
+#if NEED_COUNT_1BITS_8
 #define INIT1(X)                                \
     ((((X) & (1 << 0)) != 0) +                  \
      (((X) & (1 << 1)) != 0) +                  \
@@ -941,15 +922,10 @@ popcount(uint32_t x)
 #define INIT32(X) INIT16(X), INIT16((X) + 16)
 #define INIT64(X) INIT32(X), INIT32((X) + 32)
 
-    static const uint8_t popcount8[256] = {
-        INIT64(0), INIT64(64), INIT64(128), INIT64(192)
-    };
-
-    return (popcount8[x & 0xff] +
-            popcount8[(x >> 8) & 0xff] +
-            popcount8[(x >> 16) & 0xff] +
-            popcount8[x >> 24]);
-}
+const uint8_t count_1bits_8[256] = {
+    INIT64(0), INIT64(64), INIT64(128), INIT64(192)
+};
+#endif
 
 /* Returns true if the 'n' bytes starting at 'p' are zeros. */
 bool
@@ -1406,7 +1382,7 @@ scan_float(const char *s, const struct scan_spec *spec, va_list *args)
     case SCAN_INTMAX_T:
     case SCAN_PTRDIFF_T:
     case SCAN_SIZE_T:
-        NOT_REACHED();
+        OVS_NOT_REACHED();
     }
     return s;
 }
@@ -1511,7 +1487,7 @@ scan_chars(const char *s, const struct scan_spec *spec, va_list *args)
 /* This is an implementation of the standard sscanf() function, with the
  * following exceptions:
  *
- *   - It returns true if the entire template was successfully scanned and
+ *   - It returns true if the entire format was successfully scanned and
  *     converted, false if any conversion failed.
  *
  *   - The standard doesn't define sscanf() behavior when an out-of-range value
@@ -1528,15 +1504,15 @@ scan_chars(const char *s, const struct scan_spec *spec, va_list *args)
  *   - %p is not supported.
  */
 bool
-ovs_scan(const char *s, const char *template, ...)
+ovs_scan(const char *s, const char *format, ...)
 {
     const char *const start = s;
     bool ok = false;
     const char *p;
     va_list args;
 
-    va_start(args, template);
-    p = template;
+    va_start(args, format);
+    p = format;
     while (*p != '\0') {
         struct scan_spec spec;
         unsigned char c = *p++;
@@ -1688,3 +1664,24 @@ exit:
     return ok;
 }
 
+#ifdef _WIN32
+\f
+char *
+ovs_format_message(int error)
+{
+    enum { BUFSIZE = sizeof strerror_buffer_get()->s };
+    char *buffer = strerror_buffer_get()->s;
+
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL, error, 0, buffer, BUFSIZE, NULL);
+    return buffer;
+}
+
+/* Returns a null-terminated string that explains the last error.
+ * Use this function to get the error string for WINAPI calls. */
+char *
+ovs_lasterror_to_string(void)
+{
+    return ovs_format_message(GetLastError());
+}
+#endif