Merge pull request #126 from hevy-CC4477/master

Use ```_static``` suffix in filename of static library on Windows to distinguish it from the import library.
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..3e6d358
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,102 @@
+# Bazel build file for gflags
+#
+# See INSTALL.md for instructions for adding gflags to a Bazel workspace.
+
+licenses(["notice"])
+
+cc_library(
+    name = "gflags",
+    srcs = [
+        "src/gflags.cc",
+        "src/gflags_completions.cc",
+        "src/gflags_reporting.cc",
+        "src/mutex.h",
+        "src/util.h",
+        ":config_h",
+        ":gflags_completions_h",
+        ":gflags_declare_h",
+        ":gflags_h",
+        ":includes",
+    ],
+    hdrs = ["gflags.h"],
+    copts = [
+        "-Wno-sign-compare",
+        "-DHAVE_STDINT_H",
+        "-DHAVE_SYS_TYPES_H",
+        "-DHAVE_INTTYPES_H",
+        "-DHAVE_SYS_STAT_H",
+        "-DHAVE_UNISTD_H",
+        "-DHAVE_FNMATCH_H",
+        "-DHAVE_STRTOLL",
+        "-DHAVE_STRTOQ",
+        "-DHAVE_PTHREAD",
+        "-DHAVE_RWLOCK",
+        "-DGFLAGS_INTTYPES_FORMAT_C99",
+    ],
+    includes = [
+        "include",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+genrule(
+    name = "config_h",
+    srcs = [
+        "src/config.h.in",
+    ],
+    outs = [
+        "config.h",
+    ],
+    cmd = "sed -r -e 's,^#cmakedefine,// cmakedefine,' $(<) > $(@)",
+)
+
+genrule(
+    name = "gflags_h",
+    srcs = [
+        "src/gflags.h.in",
+    ],
+    outs = [
+        "gflags.h",
+    ],
+    cmd = "sed -r -e 's/@[A-Z_]+@//' $(<) > $(@)",
+)
+
+genrule(
+    name = "gflags_completions_h",
+    srcs = [
+        "src/gflags_completions.h.in",
+    ],
+    outs = [
+        "gflags_completions.h",
+    ],
+    cmd = "sed -r -e 's/@GFLAGS_NAMESPACE@/gflags/' $(<) > $(@)",
+)
+
+genrule(
+    name = "gflags_declare_h",
+    srcs = [
+        "src/gflags_declare.h.in",
+    ],
+    outs = [
+        "gflags_declare.h",
+    ],
+    cmd = ("sed -r -e '" +
+           "s/@GFLAGS_NAMESPACE@/gflags/;" +
+           "s/@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H" +
+           "|GFLAGS_INTTYPES_FORMAT_C99)@/1/;" +
+           "s/@([A-Z0-9_]+)@/0/" +
+           "' $(<) > $(@)"),
+)
+
+genrule(
+    name = "includes",
+    srcs = [
+        ":gflags_h",
+        ":gflags_declare_h",
+    ],
+    outs = [
+        "include/gflags/gflags.h",
+        "include/gflags/gflags_declare.h",
+    ],
+    cmd = "mkdir -p $(@D)/include/gflags && cp $(SRCS) $(@D)/include/gflags",
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ac6853..21c8660 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,7 +326,7 @@
           PRIVATE "${PROJECT_SOURCE_DIR}/src;${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}"
         )
         if (opts MATCHES "nothreads")
-          set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL};NOTHREADS")
+          set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL};NO_THREADS")
         else ()
           set (defines "GFLAGS_IS_A_DLL=${GFLAGS_IS_A_DLL}")
           if (CMAKE_USE_PTHREADS_INIT)
diff --git a/INSTALL.md b/INSTALL.md
index b89d86d..a206bda 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -11,7 +11,7 @@
     sudo apt-get install gflags
 
 
