| // Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #ifndef RUNTIME_BIN_OPTIONS_H_ | 
 | #define RUNTIME_BIN_OPTIONS_H_ | 
 |  | 
 | #include "bin/dartutils.h" | 
 | #include "platform/globals.h" | 
 | #include "platform/hashmap.h" | 
 | #include "platform/syslog.h" | 
 |  | 
 | namespace dart { | 
 | namespace bin { | 
 |  | 
 | typedef bool (*OptionProcessorCallback)(const char* arg, | 
 |                                         CommandLineOptions* vm_options); | 
 |  | 
 | class OptionProcessor { | 
 |  public: | 
 |   OptionProcessor() : next_(first_) { first_ = this; } | 
 |  | 
 |   virtual ~OptionProcessor() {} | 
 |  | 
 |   // Returns true if name starts with "--". | 
 |   static bool IsValidFlag(const char* name); | 
 |  | 
 |   // Returns true if name starts with "-". | 
 |   static bool IsValidShortFlag(const char* name); | 
 |  | 
 |   virtual bool Process(const char* option, CommandLineOptions* options) = 0; | 
 |  | 
 |   static bool TryProcess(const char* option, CommandLineOptions* options); | 
 |  | 
 |   static const char* ProcessOption(const char* option, const char* name); | 
 |  | 
 |   static bool ProcessEnvironmentOption(const char* arg, | 
 |                                        CommandLineOptions* vm_options, | 
 |                                        dart::SimpleHashMap** environment); | 
 |  | 
 |  private: | 
 |   static OptionProcessor* first_; | 
 |   OptionProcessor* next_; | 
 |  | 
 |   DISALLOW_ALLOCATION(); | 
 |   DISALLOW_COPY_AND_ASSIGN(OptionProcessor); | 
 | }; | 
 |  | 
 | class CallbackOptionProcessor : public OptionProcessor { | 
 |  public: | 
 |   explicit CallbackOptionProcessor(OptionProcessorCallback cb) : cb_(cb) {} | 
 |   virtual bool Process(const char* option, CommandLineOptions* vm_options) { | 
 |     return cb_(option, vm_options); | 
 |   } | 
 |  | 
 |  private: | 
 |   OptionProcessorCallback cb_; | 
 | }; | 
 |  | 
 | #define DEFINE_CB_OPTION(callback)                                             \ | 
 |   static CallbackOptionProcessor option_##callback(&callback); | 
 |  | 
 | #define DEFINE_STRING_OPTION_CB(name, callback)                                \ | 
 |   class OptionProcessor_##name : public OptionProcessor {                      \ | 
 |    public:                                                                     \ | 
 |     virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ | 
 |       const char* value =                                                      \ | 
 |           OptionProcessor::ProcessOption(option, "--" #name "=");              \ | 
 |       if (value == nullptr) {                                                  \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value == '\0') {                                                    \ | 
 |         Syslog::PrintErr("Empty value for option " #name "\n");                \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       callback;                                                                \ | 
 |       return true;                                                             \ | 
 |     }                                                                          \ | 
 |   };                                                                           \ | 
 |   static OptionProcessor_##name option_##name; | 
 |  | 
 | #define DEFINE_STRING_OPTION(name, variable)                                   \ | 
 |   DEFINE_STRING_OPTION_CB(name, { variable = value; }) | 
 |  | 
 | #define DEFINE_ENUM_OPTION(name, enum_name, variable)                          \ | 
 |   DEFINE_STRING_OPTION_CB(name, {                                              \ | 
 |     const char* const* kNames = k##enum_name##Names;                           \ | 
 |     for (intptr_t i = 0; kNames[i] != nullptr; i++) {                          \ | 
 |       if (strcmp(value, kNames[i]) == 0) {                                     \ | 
 |         variable = static_cast<enum_name>(i);                                  \ | 
 |         return true;                                                           \ | 
 |       }                                                                        \ | 
 |     }                                                                          \ | 
 |     Syslog::PrintErr(                                                          \ | 
 |         "Unrecognized value for " #name ": '%s'\nValid values are: ", value);  \ | 
 |     for (intptr_t i = 0; kNames[i] != nullptr; i++) {                          \ | 
 |       Syslog::PrintErr("%s%s", i > 0 ? ", " : "", kNames[i]);                  \ | 
 |     }                                                                          \ | 
 |     Syslog::PrintErr("\n");                                                    \ | 
 |   }) | 
 |  | 
 | #define DEFINE_BOOL_OPTION_CB(name, callback)                                  \ | 
 |   class OptionProcessor_##name : public OptionProcessor {                      \ | 
 |    public:                                                                     \ | 
 |     virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ | 
 |       const char* value = OptionProcessor::ProcessOption(option, "--" #name);  \ | 
 |       if (value == nullptr) {                                                  \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value == '=') {                                                     \ | 
 |         Syslog::PrintErr("Non-empty value for option " #name "\n");            \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value != '\0') {                                                    \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       callback(vm_options);                                                    \ | 
 |       return true;                                                             \ | 
 |     }                                                                          \ | 
 |   };                                                                           \ | 
 |   static OptionProcessor_##name option_##name; | 
 |  | 
 | #define DEFINE_BOOL_OPTION(name, variable)                                     \ | 
 |   class OptionProcessor_##name : public OptionProcessor {                      \ | 
 |    public:                                                                     \ | 
 |     virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ | 
 |       const char* value = OptionProcessor::ProcessOption(option, "--" #name);  \ | 
 |       if (value == nullptr) {                                                  \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value == '=') {                                                     \ | 
 |         Syslog::PrintErr("Non-empty value for option " #name "\n");            \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value != '\0') {                                                    \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       variable = true;                                                         \ | 
 |       return true;                                                             \ | 
 |     }                                                                          \ | 
 |   };                                                                           \ | 
 |   static OptionProcessor_##name option_##name; | 
 |  | 
 | #define DEFINE_BOOL_OPTION_SHORT(short_name, long_name, variable)              \ | 
 |   class OptionProcessor_##long_name : public OptionProcessor {                 \ | 
 |    public:                                                                     \ | 
 |     virtual bool Process(const char* option, CommandLineOptions* vm_options) { \ | 
 |       const char* value =                                                      \ | 
 |           OptionProcessor::ProcessOption(option, "-" #short_name);             \ | 
 |       if (value == nullptr) {                                                  \ | 
 |         value = OptionProcessor::ProcessOption(option, "--" #long_name);       \ | 
 |       }                                                                        \ | 
 |       if (value == nullptr) {                                                  \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value == '=') {                                                     \ | 
 |         Syslog::PrintErr("Non-empty value for option " #long_name "\n");       \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       if (*value != '\0') {                                                    \ | 
 |         return false;                                                          \ | 
 |       }                                                                        \ | 
 |       variable = true;                                                         \ | 
 |       return true;                                                             \ | 
 |     }                                                                          \ | 
 |   };                                                                           \ | 
 |   static OptionProcessor_##long_name option_##long_name; | 
 |  | 
 | }  // namespace bin | 
 | }  // namespace dart | 
 |  | 
 | #endif  // RUNTIME_BIN_OPTIONS_H_ |