CBMC: /home/runner/work/cbmc/cbmc/src/util/cmdline.cpp Source File

CBMC
Loading...
Searching...
No Matches
cmdline.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "cmdline.h"
10
11#include <util/edit_distance.h>
12#include <util/exception_utils.h>
13#include <util/invariant.h>
14#include <util/string_utils.h>
15
19
23
25{
26 options.clear();
27 args.clear();
28}
29
30 bool cmdlinet::isset(char option) const
31{
32 auto i=getoptnr(option);
33 if(i.has_value())
34 return options[*i].isset;
35 else
36 return false;
37}
38
39 bool cmdlinet::isset(const char *option) const
40{
41 auto i=getoptnr(option);
42 if(i.has_value())
43 return options[*i].isset;
44 else
45 return false;
46}
47
48 std::string cmdlinet::get_value(char option) const
49{
50 return value_opt(option).value_or("");
51}
52
53 std::optional<std::string> cmdlinet::value_opt(char option) const
54{
55 auto i=getoptnr(option);
56
57 if(i.has_value() && !options[*i].values.empty())
58 return options[*i].values.front();
59 else
60 return {};
61}
62
63 void cmdlinet::set(const std::string &option, bool value)
64{
65 auto i=getoptnr(option);
66
67 if(i.has_value())
68 options[*i].isset = value;
69 else
70 {
72 "unknown command line option", option);
73 }
74 }
75
76 void cmdlinet::set(const std::string &option, const std::string &value)
77{
78 auto i=getoptnr(option);
79
80 if(i.has_value())
81 {
82 options[*i].isset=true;
83 options[*i].values.push_back(value);
84 }
85 else
86 {
88 "unknown command line option", option);
89 }
90}
91
92 void cmdlinet::set(char option, const std::string &value)
93{
94 auto i = getoptnr(option);
95
96 if(i.has_value())
97 {
98 options[*i].isset = true;
99 options[*i].values.push_back(value);
100 }
101 else
102 {
104 "unknown command line option", std::string(1, option));
105 }
106}
107
108 static std::list<std::string> immutable_empty_list;
109
110 const std::list<std::string> &cmdlinet::get_values(char option) const
111{
112 auto i=getoptnr(option);
113
114 if(i.has_value())
115 return options[*i].values;
116 else
118}
119
120 std::string cmdlinet::get_value(const char *option) const
121{
122 return value_opt(option).value_or("");
123}
124
125 std::optional<std::string> cmdlinet::value_opt(const char *option) const
126{
127 auto i=getoptnr(option);
128
129 if(i.has_value() && !options[*i].values.empty())
130 return options[*i].values.front();
131 else
132 return {};
133}
134
135 const std::list<std::string> &cmdlinet::get_values(
136 const std::string &option) const
137{
138 auto i=getoptnr(option);
139
140 if(i.has_value())
141 return options[*i].values;
142 else
144}
145
146std::list<std::string>
147 cmdlinet::get_comma_separated_values(const char *option) const
148{
149 std::list<std::string> separated_values;
150
151 for(const auto &csv : get_values(option))
152 {
153 const auto values = split_string(csv, ',');
154 separated_values.insert(
155 separated_values.end(), values.begin(), values.end());
156 }
157
158 return separated_values;
159}
160
161 std::optional<std::size_t> cmdlinet::getoptnr(char option) const
162{
163 for(std::size_t i=0; i<options.size(); i++)
164 if(options[i].optchar==option)
165 return i;
166
167 return std::optional<std::size_t>();
168}
169
170 std::optional<std::size_t> cmdlinet::getoptnr(const std::string &option) const
171{
172 for(std::size_t i=0; i<options.size(); i++)
173 if(options[i].optstring==option)
174 return i;
175
176 return std::optional<std::size_t>();
177}
178
179 bool cmdlinet::parse(int argc, const char **argv, const char *optstring)
180{
181 clear();
182
183 parse_optstring(optstring);
184 return parse_arguments(argc, argv);
185}
186
191 void cmdlinet::parse_optstring(const char *optstring)
192{
193 while(optstring[0] != 0)
194 {
195 optiont option;
196
198 optstring[0] != ':', "cmdlinet::parse: Invalid option string\n");
199
200 if(optstring[0] == '(')
201 {
202 option.islong = true;
203 option.optchar = 0;
204 option.isset = false;
205 option.optstring.clear();
206
207 for(optstring++; optstring[0] != ')' && optstring[0] != 0; optstring++)
208 option.optstring += optstring[0];
209
210 if(optstring[0] == ')')
211 optstring++;
212 }
213 else
214 {
215 option.islong = false;
216 option.optchar = optstring[0];
217 option.optstring.clear();
218 option.isset = false;
219
220 optstring++;
221 }
222
223 if(optstring[0] == ':')
224 {
225 option.hasval = true;
226 optstring++;
227 }
228 else
229 option.hasval = false;
230
231 options.push_back(option);
232 }
233}
234
235std::vector<std::string>
237{
238 struct suggestiont
239 {
240 std::size_t distance;
241 std::string suggestion;
242
243 bool operator<(const suggestiont &other) const
244{
245 return distance < other.distance;
246 }
247 };
248
249 auto argument_suggestions = std::vector<suggestiont>{};
250 // We allow 3 errors here. This can lead to the output being a bit chatty,
251 // which we mitigate by reducing suggestions to those with the minimum
252 // distance further down below
254 for(const auto &option : options)
255 {
256 if(option.islong)
257 {
258 const auto long_name = "--" + option.optstring;
259 if(auto distance = argument_matcher.get_edit_distance(long_name))
260 {
261 argument_suggestions.push_back({distance.value(), long_name});
262 }
263 }
264 if(!option.islong)
265 {
266 const auto short_name = std::string{"-"} + option.optchar;
267 if(auto distance = argument_matcher.get_edit_distance(short_name))
268 {
269 argument_suggestions.push_back({distance.value(), short_name});
270 }
271 }
272 }
273
274 auto final_suggestions = std::vector<std::string>{};
275 if(!argument_suggestions.empty())
276 {
277 // we only want to keep suggestions with the minimum distance
278 // because otherwise they become quickly too noisy to be useful
279 auto min = std::min_element(
281 INVARIANT(
282 min != argument_suggestions.end(),
283 "there is a minimum because it's not empty");
284 for(auto const &suggestion : argument_suggestions)
285 {
286 if(suggestion.distance == min->distance)
287 {
288 final_suggestions.push_back(suggestion.suggestion);
289 }
290 }
291 }
292 return final_suggestions;
293}
294
295 bool cmdlinet::parse_arguments(int argc, const char **argv)
296{
297 for(int i = 1; i < argc; i++)
298 {
299 if(argv[i][0] != '-')
300 args.push_back(argv[i]);
301 else
302 {
303 std::optional<std::size_t> optnr;
304
305 if(argv[i][1] != 0 && argv[i][2] == 0)
306 optnr = getoptnr(argv[i][1]); // single-letter option -X
307 else if(argv[i][1] == '-')
308 optnr = getoptnr(argv[i] + 2); // multi-letter option with --XXX
309 else
310 {
311 // Multi-letter option -XXX, or single-letter with argument -Xval
312 // We first try single-letter.
313 optnr = getoptnr(argv[i][1]);
314
315 if(!optnr.has_value()) // try multi-letter
316 optnr = getoptnr(argv[i] + 1);
317 }
318
319 if(!optnr.has_value())
320 {
321 unknown_arg = argv[i];
322 return true;
323 }
324
325 options[*optnr].isset = true;
326
327 if(options[*optnr].hasval)
328 {
329 if(argv[i][2] == 0 || options[*optnr].islong)
330 {
331 i++;
332 if(i == argc)
333 return true;
334 if(argv[i][0] == '-' && argv[i][1] != 0)
335 return true;
336 options[*optnr].values.push_back(argv[i]);
337 }
338 else
339 options[*optnr].values.push_back(argv[i] + 2);
340 }
341 }
342 }
343 return false;
344}
345
347 const cmdlinet *command_line,
348 std::size_t index)
349 : command_line(command_line), index(index)
350{
352}
353
354cmdlinet::option_namest::option_names_iteratort &
356{
357 PRECONDITION(command_line != nullptr);
358 ++index;
359 goto_next_valid_index();
360 return *this;
361}
363{
364 PRECONDITION(command_line != nullptr);
365 auto const &options = command_line->options;
366 return index < options.size() && options[index].isset &&
367 options[index].islong;
368}
369
371{
372 PRECONDITION(command_line != nullptr);
373 while(index < command_line-> options.size() && !is_valid_index())
374 {
375 ++index;
376 }
377}
378
379const cmdlinet::option_namest::option_names_iteratort
384
386{
387 PRECONDITION(command_line != nullptr);
388 return command_line->options.at(index).optstring;
389}
390
397
404
409
414
416{
417 return option_names_iteratort(&command_line, command_line.options.size());
418}
virtual void clear()
Reset the abstract state.
Definition ai.h:269
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
std::string get_value(char option) const
Definition cmdline.cpp:48
std::string unknown_arg
Definition cmdline.h:156
virtual bool isset(char option) const
Definition cmdline.cpp:30
std::list< std::string > get_comma_separated_values(const char *option) const
Collect all occurrences of option option and split their values on each comma, merging them into a si...
Definition cmdline.cpp:147
std::optional< std::size_t > getoptnr(char option) const
Definition cmdline.cpp:161
cmdlinet()
Definition cmdline.cpp:16
argst args
Definition cmdline.h:155
std::optional< std::string > value_opt(char option) const
Definition cmdline.cpp:53
bool parse_arguments(int argc, const char **argv)
Parses a commandline according to a previously parsed optstring and writes the result to cmdlinet::op...
Definition cmdline.cpp:295
std::vector< optiont > options
Definition cmdline.h:194
virtual ~cmdlinet()
Definition cmdline.cpp:20
virtual void set(const std::string &option, bool value=true)
Set option option to value, or true if the value is omitted.
Definition cmdline.cpp:63
virtual bool parse(int argc, const char **argv, const char *optstring)
Parses a commandline according to a specification given in optstring.
Definition cmdline.cpp:179
std::vector< std::string > get_argument_suggestions(const std::string &unknown_argument)
Definition cmdline.cpp:236
void parse_optstring(const char *optstring)
Parses an optstring and writes the result to cmdlinet::options.
Definition cmdline.cpp:191
option_namest option_names() const
Pseudo-object that can be used to iterate over options in this cmdlinet (should not outlive this)
Definition cmdline.cpp:187
virtual void clear()
Definition cmdline.cpp:24
const std::list< std::string > & get_values(const std::string &option) const
Definition cmdline.cpp:135
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
static std::list< std::string > immutable_empty_list
Definition cmdline.cpp:108
bool operator<(const reaching_definitiont &a, const reaching_definitiont &b)
In order to use instances of this structure as keys in ordered containers, such as std::map,...
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
void split_string(std::string_view s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
bool operator==(const option_names_iteratort &other)
Definition cmdline.cpp:392
bool operator!=(const option_names_iteratort &other)
Definition cmdline.cpp:399
option_names_iteratort & operator++()
Definition cmdline.cpp:355
option_names_iteratort end()
Definition cmdline.cpp:415
option_names_iteratort begin()
Definition cmdline.cpp:410
option_namest(const cmdlinet &command_line)
Definition cmdline.cpp:405
const cmdlinet & command_line
Definition cmdline.h:147
std::string optstring
Definition cmdline.h:171
Simple automaton that can detect whether a string can be transformed into another with a limited numb...
Definition edit_distance.h:25

AltStyle によって変換されたページ (->オリジナル) /