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 inline 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 53 template <> 54 inline 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 60 template <> 61 inline 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 76 template <> 77 inline bool FlagHandler<const char *>::Parse(const char *value) { 78 *t_ = value; 79 return true; 80 } 81 82 template <> 83 inline 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 91 template <> 92 inline 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 100 class 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 132 template <typename T> 133 static 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 139 void ReportUnrecognizedFlags(); 140 141 } // namespace __sanitizer 142 143 #endif // SANITIZER_FLAG_REGISTRY_H 144