1//===-- sanitizer_flags.cc ------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_flags.h"
15
16#include "sanitizer_common.h"
17#include "sanitizer_libc.h"
18
19namespace __sanitizer {
20
21static bool GetFlagValue(const char *env, const char *name,
22                         const char **value, int *value_length) {
23  if (env == 0)
24    return false;
25  const char *pos = internal_strstr(env, name);
26  const char *end;
27  if (pos == 0)
28    return false;
29  pos += internal_strlen(name);
30  if (pos[0] != '=') {
31    end = pos;
32  } else {
33    pos += 1;
34    if (pos[0] == '"') {
35      pos += 1;
36      end = internal_strchr(pos, '"');
37    } else if (pos[0] == '\'') {
38      pos += 1;
39      end = internal_strchr(pos, '\'');
40    } else {
41      end = internal_strchr(pos, ' ');
42    }
43    if (end == 0)
44      end = pos + internal_strlen(pos);
45  }
46  *value = pos;
47  *value_length = end - pos;
48  return true;
49}
50
51static bool StartsWith(const char *flag, int flag_length, const char *value) {
52  if (!flag || !value)
53    return false;
54  int value_length = internal_strlen(value);
55  return (flag_length >= value_length) &&
56         (0 == internal_strncmp(flag, value, value_length));
57}
58
59void ParseFlag(const char *env, bool *flag, const char *name) {
60  const char *value;
61  int value_length;
62  if (!GetFlagValue(env, name, &value, &value_length))
63    return;
64  if (StartsWith(value, value_length, "0") ||
65      StartsWith(value, value_length, "no") ||
66      StartsWith(value, value_length, "false"))
67    *flag = false;
68  if (StartsWith(value, value_length, "1") ||
69      StartsWith(value, value_length, "yes") ||
70      StartsWith(value, value_length, "true"))
71    *flag = true;
72}
73
74void ParseFlag(const char *env, int *flag, const char *name) {
75  const char *value;
76  int value_length;
77  if (!GetFlagValue(env, name, &value, &value_length))
78    return;
79  *flag = internal_atoll(value);
80}
81
82static LowLevelAllocator allocator_for_flags;
83
84void ParseFlag(const char *env, const char **flag, const char *name) {
85  const char *value;
86  int value_length;
87  if (!GetFlagValue(env, name, &value, &value_length))
88    return;
89  // Copy the flag value. Don't use locks here, as flags are parsed at
90  // tool startup.
91  char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1));
92  internal_memcpy(value_copy, value, value_length);
93  value_copy[value_length] = '\0';
94  *flag = value_copy;
95}
96
97}  // namespace __sanitizer
98