[Sanitizer] move flag parsing routines (and unit tests) from tsan runtime to common runtime.

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@159928 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/sanitizer_common/sanitizer_flags.cc b/lib/sanitizer_common/sanitizer_flags.cc
new file mode 100644
index 0000000..cdeeb78
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_flags.cc
@@ -0,0 +1,82 @@
+//===-- sanitizer_flags.cc ------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_flags.h"
+
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+
+namespace __sanitizer {
+
+static char *GetFlagValue(const char *env, const char *name) {
+  if (env == 0)
+    return 0;
+  const char *pos = internal_strstr(env, name);
+  const char *end;
+  if (pos == 0)
+    return 0;
+  pos += internal_strlen(name);
+  if (pos[0] != '=') {
+    end = pos;
+  } else {
+    pos += 1;
+    if (pos[0] == '"') {
+      pos += 1;
+      end = internal_strchr(pos, '"');
+    } else if (pos[0] == '\'') {
+      pos += 1;
+      end = internal_strchr(pos, '\'');
+    } else {
+      end = internal_strchr(pos, ' ');
+    }
+    if (end == 0)
+      end = pos + internal_strlen(pos);
+  }
+  int len = end - pos;
+  char *f = (char*)InternalAlloc(len + 1);
+  internal_memcpy(f, pos, len);
+  f[len] = '\0';
+  return f;
+}
+
+void ParseFlag(const char *env, bool *flag, const char *name) {
+  char *val = GetFlagValue(env, name);
+  if (val == 0)
+    return;
+  if (0 == internal_strcmp(val, "0") ||
+      0 == internal_strcmp(val, "no") ||
+      0 == internal_strcmp(val, "false"))
+    *flag = false;
+  if (0 == internal_strcmp(val, "1") ||
+      0 == internal_strcmp(val, "yes") ||
+      0 == internal_strcmp(val, "true"))
+    *flag = true;
+  InternalFree(val);
+}
+
+void ParseFlag(const char *env, int *flag, const char *name) {
+  char *val = GetFlagValue(env, name);
+  if (val == 0)
+    return;
+  *flag = internal_atoll(val);
+  InternalFree(val);
+}
+
+void ParseFlag(const char *env, const char **flag, const char *name) {
+  const char *val = GetFlagValue(env, name);
+  if (val == 0)
+    return;
+  *flag = val;
+}
+
+}  // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_flags.h b/lib/sanitizer_common/sanitizer_flags.h
new file mode 100644
index 0000000..43afe82
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_flags.h
@@ -0,0 +1,27 @@
+//===-- sanitizer_flags.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_FLAGS_H
+#define SANITIZER_FLAGS_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+void ParseFlag(const char *env, bool *flag, const char *name);
+void ParseFlag(const char *env, int *flag, const char *name);
+void ParseFlag(const char *env, const char **flag, const char *name);
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_FLAGS_H
diff --git a/lib/tsan/Makefile.old b/lib/tsan/Makefile.old
index 4ee928c..7bcc84e 100644
--- a/lib/tsan/Makefile.old
+++ b/lib/tsan/Makefile.old
@@ -43,7 +43,7 @@
 libtsan:
 	$(MAKE) -C rtl -f Makefile.old DEBUG=$(DEBUG)
 
-%.o: %.cc $(UNIT_TEST_HDR)
+%.o: %.cc $(UNIT_TEST_HDR) libtsan
 	$(CXX) $(CXXFLAGS) $(CFLAGS) $(INCLUDES) -o $@ -c $<
 
 tsan_test: $(UNIT_TEST_OBJ) $(RTL_TEST_OBJ) \
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index f2987c4..11a5ce6 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "sanitizer_common/sanitizer_flags.h"
 #include "sanitizer_common/sanitizer_libc.h"
 #include "tsan_flags.h"
 #include "tsan_rtl.h"
