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(std::vector<std::string> argvs, OptionCategory &optCategory); Parse(std::vector<std::string> argvs)100 RetCode Parse(std::vector<std::string> argvs) 101 { 102 return Parse(argvs, defaultCategory); 103 } 104 RetCode HandleInputArgs(const std::deque<std::string_view> &args, OptionCategory &optCategory); 105 void Register(const std::vector<std::string> &optNames, OptionInterface &opt, OptionCategory &optCategory); 106 107 std::vector<std::pair<std::string, RetCode>> badCLArgs; 108 OptionCategory defaultCategory; 109 110 /* NOTE: categories must be constructed before options. 111 * It's the reason why they are inside CommandLine. 112 * Looks like ugly architecture, but we need it */ 113 OptionCategory clangCategory; 114 OptionCategory hir2mplCategory; 115 OptionCategory mpl2mplCategory; 116 OptionCategory meCategory; 117 OptionCategory cgCategory; 118 OptionCategory asCategory; 119 OptionCategory ldCategory; 120 121 OptionCategory jbc2mplCategory; 122 OptionCategory ipaCategory; 123 124 private: 125 CommandLine() = default; 126 127 OptionInterface *CheckJoinedOption(KeyArg &keyArg, OptionCategory &optCategory); 128 RetCode ParseJoinedOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 129 OptionCategory &optCategory); 130 RetCode ParseOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 131 OptionCategory &optCategory, OptionInterface *opt); 132 RetCode ParseEqualOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 133 OptionCategory &optCategory, const OptionsMapType &optMap, size_t pos); 134 RetCode ParseSimpleOption(size_t &argsIndex, const std::deque<std::string_view> &args, KeyArg &keyArg, 135 OptionCategory &optCategory, const OptionsMapType &optMap); 136 }; 137 138 } // namespace maplecl 139 140 #endif /* MAPLE_UTIL_INCLUDE_PARSER_H */ 141