CBMC
ms_link_cmdline.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: A special command line object for LINK options
4 
5 Author: Daniel Kroening
6 
7 \*******************************************************************/
8 
11 
12 #include "ms_link_cmdline.h"
13 
14 #include <fstream>
15 #include <iostream>
16 
17 #include <util/unicode.h>
18 
22 const char *non_ms_link_options[]=
23 {
24  "--help",
25  "--verbosity"
26 };
27 
28 bool ms_link_cmdlinet::parse(const std::vector<std::string> &arguments)
29 {
30  for(std::size_t i = 0; i < arguments.size(); i++)
31  {
32  // is it a non-link option?
33  if(std::string(arguments[i], 0, 2) == "--")
34  {
35  process_non_link_option(arguments[i]);
36 
37  if(arguments[i] == "--verbosity")
38  {
39  if(i < arguments.size() - 1)
40  {
41  set(arguments[i], arguments[i + 1]);
42  i++; // skip ahead
43  }
44  }
45  }
46  else if(!arguments[i].empty() && arguments[i][0] == '@')
47  {
48  // potentially recursive
49  process_response_file(std::string(arguments[i], 1, std::string::npos));
50  }
51  else
52  process_link_option(arguments[i]);
53  }
54 
55  return false;
56 }
57 
61 bool ms_link_cmdlinet::parse(int argc, const char **argv)
62 {
63  // should really use "wide" argv from wmain()
64 
65  std::vector<std::string> arguments;
66 
67  // skip argv[0]
68  for(int i = 1; i < argc; i++)
69  arguments.push_back(argv[i]);
70 
71  return parse(arguments);
72 }
73 
74 static std::istream &my_wgetline(std::istream &in, std::wstring &dest)
75 {
76  // We should support this properly,
77  // but will just strip right now.
78  dest.clear();
79 
80  while(in)
81  {
82  char ch1, ch2;
83  in.get(ch1);
84  in.get(ch2);
85 
86  if(!in)
87  {
88  if(!dest.empty())
89  in.clear();
90  break;
91  }
92 
93  if(ch1 == '\r')
94  {
95  // ignore
96  }
97  else if(ch1 == '\n')
98  {
99  in.clear();
100  break; // line end
101  }
102  else
103  dest += wchar_t(ch1 + (ch2 << 8));
104  }
105 
106  return in;
107 }
108 
110 void ms_link_cmdlinet::process_response_file(const std::string &file)
111 {
112  std::ifstream infile(file);
113 
114  if(!infile)
115  {
116  std::cerr << "failed to open response file '" << file << "'\n";
117  return;
118  }
119 
120  // these may be Unicode -- which is indicated by 0xff 0xfe
121  std::string line;
122  getline(infile, line);
123  if(
124  line.size() >= 2 && line[0] == static_cast<char>(0xff) &&
125  line[1] == static_cast<char>(0xfe))
126  {
127  // Unicode, UTF-16 little endian
128 
129 #if 1
130  // Re-open -- should be using wifstream,
131  // but this isn't available everywhere.
132  std::ifstream infile2(file, std::ios::binary);
133  infile2.seekg(2);
134  std::wstring wline;
135 
136  while(my_wgetline(infile2, wline))
137  process_response_file_line(narrow(wline)); // we UTF-8 it
138 
139 #else
140 
141  std::wifstream infile2(file, std::ios::binary);
142  std::wstring wline;
143 
144  while(std::getline(infile2, wline))
145  process_response_file_line(narrow(wline)); // we UTF-8 it
146 
147 #endif
148  }
149  else if(
150  line.size() >= 3 && line[0] == static_cast<char>(0xef) &&
151  line[1] == static_cast<char>(0xbb) && line[2] == static_cast<char>(0xbf))
152  {
153  // This is the UTF-8 BOM. We can proceed as usual, since
154  // we use UTF-8 internally.
155  infile.seekg(3);
156 
157  while(getline(infile, line))
159  }
160  else
161  {
162  // normal ASCII
163  infile.seekg(0);
164  while(getline(infile, line))
166  }
167 }
168 
170 void ms_link_cmdlinet::process_response_file_line(const std::string &line)
171 {
172  // In a response file, multiple compiler options and source-code files can
173  // appear on one line. A single compiler-option specification must appear
174  // on one line (cannot span multiple lines). Response files can have
175  // comments that begin with the # symbol.
176 
177  if(line.empty())
178  return;
179  if(line[0] == '#')
180  return; // comment
181 
182  std::vector<std::string> arguments;
183  std::string option;
184  bool in_quotes = false;
185  for(std::size_t i = 0; i < line.size(); i++)
186  {
187  char ch = line[i];
188 
189  if(ch == ' ' && !in_quotes)
190  {
191  if(!option.empty())
192  arguments.push_back(option);
193  option.clear();
194  }
195  else if(ch == '"')
196  {
197  in_quotes = !in_quotes;
198  }
199  else
200  option += ch;
201  }
202 
203  if(!option.empty())
204  arguments.push_back(option);
205 
206  parse(arguments);
207 }
208 
211 {
212  set(s);
213 
214  for(const auto & opt : non_ms_link_options)
215  if(s == opt)
216  return;
217 
218  // unrecognized option
219  std::cout << "Warning: uninterpreted non-LINK option '" << s << "'\n";
220 }
221 
222 const char *ms_link_options[] = {
223  "ALIGN",
224  "ALLOWBIND",
225  "ALLOWISOLATION",
226  "APPCONTAINER",
227  "ASSEMBLYDEBUG",
228  "ASSEMBLYLINKRESOURCE",
229  "ASSEMBLYMODULE",
230  "ASSEMBLYRESOURCE",
231  "BASE",
232  "CLRIMAGETYPE",
233  "CLRLOADEROPTIMIZATION",
234  "CLRSUPPORTLASTERROR",
235  "CLRTHREADATTRIBUTE",
236  "CLRUNMANAGEDCODECHECK",
237  "DEBUG",
238  "DEF",
239  "DEFAULTLIB",
240  "DELAY",
241  "DELAYLOAD",
242  "DELAYSIGN",
243  "DLL",
244  "DRIVER",
245  "DYNAMICBASE",
246  "ENTRY",
247  "ERRORREPORT",
248  "EXPORT",
249  "EXPORTPADMIN",
250  "FASTGENPROFILE",
251  "FIXED",
252  "FORCE",
253  "FUNCTIONPADMIN",
254  "GUARD",
255  "GENPROFILE",
256  "HEAP",
257  "HIGHENTROPYVA",
258  "IDLOUT",
259  "IGNORE",
260  "IGNOREIDL",
261  "IMPLIB",
262  "INCLUDE",
263  "INCREMENTAL",
264  "INTEGRITYCHECK",
265  "KERNEL",
266  "KEYCONTAINER",
267  "KEYFILE",
268  "LARGEADDRESSAWARE",
269  "LIBPATH",
270  "LTCG",
271  "MACHINE",
272  "MANIFEST",
273  "MANIFESTDEPENDENCY",
274  "MANIFESTFILE",
275  "MANIFESTINPUT",
276  "MANIFESTUAC",
277  "MAP",
278  "MAPINFO",
279  "MERGE",
280  "MIDL",
281  "NOASSEMBLY",
282  "NODEFAULTLIB",
283  "NOENTRY",
284  "NOIMPLIB",
285  "NOLOGO",
286  "NXCOMPAT",
287  "OPT",
288  "ORDER",
289  "OUT",
290  "PDB",
291  "PDBSTRIPPED",
292  "PROFILE",
293  "RELEASE",
294  "SAFESEH",
295  "SECTION",
296  "STACK",
297  "STUB",
298  "SUBSYSTEM",
299  "SWAPRUN",
300  "TLBID",
301  "TLBOUT",
302  "TIME",
303  "TSAWARE",
304  "USEPROFILE",
305  "VERBOSE",
306  "VERSION",
307  "WINMD",
308  "WINMDDELAYSIGN",
309  "WINMDFILE",
310  "WINMDKEYCONTAINER",
311  "WINMDKEYFILE",
312  "WHOLEARCHIVE",
313  "WX"
314 };
315 
316 static std::string to_upper_string(const std::string &s)
317 {
318  std::string result = s;
319  transform(result.begin(), result.end(), result.begin(), toupper);
320  return result;
321 }
322 
323 void ms_link_cmdlinet::process_link_option(const std::string &s)
324 {
325  if(s.empty())
326  return;
327 
328  if(s[0] != '/' && s[0] != '-')
329  {
330  args.push_back(s);
331  return;
332  }
333 
334  for(const std::string ms_link_option : ms_link_options)
335  {
336  // These are case insensitive.
337  if(
338  to_upper_string(std::string(s, 1, std::string::npos)) == ms_link_option ||
339  to_upper_string(std::string(s, 1, ms_link_option.size() + 1)) == ms_link_option + ':')
340  {
341  optionalt<std::size_t> optnr = getoptnr(ms_link_option);
342 
343  if(!optnr.has_value())
344  {
345  cmdlinet::optiont option;
346  option.islong = true;
347  option.optstring = ms_link_option;
348  option.optchar = 0;
349  options.push_back(option);
350  optnr = options.size() - 1;
351  }
352 
353  options[*optnr].isset = true;
354 
355  if(s.size() > ms_link_option.size() + 1)
356  options[*optnr].values.push_back(
357  std::string(s, ms_link_option.size() + 2, std::string::npos));
358 
359  return;
360  }
361  }
362 
363  // unrecognized option
364  std::cout << "Warning: uninterpreted LINK option '" << s << "'\n";
365 }
cmdlinet::args
argst args
Definition: cmdline.h:145
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
transform
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
Definition: abstract_value_object.cpp:159
cmdlinet::options
std::vector< optiont > options
Definition: cmdline.h:184
cmdlinet::optiont::islong
bool islong
Definition: cmdline.h:159
cmdlinet::optiont::optstring
std::string optstring
Definition: cmdline.h:161
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
narrow
output_type narrow(input_type input)
Run-time checked narrowing cast.
Definition: narrow.h:34
cmdlinet::getoptnr
optionalt< std::size_t > getoptnr(char option) const
Definition: cmdline.cpp:135
cmdlinet::optiont::optchar
char optchar
Definition: cmdline.h:160
binary
static std::string binary(const constant_exprt &src)
Definition: json_expr.cpp:189
unicode.h
cmdlinet::optiont
Definition: cmdline.h:155