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