Home | History | Annotate | 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 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