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