cprover
ms_cl_mode.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Visual Studio CL Mode
4 
5 Author: CM Wintersteiger, 2006
6 
7 \*******************************************************************/
8 
11 
12 #include "ms_cl_mode.h"
13 
14 #ifdef _WIN32
15 #define EX_OK 0
16 #define EX_USAGE 64
17 #define EX_SOFTWARE 70
18 #else
19 #include <sysexits.h>
20 #endif
21 
22 #include <iostream>
23 
24 #include <util/config.h>
25 #include <util/file_util.h>
26 #include <util/get_base_name.h>
27 #include <util/message.h>
28 #include <util/prefix.h>
29 
30 #include "compile.h"
31 #include "ms_cl_version.h"
32 
33 static bool has_directory_suffix(const std::string &path)
34 {
35  // MS CL decides whether a parameter is a directory on the
36  // basis of the / or \\ suffix; it doesn't matter
37  // whether the directory actually exists.
38  return path.empty() ? false :
39  path.back()=='/' || path.back()=='\\';
40 }
41 
44 {
45  if(cmdline.isset('?') ||
46  cmdline.isset("help"))
47  {
48  help();
49  return EX_OK;
50  }
51 
52  compilet compiler(cmdline, message_handler, cmdline.isset("WX"));
53 
54  #if 0
55  bool act_as_ld=
56  has_prefix(base_name, "link") ||
57  has_prefix(base_name, "goto-link");
58  #endif
59 
60  const auto verbosity = eval_verbosity(
62 
63  ms_cl_versiont ms_cl_version;
64  ms_cl_version.get("cl.exe");
65 
66  debug() << "Visual Studio mode " << ms_cl_version << eom;
67 
68  // get configuration
70 
71  if(ms_cl_version.target == ms_cl_versiont::targett::x86)
73  else if(ms_cl_version.target == ms_cl_versiont::targett::ARM)
75  else if(ms_cl_version.target == ms_cl_versiont::targett::x86)
77 
79  compiler.object_file_extension="obj";
80 
81  // determine actions to be undertaken
82 
83  if(cmdline.isset('E') || cmdline.isset('P'))
84  compiler.mode=compilet::PREPROCESS_ONLY;
85  else if(cmdline.isset('c'))
86  compiler.mode=compilet::COMPILE_ONLY;
87  else
89 
90  if(cmdline.isset("std"))
91  {
92  const std::string std_string = cmdline.get_value("std");
93 
94  if(
95  std_string == ":c++14" || std_string == "=c++14" ||
96  std_string == ":c++17" || std_string == "=c++17" ||
97  std_string == ":c++latest" || std_string == "=c++latest")
98  {
99  // we don't have any newer version at the moment
100  config.cpp.set_cpp14();
101  }
102  else if(std_string == ":c++11" || std_string == "=c++11")
103  {
104  // this isn't really a Visual Studio variant, we just do this for GCC
105  // command-line compatibility
106  config.cpp.set_cpp11();
107  }
108  else
109  warning() << "unknown language standard " << std_string << eom;
110  }
111  else
112  config.cpp.set_cpp14();
113 
114  compiler.echo_file_name=true;
115 
116  if(cmdline.isset("Fo"))
117  {
118  std::string Fo_value = cmdline.get_value("Fo");
119 
120  // this could be a directory or a file name
121  if(has_directory_suffix(Fo_value))
122  {
123  compiler.output_directory_object = Fo_value;
124 
125  if(!is_directory(Fo_value))
126  warning() << "not a directory: " << Fo_value << eom;
127  }
128  else
129  compiler.output_file_object = Fo_value;
130  }
131 
132  if(
133  compiler.mode == compilet::COMPILE_ONLY &&
134  cmdline.args.size() > 1 &&
135  compiler.output_directory_object.empty())
136  {
137  error() << "output directory required for /c with multiple input files"
138  << eom;
139  return EX_USAGE;
140  }
141 
142  if(cmdline.isset("Fe"))
143  {
144  compiler.output_file_executable=cmdline.get_value("Fe");
145 
146  // this could be a directory
147  if(
148  has_directory_suffix(compiler.output_file_executable) &&
149  cmdline.args.size() >= 1)
150  {
151  if(!is_directory(compiler.output_file_executable))
152  warning() << "not a directory: "
153  << compiler.output_file_executable << eom;
154 
155  compiler.output_file_executable+=
156  get_base_name(cmdline.args[0], true) + ".exe";
157  }
158  }
159  else
160  {
161  // We need at least one argument.
162  // CL uses the first file name it gets!
163  if(cmdline.args.size()>=1)
164  compiler.output_file_executable=
165  get_base_name(cmdline.args[0], true)+".exe";
166  }
167 
168  if(cmdline.isset('J'))
170 
171  if(verbosity > messaget::M_STATISTICS)
172  {
173  std::list<std::string>::iterator it;
174 
175  std::cout << "Defines:\n";
176  for(it=config.ansi_c.defines.begin();
177  it!=config.ansi_c.defines.end();
178  it++)
179  {
180  std::cout << " " << (*it) << '\n';
181  }
182 
183  std::cout << "Undefines:\n";
184  for(it=config.ansi_c.undefines.begin();
185  it!=config.ansi_c.undefines.end();
186  it++)
187  {
188  std::cout << " " << (*it) << '\n';
189  }
190 
191  std::cout << "Preprocessor Options:\n";
192  for(it=config.ansi_c.preprocessor_options.begin();
194  it++)
195  {
196  std::cout << " " << (*it) << '\n';
197  }
198 
199  std::cout << "Include Paths:\n";
200  for(it=config.ansi_c.include_paths.begin();
201  it!=config.ansi_c.include_paths.end();
202  it++)
203  {
204  std::cout << " " << (*it) << '\n';
205  }
206 
207  std::cout << "Library Paths:\n";
208  for(it=compiler.library_paths.begin();
209  it!=compiler.library_paths.end();
210  it++)
211  {
212  std::cout << " " << (*it) << '\n';
213  }
214 
215  std::cout << "Output file (object): "
216  << compiler.output_file_object << '\n';
217  std::cout << "Output file (executable): "
218  << compiler.output_file_executable << '\n';
219  }
220 
221  // Parse input program, convert to goto program, write output
222  return compiler.doit() ? EX_USAGE : EX_OK;
223 }
224 
227 {
228  std::cout << "goto-cl understands the options of CL plus the following.\n\n";
229 }
struct configt::ansi_ct ansi_c
ms_cl_cmdlinet & cmdline
Definition: ms_cl_mode.h:37
static unsigned eval_verbosity(const std::string &user_input, const message_levelt default_verbosity, message_handlert &dest)
Parse a (user-)provided string as a verbosity level and set it as the verbosity of dest...
Definition: message.cpp:98
std::list< std::string > defines
Definition: config.h:121
std::string get_value(char option) const
Definition: cmdline.cpp:45
std::list< std::string > undefines
Definition: config.h:122
virtual void help_mode()
display command line help
Definition: ms_cl_mode.cpp:226
configt config
Definition: config.cpp:24
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
Visual Studio CL Mode.
mstreamt & warning() const
Definition: message.h:391
void set_cpp14()
Definition: config.h:143
bool set(const cmdlinet &cmdline)
Definition: config.cpp:767
argst args
Definition: cmdline.h:44
virtual bool isset(char option) const
Definition: cmdline.cpp:27
flavourt mode
Definition: config.h:115
mstreamt & error() const
Definition: message.h:386
void set_32()
Definition: config.cpp:31
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
bool char_is_unsigned
Definition: config.h:43
static eomt eom
Definition: message.h:284
Compile and link source and object files.
struct configt::cppt cpp
void set_cpp11()
Definition: config.h:142
void get(const std::string &executable)
virtual void help()
display command line help
void set_64()
Definition: config.cpp:36
virtual int doit()
does it.
Definition: ms_cl_mode.cpp:43
console_message_handlert message_handler
Definition: ms_cl_mode.h:38
mstreamt & debug() const
Definition: message.h:416
bool is_directory(const std::string &path)
Definition: file_util.cpp:154
std::list< std::string > preprocessor_options
Definition: config.h:123
static bool has_directory_suffix(const std::string &path)
Definition: ms_cl_mode.cpp:33
const std::string base_name
Definition: goto_cc_mode.h:38
std::list< std::string > include_paths
Definition: config.h:124