@@ -18,10 +19,6 @@
 
 namespace __tsan {
 
-static void Flag(const char *env, bool *flag, const char *name);
-static void Flag(const char *env, int *flag, const char *name);
-static void Flag(const char *env, const char **flag, const char *name);
-
 Flags *flags() {
   return &CTX()->flags;
 }
@@ -57,92 +54,22 @@
   OverrideFlags(f);
 
   // Override from command line.
-  Flag(env, &f->enable_annotations, "enable_annotations");
-  Flag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
-  Flag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
-  Flag(env, &f->report_thread_leaks, "report_thread_leaks");
-  Flag(env, &f->report_signal_unsafe, "report_signal_unsafe");
-  Flag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
-  Flag(env, &f->strip_path_prefix, "strip_path_prefix");
-  Flag(env, &f->suppressions, "suppressions");
-  Flag(env, &f->exitcode, "exitcode");
-  Flag(env, &f->log_fileno, "log_fileno");
-  Flag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
-  Flag(env, &f->verbosity, "verbosity");
-  Flag(env, &f->profile_memory, "profile_memory");
-  Flag(env, &f->flush_memory_ms, "flush_memory_ms");
-  Flag(env, &f->stop_on_start, "stop_on_start");
-  Flag(env, &f->use_internal_symbolizer, "use_internal_symbolizer");
-}
-
-static const char *GetFlagValue(const char *env, const char *name,
-                                const char **end) {
-  if (env == 0)
-    return *end = 0;
-  const char *pos = internal_strstr(env, name);
-  if (pos == 0)
-    return *end = 0;
-  pos += internal_strlen(name);
-  if (pos[0] != '=')
-    return *end = pos;
-  pos += 1;
-  if (pos[0] == '"') {
-    pos += 1;
-    *end = internal_strchr(pos, '"');
-  } else if (pos[0] == '\'') {
-    pos += 1;
-    *end = internal_strchr(pos, '\'');
-  } else {
-    *end = internal_strchr(pos, ' ');
-  }
-  if (*end == 0)
-    *end = pos + internal_strlen(pos);
-  return pos;
-}
-
-static void Flag(const char *env, bool *flag, const char *name) {
-  const char *end = 0;
-  const char *val = GetFlagValue(env, name, &end);
-  if (val == 0)
-    return;
-  int len = end - val;
-  if (len == 1 && val[0] == '0')
-    *flag = false;
-  else if (len == 1 && val[0] == '1')
-    *flag = true;
-}
-
-static void Flag(const char *env, int *flag, const char *name) {
-  const char *end = 0;
-  const char *val = GetFlagValue(env, name, &end);
-  if (val == 0)
-    return;
-  bool minus = false;
-  if (val != end && val[0] == '-') {
-    minus = true;
-    val += 1;
-  }
-  int v = 0;
-  for (; val != end; val++) {
-    if (val[0] < '0' || val[0] > '9')
-      break;
-    v = v * 10 + val[0] - '0';
-  }
-  if (minus)
-    v = -v;
-  *flag = v;
-}
-
-static void Flag(const char *env, const char **flag, const char *name) {
-  const char *end = 0;
-  const char *val = GetFlagValue(env, name, &end);
-  if (val == 0)
-    return;
-  int len = end - val;
-  char *f = (char*)internal_alloc(MBlockFlag, len + 1);
-  internal_memcpy(f, val, len);
-  f[len] = 0;
-  *flag = f;
+  ParseFlag(env, &f->enable_annotations, "enable_annotations");
+  ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks");
+  ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses");
+  ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks");
+  ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe");
+  ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
+  ParseFlag(env, &f->strip_path_prefix, "strip_path_prefix");
+  ParseFlag(env, &f->suppressions, "suppressions");
+  ParseFlag(env, &f->exitcode, "exitcode");
+  ParseFlag(env, &f->log_fileno, "log_fileno");
+  ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
+  ParseFlag(env, &f->verbosity, "verbosity");
+  ParseFlag(env, &f->profile_memory, "profile_memory");
+  ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
+  ParseFlag(env, &f->stop_on_start, "stop_on_start");
+  ParseFlag(env, &f->use_internal_symbolizer, "use_internal_symbolizer");
 }
 
 }  // namespace __tsan
diff --git a/lib/tsan/unit_tests/tsan_flags_test.cc b/lib/tsan/unit_tests/tsan_flags_test.cc
index 00af64b..d344cb5 100644
--- a/lib/tsan/unit_tests/tsan_flags_test.cc
+++ b/lib/tsan/unit_tests/tsan_flags_test.cc
@@ -24,78 +24,15 @@
   InitializeFlags(&f, "");
 }
 
-TEST(Flags, ParseBool) {
+TEST(Flags, DefaultValues) {
   ScopedInRtl in_rtl;
   Flags f = {};
 
   f.enable_annotations = false;
-  InitializeFlags(&f, "enable_annotations");
-  EXPECT_EQ(f.enable_annotations, true);
-
-  f.enable_annotations = false;
-  InitializeFlags(&f, "--enable_annotations");
-  EXPECT_EQ(f.enable_annotations, true);
-
-  f.enable_annotations = false;
-  InitializeFlags(&f, "--enable_annotations=1");
-  EXPECT_EQ(f.enable_annotations, true);
-
-  // This flag is false by default.
-  f.force_seq_cst_atomics = false;
-  InitializeFlags(&f, "--force_seq_cst_atomics=1");
-  EXPECT_EQ(f.force_seq_cst_atomics, true);
-
-  f.enable_annotations = true;
-  InitializeFlags(&f, "asdas enable_annotations=0 asdasd");
-  EXPECT_EQ(f.enable_annotations, false);
-
-  f.enable_annotations = true;
-  InitializeFlags(&f, "   --enable_annotations=0   ");
-  EXPECT_EQ(f.enable_annotations, false);
-}
-
-TEST(Flags, ParseInt) {
-  ScopedInRtl in_rtl;
-  Flags f = {};
-
   f.exitcode = -11;
-  InitializeFlags(&f, "exitcode");
-  EXPECT_EQ(f.exitcode, 0);
-
-  f.exitcode = -11;
-  InitializeFlags(&f, "--exitcode=");
-  EXPECT_EQ(f.exitcode, 0);
-
-  f.exitcode = -11;
-  InitializeFlags(&f, "--exitcode=42");
-  EXPECT_EQ(f.exitcode, 42);
-
-  f.exitcode = -11;
-  InitializeFlags(&f, "--exitcode=-42");
-  EXPECT_EQ(f.exitcode, -42);
-}
-
-TEST(Flags, ParseStr) {
-  ScopedInRtl in_rtl;
-  Flags f = {};
-
-  InitializeFlags(&f, 0);
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
-
-  InitializeFlags(&f, "strip_path_prefix");
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
-
-  InitializeFlags(&f, "--strip_path_prefix=");
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, ""));
-
-  InitializeFlags(&f, "--strip_path_prefix=abc");
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc"));
-
-  InitializeFlags(&f, "--strip_path_prefix='abc zxc'");
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc zxc"));
-
-  InitializeFlags(&f, "--strip_path_prefix=\"abc zxc\"");
-  EXPECT_EQ(0, strcmp(f.strip_path_prefix, "abc zxc"));
+  InitializeFlags(&f, "");
+  EXPECT_EQ(66, f.exitcode);
+  EXPECT_EQ(true, f.enable_annotations);
 }
 
 }  // namespace __tsan