-Compiling the source code
+Compiling the source code with CMake
 =========================
 
 The build system of gflags is since version 2.1 based on [CMake](http://cmake.org).
@@ -65,3 +65,24 @@
 GFLAGS_INCLUDE_DIR          | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX.
 LIBRARY_INSTALL_DIR         | Name of library installation directory relative to CMAKE_INSTALL_PREFIX.
 INSTALL_HEADERS             | Request installation of public header files.
+
+Using gflags with [Bazel](http://bazel.io)
+=========================
+
+To use gflags in a Bazel project, map it in as an external dependency by editing
+your WORKSPACE file:
+
+    git_repository(
+        name = "gflags_git",
+        commit = "",  # Use the current HEAD commit
+        remote = "https://github.com/gflags/gflags.git",
+    )
+
+    bind(
+        name = "gflags",
+        actual = "@gflags_git//:gflags",
+    )
+
+You can then add `//external:gflags` to the `deps` section of a `cc_binary` or
+`cc_library` rule, and `#include <gflags/gflags.h>` to include it in your source
+code.
diff --git a/doc b/doc
index e1d15b3..16651b7 160000
--- a/doc
+++ b/doc
@@ -1 +1 @@
-Subproject commit e1d15b33406ec571095e7a91dbc4b2ada1ae3bac
+Subproject commit 16651b78706e7ac3a1697146dd3b41f885ac73f1
diff --git a/src/gflags.cc b/src/gflags.cc
index a35bbfe..85b1ef7 100644
--- a/src/gflags.cc
+++ b/src/gflags.cc
@@ -1454,65 +1454,58 @@
 
 // These values are not protected by a Mutex because they are normally
 // set only once during program startup.
-static const char* argv0 = "UNKNOWN";      // just the program name
-static const char* cmdline = "";           // the entire command-line
+static string argv0("UNKNOWN");  // just the program name
+static string cmdline;           // the entire command-line
+static string program_usage;
 static vector<string> argvs;
 static uint32 argv_sum = 0;
-static const char* program_usage = NULL;
 
 void SetArgv(int argc, const char** argv) {
   static bool called_set_argv = false;
-  if (called_set_argv)         // we already have an argv for you
-    return;
-
+  if (called_set_argv) return;
   called_set_argv = true;
 
-  assert(argc > 0);            // every program has at least a progname
-  argv0 = strdup(argv[0]);     // small memory leak, but fn only called once
-  assert(argv0);
+  assert(argc > 0); // every program has at least a name
+  argv0 = argv[0];
 
-  string cmdline_string;       // easier than doing strcats
+  cmdline.clear();
   for (int i = 0; i < argc; i++) {
-    if (i != 0) {
-      cmdline_string += " ";
-    }
-    cmdline_string += argv[i];
+    if (i != 0) cmdline += " ";
+    cmdline += argv[i];
     argvs.push_back(argv[i]);
   }
-  cmdline = strdup(cmdline_string.c_str());  // another small memory leak
-  assert(cmdline);
 
   // Compute a simple sum of all the chars in argv
-  for (const char* c = cmdline; *c; c++)
+  argv_sum = 0;
+  for (string::const_iterator c = cmdline.begin(); c != cmdline.end(); ++c) {
     argv_sum += *c;
+  }
 }
 
 const vector<string>& GetArgvs() { return argvs; }
-const char* GetArgv()            { return cmdline; }
-const char* GetArgv0()           { return argv0; }
+const char* GetArgv()            { return cmdline.c_str(); }
+const char* GetArgv0()           { return argv0.c_str(); }
 uint32 GetArgvSum()              { return argv_sum; }
 const char* ProgramInvocationName() {             // like the GNU libc fn
   return GetArgv0();
 }
 const char* ProgramInvocationShortName() {        // like the GNU libc fn
-  const char* slash = strrchr(argv0, '/');
+  size_t pos = argv0.rfind('/');
 #ifdef OS_WINDOWS
-  if (!slash)  slash = strrchr(argv0, '\\');
+  if (pos == string::npos) pos = argv0.rfind('\\');
 #endif
-  return slash ? slash + 1 : argv0;
+  return (pos == string::npos ? argv0.c_str() : (argv0.c_str() + pos + 1));
 }
 
 void SetUsageMessage(const string& usage) {
-  if (program_usage != NULL)
-    ReportError(DIE, "ERROR: SetUsageMessage() called twice\n");
-  program_usage = strdup(usage.c_str());      // small memory leak
+  program_usage = usage;
 }
 
 const char* ProgramUsage() {
-  if (program_usage) {
-    return program_usage;
+  if (program_usage.empty()) {
+    return "Warning: SetUsageMessage() never called";
   }
-  return "Warning: SetUsageMessage() never called";
+  return program_usage.c_str();
 }
 
 // --------------------------------------------------------------------
@@ -1520,16 +1513,14 @@
 // VersionString()
 // --------------------------------------------------------------------
 
-static const char* version_string = NULL;
+static string version_string;
 
 void SetVersionString(const string& version) {
-  if (version_string != NULL)
-    ReportError(DIE, "ERROR: SetVersionString() called twice\n");
-  version_string = strdup(version.c_str());   // small memory leak
+  version_string = version;
 }
 
 const char* VersionString() {
-  return version_string ? version_string : "";
+  return version_string.c_str();
 }
 
 
diff --git a/src/gflags.h.in b/src/gflags.h.in
index 0324d39..88ab1aa 100644
--- a/src/gflags.h.in
+++ b/src/gflags.h.in
@@ -538,6 +538,26 @@
 }
 inline clstring* dont_pass0toDEFINE_string(char *stringspot,
                                            int value);
+
+// Auxiliary class used to explicitly call destructor of string objects
+// allocated using placement new during static program deinitialization.
+// The destructor MUST be an inline function such that the explicit
+// destruction occurs in the same compilation unit as the placement new.
+class StringFlagDestructor {
+  void *current_storage_;
+  void *defvalue_storage_;
+
+public: 
+
+  StringFlagDestructor(void *current, void *defvalue)
+  : current_storage_(current), defvalue_storage_(defvalue) {}
+
+  ~StringFlagDestructor() {
+    reinterpret_cast<clstring*>(current_storage_ )->~clstring();
+    reinterpret_cast<clstring*>(defvalue_storage_)->~clstring();
+  }
+};
+
 }  // namespace fLS
 
 // We need to define a var named FLAGS_no##name so people don't define
@@ -557,6 +577,7 @@
     static GFLAGS_NAMESPACE::FlagRegisterer o_##name(                       \
         #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__,                \
         s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name));      \
