1//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
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#ifndef SANITIZER_FLAG_REGISTRY_H
15#define SANITIZER_FLAG_REGISTRY_H
16
17#include "sanitizer_internal_defs.h"
18#include "sanitizer_libc.h"
19#include "sanitizer_common.h"
20
21namespace __sanitizer {
22
23class FlagHandlerBase {
24 public:
25  virtual bool Parse(const char *value) { return false; }
26};
27
28template <typename T>
29class FlagHandler : public FlagHandlerBase {
30  T *t_;
31
32 public:
33  explicit FlagHandler(T *t) : t_(t) {}
34  bool Parse(const char *value) final;
35};
36
37inline bool ParseBool(const char *value, bool *b) {
38  if (internal_strcmp(value, "0") == 0 ||
39      internal_strcmp(value, "no") == 0 ||
40      internal_strcmp(value, "false") == 0) {
41    *b = false;
42    return true;
43  }
44  if (internal_strcmp(value, "1") == 0 ||
45      internal_strcmp(value, "yes") == 0 ||
46      internal_strcmp(value, "true") == 0) {
47    *b = true;
48    return true;
49  }
50  return false;
51}
52
53template <>
54inline bool FlagHandler<bool>::Parse(const char *value) {
55  if (ParseBool(value, t_)) return true;
56  Printf("ERROR: Invalid value for bool option: '%s'\n", value);
57  return false;
58}
59
60template <>
61inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
62  bool b;
63  if (ParseBool(value, &b)) {
64    *t_ = b ? kHandleSignalYes : kHandleSignalNo;
65    return true;
66  }
67  if (internal_strcmp(value, "2") == 0 ||
68      internal_strcmp(value, "exclusive") == 0) {
69    *t_ = kHandleSignalExclusive;
70    return true;
71  }
72  Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
73  return false;
74}
75
76template <>
77inline bool FlagHandler<const char *>::Parse(const char *value) {
78  *t_ = value;
79  return true;
80}
81
82template <>
83inline bool FlagHandler<int>::Parse(const char *value) {
84  const char *value_end;
85  *t_ = internal_simple_strtoll(value, &value_end, 10);
86  bool ok = *value_end == 0;
87  if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
88  return ok;
89}
90
91template <>
92inline bool FlagHandler<uptr>::Parse(const char *value) {
93  const char *value_end;
94  *t_ = internal_simple_strtoll(value, &value_end, 10);
95  bool ok = *value_end == 0;
96  if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
97  return ok;
98}
99
100class FlagParser {
101  static const int kMaxFlags = 200;
102  struct Flag {
103    const char *name;
104    const char *desc;
105    FlagHandlerBase *handler;
106  } *flags_;
107  int n_flags_;
108
109  const char *buf_;
110  uptr pos_;
111
112 public:
113  FlagParser();
114  void RegisterHandler(const char *name, FlagHandlerBase *handler,
115                       const char *desc);
116  void ParseString(const char *s);
117  bool ParseFile(const char *path, bool ignore_missing);
118  void PrintFlagDescriptions();
119
120  static LowLevelAllocator Alloc;
121
122 private:
123  void fatal_error(const char *err);
124  bool is_space(char c);
125  void skip_whitespace();
126  void parse_flags();
127  void parse_flag();
128  bool run_handler(const char *name, const char *value);
129  char *ll_strndup(const char *s, uptr n);
130};
131
132template <typename T>
133static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
134                         T *var) {
135  FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);  // NOLINT
136  parser->RegisterHandler(name, fh, desc);
137}
138
139void ReportUnrecognizedFlags();
140
141}  // namespace __sanitizer
142
143#endif  // SANITIZER_FLAG_REGISTRY_H
144