cprover
Toggle main menu visibility
Loading...
Searching...
No Matches
ms_cl_cmdline.cpp
Go to the documentation of this file.
1
/*******************************************************************\
2
3
Module: A special command line object for the CL options
4
5
Author: Daniel Kroening
6
7
\*******************************************************************/
8
11
12
#include "
ms_cl_cmdline.h
"
13
14
#include <
util/unicode.h
>
15
16
#include <climits>
17
#include <cstdlib>
18
#include <fstream>
// IWYU pragma: keep
19
#include <iostream>
20
24
// clang-format off
25
const
char
*
non_ms_cl_options
[]=
26
{
27
"--show-symbol-table"
,
28
"--show-function-table"
,
29
"--ppc-macos"
,
30
"--i386-linux"
,
31
"--i386-win32"
,
32
"--i386-macos"
,
33
"--string-abstraction"
,
34
"--no-library"
,
35
"--16"
,
36
"--32"
,
37
"--64"
,
38
"--little-endian"
,
39
"--big-endian"
,
40
"--unsigned-char"
,
41
"--help"
,
42
"--xml"
,
43
"--partial-inlining"
,
44
"--verbosity"
,
45
"--function"
,
46
"--validate-goto-model"
,
47
"--export-file-local-symbols"
,
48
"--mangle-suffix"
,
49
nullptr
50
};
51
// clang-format on
52
53
bool
ms_cl_cmdlinet::parse
(
const
std::vector<std::string> &arguments)
54
{
55
for
(std::size_t i = 0; i < arguments.size(); i++)
56
{
57
// is it a non-cl option?
58
if
(std::string(arguments[i], 0, 2) ==
"--"
)
59
{
60
process_non_cl_option
(arguments[i]);
61
62
if
(
63
arguments[i] ==
"--verbosity"
|| arguments[i] ==
"--function"
||
64
arguments[i] ==
"--mangle-suffix"
)
65
{
66
if
(i < arguments.size() - 1)
67
{
68
set
(arguments[i], arguments[i + 1]);
69
i++;
// skip ahead
70
}
71
}
72
}
73
else
if
(!arguments[i].empty() && arguments[i][0] ==
'@'
)
74
{
75
// potentially recursive
76
process_response_file
(std::string(arguments[i], 1, std::string::npos));
77
}
78
else
if
(arguments[i] ==
"/link"
|| arguments[i] ==
"-link"
)
79
{
80
// anything that follows goes to the linker
81
i = arguments.size() - 1;
82
}
83
else
if
(
84
arguments[i].size() == 2 &&
85
(arguments[i] ==
"/D"
|| arguments[i] ==
"-D"
) &&
86
i != arguments.size() - 1)
87
{
88
// this requires special treatment, as you can do "/D something"
89
std::string tmp =
"/D"
+ arguments[i + 1];
90
i++;
91
process_cl_option
(tmp);
92
}
93
else
94
process_cl_option
(arguments[i]);
95
}
96
97
return
false
;
98
}
99
100
void
ms_cl_cmdlinet::parse_env
()
101
{
102
// first do environment
103
104
#ifdef _WIN32
105
106
const
wchar_t
*CL_env=_wgetenv(L
"CL"
);
107
108
if
(CL_env!=NULL)
109
process_response_file_line
(
narrow
(CL_env));
110
111
#else
112
113
const
char
*CL_env=getenv(
"CL"
);
114
115
if
(CL_env!=
nullptr
)
116
process_response_file_line
(CL_env);
117
118
#endif
119
}
120
124
bool
ms_cl_cmdlinet::parse
(
int
argc,
const
char
**argv)
125
{
126
// should really use "wide" argv from wmain()
127
128
std::vector<std::string> arguments;
129
130
// skip argv[0]
131
for
(
int
i=1; i<argc; i++)
132
arguments.push_back(argv[i]);
133
134
return
parse
(arguments);
135
}
136
137
static
std::istream &
my_wgetline
(std::istream &in, std::wstring &dest)
138
{
139
// We should support this properly,
140
// but will just strip right now.
141
dest.clear();
142
143
while
(in)
144
{
145
char
ch1, ch2;
146
in.get(ch1);
147
in.get(ch2);
148
149
if
(!in)
150
{
151
if
(!dest.empty())
152
in.clear();
153
break
;
154
}
155
156
if
(ch1==
'\r'
)
157
{
158
// ignore
159
}
160
else
if
(ch1==
'\n'
)
161
{
162
in.clear();
163
break
;
// line end
164
}
165
else
166
dest += wchar_t(ch1 + (ch2 << CHAR_BIT));
167
}
168
169
return
in;
170
}
171
172
void
ms_cl_cmdlinet::process_response_file
(
const
std::string &
file
)
173
{
174
std::ifstream infile(
file
);
175
176
if
(!infile)
177
{
178
std::cerr <<
"failed to open response file '"
<<
file
<<
"'\n"
;
179
return
;
180
}
181
182
// these may be Unicode -- which is indicated by 0xff 0xfe
183
std::string line;
184
getline(infile, line);
185
if
(line.size()>=2 &&
186
line[0]==
static_cast<
char
>
(0xff) &&
187
line[1]==
static_cast<
char
>
(0xfe))
188
{
189
// Unicode, UTF-16 little endian
190
191
#if 1
192
// Re-open -- should be using wifstream,
193
// but this isn't available everywhere.
194
std::ifstream infile2(
file
, std::ios::binary);
195
infile2.seekg(2);
196
std::wstring wline;
197
198
while
(
my_wgetline
(infile2, wline))
199
process_response_file_line
(
narrow
(wline));
// we UTF-8 it
200
201
#else
202
203
std::wifstream infile2(
file
, std::ios::binary);
204
std::wstring wline;
205
206
while
(std::getline(infile2, wline))
207
process_response_file_line
(
narrow
(wline));
// we UTF-8 it
208
209
#endif
210
}
211
else
if
(line.size()>=3 &&
212
line[0]==
static_cast<
char
>
(0xef) &&
213
line[1]==
static_cast<
char
>
(0xbb) &&
214
line[2]==
static_cast<
char
>
(0xbf))
215
{
216
// This is the UTF-8 BOM. We can proceed as usual, since
217
// we use UTF-8 internally.
218
infile.seekg(3);
219
220
while
(getline(infile, line))
221
process_response_file_line
(line);
222
}
223
else
224
{
225
// normal ASCII
226
infile.seekg(0);
227
while
(getline(infile, line))
228
process_response_file_line
(line);
229
}
230
}
231
232
void
ms_cl_cmdlinet::process_response_file_line
(
const
std::string &line)
233
{
234
// In a response file, multiple compiler options and source-code files can
235
// appear on one line. A single compiler-option specification must appear
236
// on one line (cannot span multiple lines). Response files can have
237
// comments that begin with the # symbol.
238
239
if
(line.empty())
240
return
;
241
if
(line[0]==
'#'
)
242
return
;
// comment
243
244
std::vector<std::string> arguments;
245
std::string option;
246
bool
in_quotes=
false
;
247
for
(std::size_t i=0; i<line.size(); i++)
248
{
249
char
ch=line[i];
250
251
if
(ch==
' '
&& !in_quotes)
252
{
253
if
(!option.empty())
254
arguments.push_back(option);
255
option.clear();
256
}
257
else
if
(ch==
'"'
)
258
{
259
in_quotes=!in_quotes;
260
}
261
else
262
option+=ch;
263
}
264
265
if
(!option.empty())
266
arguments.push_back(option);
267
268
parse
(arguments);
269
}
270
271
void
ms_cl_cmdlinet::process_non_cl_option
(
272
const
std::string &s)
273
{
274
set
(s);
275
276
for
(
unsigned
j=0;
non_ms_cl_options
[j]!=
nullptr
; j++)
277
if
(s==
non_ms_cl_options
[j])
278
return
;
279
280
// unrecognized option
281
std::cout <<
"Warning: uninterpreted non-CL option '"
<< s <<
"'\n"
;
282
}
283
285
const
char
*
ms_cl_flags
[]=
286
{
287
"c"
,
// compile only
288
nullptr
289
};
290
291
const
char
*
ms_cl_prefixes
[]=
292
{
293
"O1"
,
// minimize space
294
"O2"
,
// maximize speed
295
"Ob"
,
// <n> inline expansion (default n=0)
296
"Od"
,
// disable optimizations (default)
297
"Og"
,
// enable global optimization
298
"Oi"
,
// [-] enable intrinsic functions
299
"Os"
,
// favor code space
300
"Ot"
,
// favor code speed
301
"Ox"
,
// maximum optimizations
302
"Oy"
,
// [-] enable frame pointer omission
303
"GF"
,
// enable read-only string pooling
304
"Gm"
,
// [-] enable minimal rebuild
305
"Gy"
,
// [-] separate functions for linker
306
"GS"
,
// [-] enable security checks
307
"GR"
,
// [-] enable C++ RTTI
308
"GX"
,
// [-] enable C++ EH (same as /EHsc)
309
"EHs"
,
// enable C++ EH (no SEH exceptions)
310
"EHa"
,
// enable C++ EH (w/ SEH exceptions)
311
"EHc"
,
// extern "C" defaults to nothrow
312
"fp"
,
// floating-point model
313
"GL"
,
// [-] enable link-time code generation
314
"GA"
,
// optimize for Windows Application
315
"Ge"
,
// force stack checking for all funcs
316
"Gs"
,
// [num] control stack checking calls
317
"Gh"
,
// enable _penter function call
318
"GH"
,
// enable _pexit function call
319
"GT"
,
// generate fiber-safe TLS accesses
320
"RTC1"
,
// Enable fast checks (/RTCsu)
321
"RTCc"
,
// Convert to smaller type checks
322
"RTCs"
,
// Stack Frame runtime checking
323
"RTCu"
,
// Uninitialized local usage checks
324
"clr"
,
// compile for common language runtime
325
"Gd"
,
// __cdecl calling convention
326
"Gr"
,
// __fastcall calling convention
327
"Gz"
,
// __stdcall calling convention
328
"GZ"
,
// Enable stack checks (/RTCs)
329
"QIfist"
,
// [-] use FIST instead of ftol()
330
"hotpatch"
,
// ensure function padding for hotpatchable images
331
"arch:"
,
// <SSE|SSE2> minimum CPU architecture requirements
332
"Fa"
,
// [file] name assembly listing file
333
"FA"
,
// [scu] configure assembly listing
334
"Fd"
,
// [file] name .PDB file
335
"Fe"
,
// <file> name executable file
336
"Fm"
,
// [file] name map file
337
"Fo"
,
// <file> name object file
338
"Fp"
,
// <file> name precompiled header file
339
"Fr"
,
// [file] name source browser file
340
"FR"
,
// [file] name extended .SBR file
341
"doc"
,
// [file] process XML documentation comments
342
"AI"
,
// <dir> add to assembly search path
343
"FU"
,
// <file> forced using assembly/module
344
"C"
,
// don't strip comments
345
"D"
,
// <name>{=|#}<text> define macro
346
"E"
,
// preprocess to stdout
347
"EP"
,
// preprocess to stdout, no #line
348
"P"
,
// preprocess to file
349
"Fx"
,
// merge injected code to file
350
"FI"
,
// <file> name forced include file
351
"U"
,
// <name> remove predefined macro
352
"u"
,
// remove all predefined macros
353
"I"
,
// <dir> add to include search path
354
"X"
,
// ignore "standard places"
355
"Zi"
,
// enable debugging information
356
"Z7"
,
// enable old-style debug info
357
"Zp"
,
// [n] pack structs on n-byte boundary
358
"Za"
,
// disable extensions
359
"Ze"
,
// enable extensions (default)
360
"Zl"
,
// omit default library name in .OBJ
361
"Zg"
,
// generate function prototypes
362
"Zs"
,
// syntax check only
363
"vd"
,
// {0|1|2} disable/enable vtordisp
364
"vm"
,
// <x> type of pointers to members
365
"Zc:"
,
// arg1[,arg2] C++ language conformance, where arguments can be:
366
"ZI"
,
// enable Edit and Continue debug info
367
"openmp"
,
// enable OpenMP 2.0 language extensions
368
"analyze"
,
369
"errorReport"
,
370
"?"
,
371
"help"
,
// print this help message
372
"FC"
,
// use full pathnames in diagnostics /H<num> max external name length
373
"J"
,
// default char type is unsigned
374
"nologo"
,
// suppress copyright message
375
"show"
,
// Includes show include file names
376
"Tc"
,
// <source file> compile file as .c
377
"Tp"
,
// <source file> compile file as .cpp
378
"TC"
,
// compile all files as .c
379
"TP"
,
// compile all files as .cpp
380
"V"
,
// <string> set version string
381
"w"
,
// disable all warnings
382
"wd"
,
// <n> disable warning n
383
"we"
,
// <n> treat warning n as an error
384
"wo"
,
// <n> issue warning n once
385
"w"
,
// <l><n> set warning level 1-4 for n
386
"W"
,
// <n> set warning level (default n=1)
387
"Wall"
,
// enable all warnings
388
"WL"
,
// enable one line diagnostics
389
"WX"
,
// treat warnings as errors
390
"Yc"
,
// [file] create .PCH file
391
"Yd"
,
// put debug info in every .OBJ
392
"Yl"
,
// [sym] inject .PCH ref for debug lib
393
"Yu"
,
// [file] use .PCH file
394
"Y"
,
// - disable all PCH options
395
"Zm"
,
// <n> max memory alloc (% of default)
396
"Wp64"
,
// enable 64 bit porting warnings
397
"LD"
,
// Create .DLL
398
"LDd"
,
// Create .DLL debug library
399
"LN"
,
// Create a .netmodule
400
"F"
,
// <num> set stack size
401
"link"
,
// [linker options and libraries]
402
"MD"
,
// link with MSVCRT.LIB
403
"MT"
,
// link with LIBCMT.LIB
404
"MDd"
,
// link with MSVCRTD.LIB debug lib
405
"MTd"
,
// link with LIBCMTD.LIB debug lib
406
"std"
,
// specify C++ language standard
407
"sdl"
,
// Enable Additional Security Checks
408
"diagnostics"
,
// unknown
409
nullptr
410
};
411
412
void
ms_cl_cmdlinet::process_cl_option
(
const
std::string &s)
413
{
414
if
(s.empty())
415
return
;
416
417
if
(s[0]!=
'/'
&& s[0]!=
'-'
)
418
{
419
args
.push_back(s);
420
return
;
421
}
422
423
for
(std::size_t j=0;
ms_cl_flags
[j]!=
nullptr
; j++)
424
{
425
if
(std::string(s, 1, std::string::npos)==
ms_cl_flags
[j])
426
{
427
cmdlinet::optiont
option;
428
std::optional<std::size_t> optnr;
429
430
if
(s.size()==2)
431
{
432
option.
islong
=
false
;
433
option.
optstring
.clear();
434
option.
optchar
=s[1];
435
optnr=
getoptnr
(option.
optchar
);
436
}
437
else
438
{
439
option.
islong
=
true
;
440
option.
optstring
=std::string(s, 1, std::string::npos);
441
option.
optchar
=0;
442
optnr=
getoptnr
(option.
optstring
);
443
}
444
445
if
(!optnr.has_value())
446
{
447
options
.push_back(option);
448
optnr=
options
.size()-1;
449
}
450
451
options
[*optnr].isset=
true
;
452
return
;
453
}
454
}
455
456
for
(std::size_t j=0;
ms_cl_prefixes
[j]!=
nullptr
; j++)
457
{
458
std::string ms_cl_prefix=
ms_cl_prefixes
[j];
459
460
if
(std::string(s, 1, ms_cl_prefix.size())==ms_cl_prefix)
461
{
462
cmdlinet::optiont
option;
463
464
std::optional<std::size_t> optnr;
465
466
if
(ms_cl_prefix.size()==1)
467
{
468
option.
islong
=
false
;
469
option.
optstring
.clear();
470
option.
optchar
=ms_cl_prefix[0];
471
optnr=
getoptnr
(option.
optchar
);
472
}
473
else
474
{
475
option.
islong
=
true
;
476
option.
optstring
=ms_cl_prefix;
477
option.
optchar
=0;
478
optnr=
getoptnr
(option.
optstring
);
479
}
480
481
if
(!optnr.has_value())
482
{
483
options
.push_back(option);
484
optnr=
options
.size()-1;
485
}
486
487
options
[*optnr].isset=
true
;
488
options
[*optnr].values.push_back(
489
std::string(s, ms_cl_prefix.size()+1, std::string::npos));
490
491
return
;
492
}
493
}
494
495
// unrecognized option
496
std::cout <<
"Warning: uninterpreted CL option '"
<< s <<
"'\n"
;
497
}
cmdlinet::getoptnr
std::optional< std::size_t > getoptnr(char option) const
Definition
cmdline.cpp:145
cmdlinet::args
argst args
Definition
cmdline.h:154
cmdlinet::options
std::vector< optiont > options
Definition
cmdline.h:193
goto_cc_cmdlinet::set
void set(const std::string &opt, const char *value) override
Set option option to value.
Definition
goto_cc_cmdline.h:33
ms_cl_cmdlinet::process_response_file
void process_response_file(const std::string &file)
Definition
ms_cl_cmdline.cpp:172
ms_cl_cmdlinet::process_response_file_line
void process_response_file_line(const std::string &line)
Definition
ms_cl_cmdline.cpp:232
ms_cl_cmdlinet::parse_env
void parse_env()
Definition
ms_cl_cmdline.cpp:100
ms_cl_cmdlinet::process_non_cl_option
void process_non_cl_option(const std::string &s)
Definition
ms_cl_cmdline.cpp:271
ms_cl_cmdlinet::parse
virtual bool parse(int, const char **)
parses the command line options into a cmdlinet
Definition
ms_cl_cmdline.cpp:124
ms_cl_cmdlinet::process_cl_option
void process_cl_option(const std::string &s)
Definition
ms_cl_cmdline.cpp:412
my_wgetline
static std::istream & my_wgetline(std::istream &in, std::wstring &dest)
Definition
ms_cl_cmdline.cpp:137
ms_cl_prefixes
const char * ms_cl_prefixes[]
Definition
ms_cl_cmdline.cpp:291
non_ms_cl_options
const char * non_ms_cl_options[]
parses the command line options into a cmdlinet
Definition
ms_cl_cmdline.cpp:25
ms_cl_flags
const char * ms_cl_flags[]
Definition
ms_cl_cmdline.cpp:285
ms_cl_cmdline.h
A special command line object for the gcc-like options.
narrow
output_type narrow(input_type input)
Run-time checked narrowing cast.
Definition
narrow.h:34
cmdlinet::optiont
Definition
cmdline.h:165
cmdlinet::optiont::optchar
char optchar
Definition
cmdline.h:169
cmdlinet::optiont::optstring
std::string optstring
Definition
cmdline.h:170
cmdlinet::optiont::islong
bool islong
Definition
cmdline.h:168
file
Definition
kdev_t.h:19
unicode.h
goto-cc
ms_cl_cmdline.cpp
Generated by
1.17.0