Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 : /// @author Mirko Barthauer
19 : /// @date Mon, 17 Dec 2001
20 : ///
21 : // Parses the command line arguments
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <iostream>
26 : #include <cstring>
27 : #include "Option.h"
28 : #include "OptionsCont.h"
29 : #include "OptionsParser.h"
30 : #include <utils/common/UtilExceptions.h>
31 : #include <utils/common/MsgHandler.h>
32 :
33 :
34 : // ===========================================================================
35 : // method definitions
36 : // ===========================================================================
37 : bool
38 97079 : OptionsParser::parse(const std::vector<std::string>& args, const bool ignoreAppenders) {
39 97079 : bool ok = true;
40 97079 : const int argc = (int)args.size();
41 901591 : for (int i = 1; i < argc;) {
42 : try {
43 : int add;
44 : // try to set the current option
45 804512 : if (i < argc - 1) {
46 757040 : add = check(args[i], &args[i + 1], ok, ignoreAppenders);
47 : } else {
48 47472 : add = check(args[i], nullptr, ok, ignoreAppenders);
49 : }
50 804464 : i += add;
51 48 : } catch (ProcessError& e) {
52 96 : WRITE_ERROR("On processing option '" + args[i] + "':\n " + e.what());
53 48 : i++;
54 48 : ok = false;
55 48 : }
56 : }
57 97079 : return ok;
58 : }
59 :
60 :
61 : int
62 804512 : OptionsParser::check(const std::string& arg1, const std::string* const arg2, bool& ok, const bool ignoreAppenders) {
63 : // the first argument should be an option
64 : // (only the second may be a free string)
65 804512 : if (!checkParameter(arg1)) {
66 33 : ok = false;
67 33 : return 1;
68 : }
69 :
70 : #ifdef _DEBUG
71 : // allow to set FOX FXApp switches tracelevel (messages) and maxcolors
72 : if ((arg1 == "-tracelevel" || arg1 == "-maxcolors") && arg2 != nullptr) {
73 : ok = true;
74 : return 2;
75 : }
76 : #endif
77 :
78 804479 : OptionsCont& oc = OptionsCont::getOptions();
79 804479 : const bool append = arg1[0] == '+';
80 : // process not abbreviated switches
81 804479 : if (append || arg1[1] == '-') {
82 1268968 : const std::string tmp(arg1.substr(append ? 1 : 2));
83 634503 : const std::string::size_type idx1 = tmp.find('=');
84 634503 : if (append && ignoreAppenders) {
85 23 : return idx1 == std::string::npos ? 2 : 1;
86 : }
87 : // check whether a parameter was submitted
88 634484 : if (idx1 != std::string::npos) {
89 92481 : ok &= oc.set(tmp.substr(0, idx1), tmp.substr(idx1 + 1), append);
90 : } else {
91 542015 : if (arg2 == nullptr || (oc.isBool(tmp) && (*arg2)[0] == '-')) {
92 237629 : ok &= oc.set(tmp, "true");
93 : } else {
94 304404 : ok &= oc.set(tmp, *arg2, append);
95 304404 : return 2;
96 : }
97 : }
98 330032 : return 1;
99 : }
100 : // go through the abbreviated switches
101 169976 : const int len = (int)arg1.size();
102 206330 : for (int i = 1; i < len; i++) {
103 : // set boolean switches
104 169976 : const std::string abbr = arg1.substr(i, 1);
105 169976 : if (oc.isBool(abbr)) {
106 36368 : if (arg2 == nullptr || (*arg2)[0] == '-' || i != len - 1) {
107 36354 : ok &= oc.set(abbr, "true");
108 : } else {
109 14 : ok &= oc.set(abbr, *arg2);
110 14 : return 2;
111 : }
112 : // set non-boolean switches
113 : } else {
114 : // check whether the parameter comes directly after the switch
115 : // and process if so
116 133608 : if (arg2 == nullptr || i != len - 1) {
117 9604 : ok &= processNonBooleanSingleSwitch(oc, arg1.substr(i), append);
118 9604 : return 1;
119 : // process parameter following after a space
120 : } else {
121 124004 : ok &= oc.set(abbr, *arg2, append);
122 : // option name and attribute were in two arguments
123 124004 : return 2;
124 : }
125 : }
126 : }
127 : // all switches within the current argument were boolean switches
128 : return 1;
129 : }
130 :
131 :
132 : bool
133 9604 : OptionsParser::processNonBooleanSingleSwitch(OptionsCont& oc, const std::string& arg, const bool append) {
134 9604 : if (arg[1] == '=') {
135 9598 : if (arg.size() < 3) {
136 0 : WRITE_ERRORF(TL("Missing value for parameter '%'."), arg.substr(0, 1));
137 0 : return false;
138 : } else {
139 19196 : return oc.set(arg.substr(0, 1), arg.substr(2), append);
140 : }
141 : } else {
142 6 : if (arg.size() < 2) {
143 3 : WRITE_ERRORF(TL("Missing value for parameter '%'."), arg);
144 1 : return false;
145 : } else {
146 10 : return oc.set(arg.substr(0, 1), arg.substr(1), append);
147 : }
148 : }
149 : }
150 :
151 :
152 : bool
153 804512 : OptionsParser::checkParameter(const std::string& arg1) {
154 804512 : if (arg1[0] != '-' && arg1[0] != '+') {
155 75 : WRITE_ERRORF(TL("The parameter '%' is not allowed in this context.\n Switch or parameter name expected."), arg1);
156 25 : return false;
157 : }
158 804487 : if ((arg1[0] == '-' && arg1[1] == '+') || (arg1[0] == '+' && arg1[1] == '-')) {
159 24 : WRITE_ERRORF(TL("Mixed parameter syntax in '%'."), arg1);
160 8 : return false;
161 : }
162 : return true;
163 : }
164 :
165 :
166 : /****************************************************************************/
|