Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others. 4 : // This program and the accompanying materials are made available under the 5 : // terms of the Eclipse Public License 2.0 which is available at 6 : // https://www.eclipse.org/legal/epl-2.0/ 7 : // This Source Code may also be made available under the following Secondary 8 : // Licenses when the conditions for such availability set forth in the Eclipse 9 : // Public License 2.0 are satisfied: GNU General Public License, version 2 10 : // or later which is available at 11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 : /****************************************************************************/ 14 : /// @file OptionsParser.cpp 15 : /// @author Daniel Krajzewicz 16 : /// @author Jakob Erdmann 17 : /// @author Michael Behrisch 18 : /// @date Mon, 17 Dec 2001 19 : /// 20 : // Parses the command line arguments 21 : /****************************************************************************/ 22 : #include <config.h> 23 : 24 : #include <iostream> 25 : #include <cstring> 26 : #include "Option.h" 27 : #include "OptionsCont.h" 28 : #include "OptionsParser.h" 29 : #include <utils/common/UtilExceptions.h> 30 : #include <utils/common/MsgHandler.h> 31 : 32 : 33 : // =========================================================================== 34 : // method definitions 35 : // =========================================================================== 36 : bool 37 96399 : OptionsParser::parse(const std::vector<std::string>& args, const bool ignoreAppenders) { 38 96399 : bool ok = true; 39 96399 : const int argc = (int)args.size(); 40 858002 : for (int i = 1; i < argc;) { 41 : try { 42 : int add; 43 : // try to set the current option 44 761603 : if (i < argc - 1) { 45 721834 : add = check(args[i], &args[i + 1], ok, ignoreAppenders); 46 : } else { 47 39769 : add = check(args[i], nullptr, ok, ignoreAppenders); 48 : } 49 761555 : i += add; 50 48 : } catch (ProcessError& e) { 51 96 : WRITE_ERROR("On processing option '" + args[i] + "':\n " + e.what()); 52 48 : i++; 53 48 : ok = false; 54 48 : } 55 : } 56 96399 : return ok; 57 : } 58 : 59 : 60 : int 61 761603 : OptionsParser::check(const std::string& arg1, const std::string* const arg2, bool& ok, const bool ignoreAppenders) { 62 : // the first argument should be an option 63 : // (only the second may be a free string) 64 761603 : if (!checkParameter(arg1)) { 65 44 : ok = false; 66 44 : return 1; 67 : } 68 : 69 761559 : OptionsCont& oc = OptionsCont::getOptions(); 70 761559 : const bool append = arg1[0] == '+'; 71 : // process not abbreviated switches 72 761559 : if (append || arg1[1] == '-') { 73 1176754 : const std::string tmp(arg1.substr(append ? 1 : 2)); 74 588401 : const std::string::size_type idx1 = tmp.find('='); 75 588401 : if (append && ignoreAppenders) { 76 32 : return idx1 == std::string::npos ? 2 : 1; 77 : } 78 : // check whether a parameter was submitted 79 588377 : if (idx1 != std::string::npos) { 80 124775 : ok &= oc.set(tmp.substr(0, idx1), tmp.substr(idx1 + 1), append); 81 : } else { 82 503550 : if (arg2 == nullptr || (oc.isBool(tmp) && (*arg2)[0] == '-')) { 83 211428 : ok &= oc.set(tmp, "true"); 84 : } else { 85 292142 : ok &= oc.set(tmp, *arg2, append); 86 292142 : return 2; 87 : } 88 : } 89 296187 : return 1; 90 : } 91 : // go through the abbreviated switches 92 173158 : const int len = (int)arg1.size(); 93 206550 : for (int i = 1; i < len; i++) { 94 : // set boolean switches 95 173158 : const std::string abbr = arg1.substr(i, 1); 96 173158 : if (oc.isBool(abbr)) { 97 33392 : if (arg2 == nullptr || (*arg2)[0] == '-' || i != len - 1) { 98 33392 : ok &= oc.set(abbr, "true"); 99 : } else { 100 0 : ok &= oc.set(abbr, *arg2); 101 0 : return 2; 102 : } 103 : // set non-boolean switches 104 : } else { 105 : // check whether the parameter comes directly after the switch 106 : // and process if so 107 139766 : if (arg2 == nullptr || i != len - 1) { 108 8195 : ok &= processNonBooleanSingleSwitch(oc, arg1.substr(i), append); 109 8195 : return 1; 110 : // process parameter following after a space 111 : } else { 112 131571 : ok &= oc.set(abbr, *arg2, append); 113 : // option name and attribute were in two arguments 114 131571 : return 2; 115 : } 116 : } 117 : } 118 : // all switches within the current argument were boolean switches 119 : return 1; 120 : } 121 : 122 : 123 : bool 124 8195 : OptionsParser::processNonBooleanSingleSwitch(OptionsCont& oc, const std::string& arg, const bool append) { 125 8195 : if (arg[1] == '=') { 126 8184 : if (arg.size() < 3) { 127 0 : WRITE_ERRORF(TL("Missing value for parameter '%'."), arg.substr(0, 1)); 128 0 : return false; 129 : } else { 130 24548 : return oc.set(arg.substr(0, 1), arg.substr(2), append); 131 : } 132 : } else { 133 11 : if (arg.size() < 2) { 134 3 : WRITE_ERRORF(TL("Missing value for parameter '%'."), arg); 135 1 : return false; 136 : } else { 137 24 : return oc.set(arg.substr(0, 1), arg.substr(1), append); 138 : } 139 : } 140 : } 141 : 142 : 143 : bool 144 761603 : OptionsParser::checkParameter(const std::string& arg1) { 145 761603 : if (arg1[0] != '-' && arg1[0] != '+') { 146 84 : WRITE_ERRORF(TL("The parameter '%' is not allowed in this context.\n Switch or parameter name expected."), arg1); 147 28 : return false; 148 : } 149 761575 : if ((arg1[0] == '-' && arg1[1] == '+') || (arg1[0] == '+' && arg1[1] == '-')) { 150 48 : WRITE_ERRORF(TL("Mixed parameter syntax in '%'."), arg1); 151 16 : return false; 152 : } 153 : return true; 154 : } 155 : 156 : 157 : /****************************************************************************/