+    static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s);     \
     extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name;                   \
     using fLS::FLAGS_##name;                                                \
     clstring& FLAGS_##name = *FLAGS_no##name;                               \
diff --git a/src/gflags_completions.cc b/src/gflags_completions.cc
index 3a47623..d7097ca 100644
--- a/src/gflags_completions.cc
+++ b/src/gflags_completions.cc
@@ -47,6 +47,8 @@
 //     5b) Trim most flag's descriptions to fit on a single terminal line
 
 
+#include "gflags_completions.h"
+
 #include "config.h"
 
 #include <stdio.h>
diff --git a/src/util.h b/src/util.h
index fb59b38..164e3cf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -37,7 +37,6 @@
 #include "config.h"
 
 #include <assert.h>
-#include <config.h>
 #ifdef HAVE_INTTYPES_H
 #  include <inttypes.h>
 #endif
diff --git a/src/windows_port.cc b/src/windows_port.cc
index 9ccb630..b5b7194 100644
--- a/src/windows_port.cc
+++ b/src/windows_port.cc
@@ -44,6 +44,7 @@
 
 // These call the windows _vsnprintf, but always NUL-terminate.
 #if !defined(__MINGW32__) && !defined(__MINGW64__)  /* mingw already defines */
+#if !(defined(_MSC_VER) && _MSC_VER >= 1900)  /* msvc 2015 already defines */
 
 #ifdef _MSC_VER
 #  pragma warning(push)
