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