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 21 namespace __sanitizer { 22 23 class FlagHandlerBase { 24 public: 25 virtual bool Parse(const char *value) { return false; } 26 }; 27 28 template <typename T> 29 class 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 37 template <> 38 inline bool FlagHandler<bool>::Parse(const char *value) { 39 if (internal_strcmp(value, "0") == 0 || 40 internal_strcmp(value, "no") == 0 || 41 internal_strcmp(value, "false") == 0) { 42 *t_ = false; 43 return true; 44 } 45 if (internal_strcmp(value, "1") == 0 || 46 internal_strcmp(value, "yes") == 0 || 47 internal_strcmp(value, "true") == 0) { 48 *t_ = true; 49 return true; 50 } 51 Printf("ERROR: Invalid value for bool option: '%s'\n", value); 52 return false; 53 } 54 55 template <> 56 inline bool FlagHandler<const char *>::Parse(const char *value) { 57 *t_ = internal_strdup(value); 58 return true; 59 } 60 61 template <> 62 inline bool FlagHandler<int>::Parse(const char *value) { 63 char *value_end; 64 *t_ = internal_simple_strtoll(value, &value_end, 10); 65 bool ok = *value_end == 0; 66 if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value); 67 return ok; 68 } 69 70 template <> 71 inline bool FlagHandler<uptr>::Parse(const char *value) { 72 char *value_end; 73 *t_ = internal_simple_strtoll(value, &value_end, 10); 74 bool ok = *value_end == 0; 75 if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value); 76 return ok; 77 } 78 79 class FlagParser { 80 static const int kMaxFlags = 200; 81 struct Flag { 82 const char *name; 83 const char *desc; 84 FlagHandlerBase *handler; 85 } *flags_; 86 int n_flags_; 87 88 const char *buf_; 89 uptr pos_; 90 91 public: 92 FlagParser(); 93 void RegisterHandler(const char *name, FlagHandlerBase *handler, 94 const char *desc); 95 void ParseString(const char *s); 96 bool ParseFile(const char *path, bool ignore_missing); 97 void PrintFlagDescriptions(); 98 99 static LowLevelAllocator Alloc; 100 101 private: 102 void fatal_error(const char *err); 103 bool is_space(char c); 104 void skip_whitespace(); 105 void parse_flags(); 106 void parse_flag(); 107 bool run_handler(const char *name, const char *value); 108 char *ll_strndup(const char *s, uptr n); 109 }; 110 111 template <typename T> 112 static void RegisterFlag(FlagParser *parser, const char *name, const char *desc, 113 T *var) { 114 FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); // NOLINT 115 parser->RegisterHandler(name, fh, desc); 116 } 117 118 void ReportUnrecognizedFlags(); 119 120 } // namespace __sanitizer 121 122 #endif // SANITIZER_FLAG_REGISTRY_H 123