1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef MAPLE_UTIL_INCLUDE_PARSER_H 17 #define MAPLE_UTIL_INCLUDE_PARSER_H 18 19 #include <algorithm> 20 #include <map> 21 #include <string> 22 #include <string_view> 23 #include <unordered_map> 24 #include <unordered_set> 25 #include <vector> 26 #include <deque> 27 28 namespace maplecl { 29 30 enum class RetCode { 31 noError, 32 notRegistered, 33 incorrectValue, 34 unnecessaryValue, 35 outOfRange, 36 notSupportedOptionType, 37 valueEmpty, 38 parsingErr, 39 }; 40 41 class OptionInterface; 42 43 using OptionsMapType = std::unordered_map<std::string, OptionInterface *>; 44 45 /* This structure is used to aggregate option information during option parsing. 46 * It's a string view from original input command line string. */ 47 struct KeyArg { KeyArgKeyArg48 explicit KeyArg(std::string_view arg) : rawArg(arg) {} 49 const std::string_view rawArg; /* full option, like "--key=value" */ 50 std::string_view key; /* Extracted key, like "--key" */ 51 std::string_view val; /* Extracted value, like "value" */ 52 bool isEqualOpt = false; /* indicates whether the parsed option contained "=" symbol. 53 For options like --key=value, it's true. 54 For options like --key value, it's false */ 55 bool isJoinedOpt = false; /* indicates whether the parsed option was a joined option, like: --optValue */ 56 }; 57 58 struct OptionCategory { 59 OptionsMapType options; 60 OptionsMapType joinedOptions; 61 std::vector<OptionInterface *> registredOptions; 62 AddEnabledOptionOptionCategory63 void AddEnabledOption(OptionInterface *opt) 64 { 65 if (enabledOptionsSet.find(opt) == enabledOptionsSet.end()) { 66 enabledOptionsSet.insert(opt); 67 enabledOptions.push_back(opt); 68 } 69 } 70 GetEnabledOptionsOptionCategory71 const std::vector<OptionInterface *> &GetEnabledOptions() 72 { 73 return enabledOptions; 74 } 75 RemoveOptionCategory76 void Remove(OptionInterface *opt) 77 { 78 enabledOptionsSet.erase(opt); 79 auto it = std::find(enabledOptions.begin(), enabledOptions.end(), opt); 80 if (it != enabledOptions.end()) { 81 enabledOptions.erase(it); 82 } 83 } 84 85 private: 86 std::unordered_set<OptionInterface *> enabledOptionsSet; 87 std::vector<OptionInterface *> enabledOptions; 88 }; 89 90 class CommandLine { 91 public: 92 /* singleton */ 93 static CommandLine &GetCommandLine(); 94 95 // CommandLine must not be copyable 96 CommandLine(const CommandLine &) = delete; 97 CommandLine &operator=(const CommandLine &) = delete; 98 99 RetCode Parse(int argc, char **argv, OptionCategory &optCategory); Parse(int argc,char ** argv)100 RetCode Parse(int argc, char **argv) 101 { 102 return Parse(argc, argv, defaultCategory); 103 } 104 105 RetCode Parse(std::vector<std::string> argvs, OptionCategory &optCategory); Parse(std::vector<std::string> argvs)106 RetCode Parse(std::vector<std::string> argvs) 107 { 108 return Parse(argvs, defaultCategory); 109 } 110 RetCode HandleInputArgs(const std::deque<std::string_view> &args, OptionCategory &optCategory); 111 void Register(const std::vector<std::string> &optNames, OptionInterface &opt, OptionCategory &optCategory); 112 113 void Clear(OptionCategory &optCategory); Clear()114 void Clear() 115 { 116 return Clear(defaultCategory); 117 } 118 119 void BashCompletionPrinter(const OptionCategory &optCategory) const; BashCompletionPrinter()120 void BashCompletionPrinter() const 121 { 122 return BashCompletionPrinter(defaultCategory); 123 } 124 125 void HelpPrinter(const OptionCategory &optCategory) const; HelpPrinter()126 void HelpPrinter() const 127 { 128 return HelpPrinter(defaultCategory); 129 } 130 131 std::vector<std::pair<std::string, RetCode>> badCLArgs; 132 OptionCategory defaultCategory; 133 134 /* NOTE: categories must be constructed before options. 135 * It's the reason why they are inside CommandLine. 136 * Looks like ugly architecture, but we need it */ 137 OptionCategory clangCategory; 138 OptionCategory hir2mplCategory; 139 OptionCategory mpl2mplCategory; 140 OptionCategory meCategory; 141 OptionCategory cgCategory; 142 OptionCategory asCategory; 143 OptionCategory ldCategory; 144 145 OptionCategory jbc2mplCategory; 146 OptionCategory ipaCategory; 147 148 private: 149 CommandLine() = default; 150 151 OptionInterface *CheckJoinedOption(KeyArg &keyArg, OptionCategory &optCategory); 152 RetCode ParseJoinedOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 153 OptionCategory &optCategory); 154 RetCode ParseOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 155 OptionCategory &optCategory, OptionInterface *opt); 156 RetCode ParseEqualOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 157 OptionCategory &optCategory, const OptionsMapType &optMap, size_t pos); 158 RetCode ParseSimpleOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 159 OptionCategory &optCategory, const OptionsMapType &optMap); 160 }; 161 162 } // namespace maplecl 163 164 #endif /* MAPLE_UTIL_INCLUDE_PARSER_H */ 165