cprover
Loading...
Searching...
No Matches
ms_link_cmdline.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: A special command line object for LINK options
4
5Author: 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
22const char *non_ms_link_options[]=
23{
24 "--help",
25 "--verbosity"
26};
27
28bool 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
61bool 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
74static 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
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
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
222const 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
316static 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
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}
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
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.
static std::istream & my_wgetline(std::istream &in, std::wstring &dest)
output_type narrow(input_type input)
Run-time checked narrowing cast.
Definition: narrow.h:34
nonstd::optional< T > optionalt
Definition: optional.h:35
std::string optstring
Definition: cmdline.h:161
Definition: kdev_t.h:19