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