forked from diffblue/cbmc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse_options.cpp
231 lines (198 loc) · 5.67 KB
/
parse_options.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*******************************************************************\
Module:
Author: Daniel Kroening, [email protected]
\*******************************************************************/
#include "parse_options.h"
#include <algorithm>
#include <cctype>
#include <climits>
#if defined (_WIN32)
#define EX_OK 0
#define EX_USAGE 1
#else
#include <sysexits.h>
#endif
#include "cmdline.h"
#include "config.h"
#include "exception_utils.h"
#include "exit_codes.h"
#include "signal_catcher.h"
#include "string_utils.h"
#include "version.h"
parse_options_baset::parse_options_baset(
const std::string &_optstring,
int argc,
const char **argv,
const std::string &program)
: parse_result(cmdline.parse(
argc,
argv,
(std::string("?h(help)") + _optstring).c_str())),
ui_message_handler(cmdline, program),
log(ui_message_handler)
{
}
void parse_options_baset::help()
{
}
void parse_options_baset::usage_error()
{
log.error() << "Usage error!\n" << messaget::eom;
help();
}
/// Print an error message mentioning the option that was not recognized when
/// parsing the command line.
void parse_options_baset::unknown_option_msg()
{
if(!cmdline.unknown_arg.empty())
{
log.error() << "Unknown option: " << cmdline.unknown_arg;
auto const suggestions =
cmdline.get_argument_suggestions(cmdline.unknown_arg);
if(!suggestions.empty())
{
log.error() << ", did you mean ";
if(suggestions.size() > 1)
{
log.error() << "one of ";
}
join_strings(log.error(), suggestions.begin(), suggestions.end(), ", ");
log.error() << "?";
}
log.error() << messaget::eom;
}
}
int parse_options_baset::main()
{
// catch all exceptions here so that this code is not duplicated
// for each tool
try
{
if(parse_result)
{
usage_error();
unknown_option_msg();
return EX_USAGE;
}
if(cmdline.isset('?') || cmdline.isset('h') || cmdline.isset("help"))
{
help();
return EX_OK;
}
// install signal catcher
install_signal_catcher();
return doit();
}
// CPROVER style exceptions in order of decreasing happiness
catch(const invalid_command_line_argument_exceptiont &e)
{
log.error() << e.what() << messaget::eom;
return CPROVER_EXIT_USAGE_ERROR;
}
catch(const cprover_exception_baset &e)
{
log.error() << e.what() << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
catch(const std::string &e)
{
log.error() << "C++ string exception : " << e << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
catch(const char *e)
{
log.error() << "C string exception : " << e << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
catch(int e)
{
log.error() << "Numeric exception : " << e << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
// C++ style exceptions
catch(const std::bad_alloc &)
{
log.error() << "Out of memory" << messaget::eom;
return CPROVER_EXIT_INTERNAL_OUT_OF_MEMORY;
}
catch(const std::exception &e)
{
log.error() << e.what() << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
catch(const invariant_failedt &e)
{
log.error() << e.what() << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
catch(...)
{
log.error() << "Unknown exception type!" << messaget::eom;
return CPROVER_EXIT_EXCEPTION;
}
}
void parse_options_baset::log_version_and_architecture(
const std::string &front_end)
{
log.status() << front_end << " version " << CBMC_VERSION << " "
<< sizeof(void *) * CHAR_BIT << "-bit "
<< config.this_architecture() << " "
<< config.this_operating_system() << messaget::eom;
}
std::string align_center_with_border(const std::string &text)
{
auto const total_length = std::size_t{63};
auto const border = std::string{"* *"};
auto const fill =
total_length - std::min(total_length, 2 * border.size() + text.size());
auto const fill_right = fill / 2;
auto const fill_left = fill - fill_right;
return border + std::string(fill_left, ' ') + text +
std::string(fill_right, ' ') + border;
}
std::string
banner_string(const std::string &front_end, const std::string &version)
{
const std::string version_str = front_end + " " + version + " " +
std::to_string(sizeof(void *) * CHAR_BIT) +
"-bit";
return align_center_with_border(version_str);
}
std::string help_entry(
const std::string &option,
const std::string &description,
const std::size_t left_margin,
const std::size_t width)
{
PRECONDITION(!option.empty());
PRECONDITION(!std::isspace(option.front()));
PRECONDITION(!std::isspace(option.back()));
PRECONDITION(option.length() <= width);
PRECONDITION(!description.empty());
PRECONDITION(!std::isspace(description.front()));
PRECONDITION(!std::isspace(description.back()));
PRECONDITION(left_margin < width);
std::string result;
if(option.length() >= left_margin - 1)
{
result = " " + option + "\n";
result += wrap_line(description, left_margin, width) + "\n";
return result;
}
std::string padding(left_margin - option.length() - 1, ' ');
result = " " + option + padding;
if(description.length() <= (width - left_margin))
{
return result + description + "\n";
}
auto it = description.cbegin() + (width - left_margin);
auto rit = std::reverse_iterator<decltype(it)>(it) - 1;
auto rit_space = std::find(rit, description.crend(), ' ');
auto it_space = rit_space.base() - 1;
CHECK_RETURN(*it_space == ' ');
result.append(description.cbegin(), it_space);
result.append("\n");
result +=
wrap_line(it_space + 1, description.cend(), left_margin, width) + "\n";
return result;
}