@@ -59,8 +60,6 @@
 #  pragma warning(pop)
 #endif
 
-#if _MSC_VER < 1900  // msvs 2015 finally includes snprintf
-
 int snprintf(char *str, size_t size, const char *format, ...) {
   int r;
   va_list ap;
@@ -70,6 +69,5 @@
   return r;
 }
 
-#endif
-
+#endif  /* if !(defined(_MSC_VER) && _MSC_VER >= 1900)  */
 #endif  /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
diff --git a/src/windows_port.h b/src/windows_port.h
index c8ff24f..554b9c9 100644
--- a/src/windows_port.h
+++ b/src/windows_port.h
@@ -63,12 +63,14 @@
  * name vsnprintf, since windows defines that (but not snprintf (!)).
  */
 #if !defined(__MINGW32__) && !defined(__MINGW64__)  /* mingw already defines */
+#if !(defined(_MSC_VER) && _MSC_VER >= 1900)  /* msvc 2015 already defines */
 extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size,
                                        const char *format, ...);
 extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size,
                                              const char *format, va_list ap);
 #define vsnprintf(str, size, format, ap)  safe_vsnprintf(str, size, format, ap)
 #define va_copy(dst, src)  (dst) = (src)
+#endif
 #endif  /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */
 
 #ifdef _MSC_VER
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 77b582f..70644cf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,9 +2,9 @@
 
 # ----------------------------------------------------------------------------
 # output directories
-set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin")
-set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
-set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
+set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/bin")
+set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/lib")
+set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Testing/lib")
 
 # set working directory of test commands
 set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/test/config/main.cc b/test/config/main.cc
index 9b2b898..3c033e3 100644
--- a/test/config/main.cc
+++ b/test/config/main.cc
@@ -3,10 +3,18 @@
 
 DEFINE_string(message, "Hello World!", "The message to print");
 
+static bool ValidateMessage(const char* flagname, const std::string &message)
+{
+  return !message.empty();
+}
+DEFINE_validator(message, ValidateMessage);
+
 int main(int argc, char **argv)
 {
   gflags::SetUsageMessage("Test CMake configuration of gflags library (gflags-config.cmake)");
+  gflags::SetVersionString("0.1");
   gflags::ParseCommandLineFlags(&argc, &argv, true);
   std::cout << FLAGS_message << std::endl;
+  gflags::ShutDownCommandLineFlags();
   return 0;
 }
diff --git a/test/gflags_declare_flags.cc b/test/gflags_declare_flags.cc
index dc53de5..2491686 100644
--- a/test/gflags_declare_flags.cc
+++ b/test/gflags_declare_flags.cc
@@ -3,6 +3,7 @@
 
 DECLARE_string(message); // in gflags_delcare_test.cc
 
+void print_message();
 void print_message()
 {
   std::cout << FLAGS_message << std::endl;
diff --git a/test/gflags_unittest.cc b/test/gflags_unittest.cc
index 80f7398..f205466 100644
--- a/test/gflags_unittest.cc
+++ b/test/gflags_unittest.cc
@@ -1485,7 +1485,7 @@
 
 }  // unnamed namespace
 
-int main(int argc, char **argv) {
+static int main(int argc, char **argv) {
 
   // Run unit tests only if called without arguments, otherwise this program
   // is used by an "external" usage test
@@ -1514,7 +1514,7 @@
   // The non-recommended way:
   FLAGS_changed_bool2 = true;
 
-  SetUsageMessage(usage_message.c_str());
+  SetUsageMessage(usage_message);
   SetVersionString("test_version");
   ParseCommandLineFlags(&argc, &argv, true);
   MakeTmpdir(&FLAGS_test_tmpdir);