Home | History | Annotate | Line # | Download | only in sanitizer_common
      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