186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//                     The LLVM Compiler Infrastructure
486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is distributed under the University of Illinois Open Source
686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// License. See LICENSE.TXT for details.
786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===//
986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
1086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===//
1386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_FLAG_REGISTRY_H
1586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define SANITIZER_FLAG_REGISTRY_H
1686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
1786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_internal_defs.h"
1886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_libc.h"
1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common.h"
2086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __sanitizer {
2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass FlagHandlerBase {
2486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines public:
2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  virtual bool Parse(const char *value) { return false; }
2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <typename T>
2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass FlagHandler : public FlagHandlerBase {
3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  T *t_;
3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines public:
3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  explicit FlagHandler(T *t) : t_(t) {}
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool Parse(const char *value) final;
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <>
3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesinline bool FlagHandler<bool>::Parse(const char *value) {
3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (internal_strcmp(value, "0") == 0 ||
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      internal_strcmp(value, "no") == 0 ||
4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      internal_strcmp(value, "false") == 0) {
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    *t_ = false;
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return true;
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (internal_strcmp(value, "1") == 0 ||
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      internal_strcmp(value, "yes") == 0 ||
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      internal_strcmp(value, "true") == 0) {
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    *t_ = true;
4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return true;
5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  Printf("ERROR: Invalid value for bool option: '%s'\n", value);
5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return false;
5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <>
5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesinline bool FlagHandler<const char *>::Parse(const char *value) {
5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *t_ = internal_strdup(value);
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return true;
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <>
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesinline bool FlagHandler<int>::Parse(const char *value) {
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char *value_end;
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *t_ = internal_simple_strtoll(value, &value_end, 10);
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool ok = *value_end == 0;
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return ok;
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <>
7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesinline bool FlagHandler<uptr>::Parse(const char *value) {
7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char *value_end;
7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *t_ = internal_simple_strtoll(value, &value_end, 10);
7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool ok = *value_end == 0;
7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return ok;
7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesclass FlagParser {
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  static const int kMaxFlags = 200;
8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  struct Flag {
8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    const char *name;
8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    const char *desc;
8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    FlagHandlerBase *handler;
8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } *flags_;
8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int n_flags_;
8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const char *buf_;
8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr pos_;
9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines public:
9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  FlagParser();
9386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void RegisterHandler(const char *name, FlagHandlerBase *handler,
9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                       const char *desc);
9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ParseString(const char *s);
96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  bool ParseFile(const char *path, bool ignore_missing);
9786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void PrintFlagDescriptions();
9886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  static LowLevelAllocator Alloc;
10086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines private:
10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void fatal_error(const char *err);
10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool is_space(char c);
10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void skip_whitespace();
10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void parse_flags();
10686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void parse_flag();
10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool run_handler(const char *name, const char *value);
10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  char *ll_strndup(const char *s, uptr n);
10986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
11086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
11186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestemplate <typename T>
11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                         T *var) {
11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);  // NOLINT
11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  parser->RegisterHandler(name, fh, desc);
11686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ReportUnrecognizedFlags();
11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}  // namespace __sanitizer
12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif  // SANITIZER_FLAG_REGISTRY_H
123