(root)/
gcc-13.2.0/
libsanitizer/
sanitizer_common/
sanitizer_flag_parser.h
       1  //===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
       2  //
       3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4  // See https://llvm.org/LICENSE.txt for license information.
       5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6  //
       7  //===----------------------------------------------------------------------===//
       8  //
       9  // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
      10  //
      11  //===----------------------------------------------------------------------===//
      12  
      13  #ifndef SANITIZER_FLAG_REGISTRY_H
      14  #define SANITIZER_FLAG_REGISTRY_H
      15  
      16  #include "sanitizer_internal_defs.h"
      17  #include "sanitizer_libc.h"
      18  #include "sanitizer_common.h"
      19  
      20  namespace __sanitizer {
      21  
      22  class FlagHandlerBase {
      23   public:
      24    virtual bool Parse(const char *value) { return false; }
      25    // Write the C string representation of the current value (truncated to fit)
      26    // into the buffer of size `size`. Returns false if truncation occurred and
      27    // returns true otherwise.
      28    virtual bool Format(char *buffer, uptr size) {
      29      if (size > 0)
      30        buffer[0] = '\0';
      31      return false;
      32    }
      33  
      34   protected:
      35    ~FlagHandlerBase() {}
      36  
      37    inline bool FormatString(char *buffer, uptr size, const char *str_to_use) {
      38      uptr num_symbols_should_write =
      39          internal_snprintf(buffer, size, "%s", str_to_use);
      40      return num_symbols_should_write < size;
      41    }
      42  };
      43  
      44  template <typename T>
      45  class FlagHandler final : public FlagHandlerBase {
      46    T *t_;
      47  
      48   public:
      49    explicit FlagHandler(T *t) : t_(t) {}
      50    bool Parse(const char *value) final;
      51    bool Format(char *buffer, uptr size) final;
      52  };
      53  
      54  inline bool ParseBool(const char *value, bool *b) {
      55    if (internal_strcmp(value, "0") == 0 ||
      56        internal_strcmp(value, "no") == 0 ||
      57        internal_strcmp(value, "false") == 0) {
      58      *b = false;
      59      return true;
      60    }
      61    if (internal_strcmp(value, "1") == 0 ||
      62        internal_strcmp(value, "yes") == 0 ||
      63        internal_strcmp(value, "true") == 0) {
      64      *b = true;
      65      return true;
      66    }
      67    return false;
      68  }
      69  
      70  template <>
      71  inline bool FlagHandler<bool>::Parse(const char *value) {
      72    if (ParseBool(value, t_)) return true;
      73    Printf("ERROR: Invalid value for bool option: '%s'\n", value);
      74    return false;
      75  }
      76  
      77  template <>
      78  inline bool FlagHandler<bool>::Format(char *buffer, uptr size) {
      79    return FormatString(buffer, size, *t_ ? "true" : "false");
      80  }
      81  
      82  template <>
      83  inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
      84    bool b;
      85    if (ParseBool(value, &b)) {
      86      *t_ = b ? kHandleSignalYes : kHandleSignalNo;
      87      return true;
      88    }
      89    if (internal_strcmp(value, "2") == 0 ||
      90        internal_strcmp(value, "exclusive") == 0) {
      91      *t_ = kHandleSignalExclusive;
      92      return true;
      93    }
      94    Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
      95    return false;
      96  }
      97  
      98  template <>
      99  inline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) {
     100    uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
     101    return num_symbols_should_write < size;
     102  }
     103  
     104  template <>
     105  inline bool FlagHandler<const char *>::Parse(const char *value) {
     106    *t_ = value;
     107    return true;
     108  }
     109  
     110  template <>
     111  inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) {
     112    return FormatString(buffer, size, *t_);
     113  }
     114  
     115  template <>
     116  inline bool FlagHandler<int>::Parse(const char *value) {
     117    const char *value_end;
     118    *t_ = internal_simple_strtoll(value, &value_end, 10);
     119    bool ok = *value_end == 0;
     120    if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
     121    return ok;
     122  }
     123  
     124  template <>
     125  inline bool FlagHandler<int>::Format(char *buffer, uptr size) {
     126    uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
     127    return num_symbols_should_write < size;
     128  }
     129  
     130  template <>
     131  inline bool FlagHandler<uptr>::Parse(const char *value) {
     132    const char *value_end;
     133    *t_ = internal_simple_strtoll(value, &value_end, 10);
     134    bool ok = *value_end == 0;
     135    if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
     136    return ok;
     137  }
     138  
     139  template <>
     140  inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
     141    uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_);
     142    return num_symbols_should_write < size;
     143  }
     144  
     145  template <>
     146  inline bool FlagHandler<s64>::Parse(const char *value) {
     147    const char *value_end;
     148    *t_ = internal_simple_strtoll(value, &value_end, 10);
     149    bool ok = *value_end == 0;
     150    if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value);
     151    return ok;
     152  }
     153  
     154  template <>
     155  inline bool FlagHandler<s64>::Format(char *buffer, uptr size) {
     156    uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_);
     157    return num_symbols_should_write < size;
     158  }
     159  
     160  class FlagParser {
     161    static const int kMaxFlags = 200;
     162    struct Flag {
     163      const char *name;
     164      const char *desc;
     165      FlagHandlerBase *handler;
     166    } *flags_;
     167    int n_flags_;
     168  
     169    const char *buf_;
     170    uptr pos_;
     171  
     172   public:
     173    FlagParser();
     174    void RegisterHandler(const char *name, FlagHandlerBase *handler,
     175                         const char *desc);
     176    void ParseString(const char *s, const char *env_name = 0);
     177    void ParseStringFromEnv(const char *env_name);
     178    bool ParseFile(const char *path, bool ignore_missing);
     179    void PrintFlagDescriptions();
     180  
     181    static LowLevelAllocator Alloc;
     182  
     183   private:
     184    void fatal_error(const char *err);
     185    bool is_space(char c);
     186    void skip_whitespace();
     187    void parse_flags(const char *env_option_name);
     188    void parse_flag(const char *env_option_name);
     189    bool run_handler(const char *name, const char *value);
     190    char *ll_strndup(const char *s, uptr n);
     191  };
     192  
     193  template <typename T>
     194  static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
     195                           T *var) {
     196    FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
     197    parser->RegisterHandler(name, fh, desc);
     198  }
     199  
     200  void ReportUnrecognizedFlags();
     201  
     202  }  // namespace __sanitizer
     203  
     204  #endif  // SANITIZER_FLAG_REGISTRY_H