cprover
Loading...
Searching...
No Matches
gcc_cmdline.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: A special command line object for the gcc-like options
4
5Author: CM Wintersteiger, 2006
6
7\*******************************************************************/
8
11
12#include "gcc_cmdline.h"
13
14#include <cstring>
15#include <fstream>
16#include <iostream>
17#include <sstream>
18
19#include <util/prefix.h>
20
21// clang-format off
22// non-gcc options
24{
25 "--verbosity",
26 "--function",
27 "--native-compiler",
28 "--native-linker",
29 "--print-rejected-preprocessed-source",
30 "--mangle-suffix",
31 "--object-bits",
32 nullptr
33};
34
35// non-gcc options
37{
38 "--show-symbol-table",
39 "--show-function-table",
40 "--ppc-macos",
41 "--i386-linux",
42 "--i386-win32",
43 "--i386-macos",
44 "--winx64",
45 "--string-abstraction",
46 "--no-library",
47 "--16",
48 "--32",
49 "--64",
50 "--little-endian",
51 "--big-endian",
52 "--no-arch",
53 "--partial-inlining",
54 "--validate-goto-model",
55 "-?",
56 "--export-file-local-symbols",
57 // This is deprecated. Currently prints out a deprecation warning.
58 "--export-function-local-symbols",
59 nullptr
60};
61
62// separated or concatenated
64{
65 "-o",
66 "-x",
67 "-B",
68 "-iquote",
69 "-idirafter",
70 "-include",
71 "-I",
72 "-V",
73 "-D",
74 "-L",
75 "-l",
76 "-MT",
77 "-MQ",
78 "-MF",
79 "-U",
80 "-u", // goes to linker
81 "-T", // goes to linker
82 nullptr
83};
84
86{
87 "-aux-info",
88 "-arch", // Apple only
89 "--param", // Apple only
90 "-imacros",
91 "-iprefix",
92 "-iwithprefix",
93 "-iwithprefixbefore",
94 "-isystem",
95 "-isysroot",
96 "-imultilib",
97 "-imultiarch",
98 "-mcpu",
99 "-mtune",
100 "-march",
101 "-Xpreprocessor",
102 "-Xassembler",
103 "-Xlinker",
104 "-b",
105 "-std",
106 "--std",
107 "-print-file-name",
108 "-print-prog-name",
109 "-specs",
110 "--sysroot",
111 "--include", // undocumented
112 "-current_version", // on the Mac
113 "-compatibility_version", // on the Mac
114 "-z",
115 nullptr
116};
117
119{
120 "-d",
121 "-g",
122 "-A",
123 nullptr
124};
125
127{
128 "--help",
129 "-h",
130 "-r", // for ld mimicking
131 "-dylib", // for ld mimicking on MacOS
132 "-c",
133 "-S",
134 "-E",
135 "-combine",
136 "-pipe",
137 "-pass-exit-codes",
138 "-v",
139 "-###",
140 "-help",
141 "-target-help",
142 "--version",
143 "-ansi",
144 "-trigraphs",
145 "-no-integrated-cpp",
146 "-traditional",
147 "-traditional-cpp",
148 "-nostdinc++",
149 "-gen-decls",
150 "-pedantic",
151 "-pedantic-errors",
152 "-w",
153 "-dumpspecs",
154 "-dumpmachine",
155 "-dumpversion",
156 "-g",
157 "-gcoff",
158 "-gdwarf-2",
159 "-ggdb",
160 "-gstabs",
161 "-gstabs+",
162 "-gvms",
163 "-gxcoff",
164 "-gxcoff+",
165 "-p",
166 "-pg",
167 "-print-libgcc-file-name",
168 "-print-multi-directory",
169 "-print-multi-lib",
170 "-print-search-dirs",
171 "-print-sysroot",
172 "-print-sysroot-headers-suffix",
173 "-Q",
174 "-Qn",
175 "-Qy",
176 "-pthread",
177 "-save-temps",
178 "-time",
179 "-O",
180 "-O0",
181 "-O1",
182 "-O2",
183 "-O3",
184 "-O6",
185 "-Os",
186 "-Oz", // Apple only
187 "-C",
188 "-E",
189 "-H",
190 "-M",
191 "-MM",
192 "-MG",
193 "-MP",
194 "-MD",
195 "-MMD",
196 "-mno-unaligned-access",
197 "-mthumb",
198 "-mthumb-interwork",
199 "-nostdinc",
200 "-P",
201 "-remap",
202 "-undef",
203 "-nostdinc",
204 "-nostartfiles",
205 "-nodefaultlibs",
206 "-nostdlib",
207 "-pie",
208 "-rdynamic",
209 "-s",
210 "-static",
211 "-static-libgcc",
212 "--static",
213 "-shared",
214 "--shared",
215 "-shared-libgcc",
216 "-symbolic",
217 "-EB",
218 "-EL",
219 "-fast", // Apple only
220 "-coverage",
221 nullptr
222};
223// clang-format on
224
228bool gcc_cmdlinet::parse(int argc, const char **argv)
229{
230 assert(argc>0);
231 add_arg(argv[0]);
232
233 argst current_args;
234 current_args.reserve(argc - 1);
235
236 for(int i=1; i<argc; i++)
237 current_args.push_back(argv[i]);
238
239 bool result = parse_arguments(current_args, false);
240
241 parse_specs();
242
243 return result;
244}
245
247 const argst &args_to_parse,
248 bool in_spec_file)
249{
250 for(argst::const_iterator it = args_to_parse.begin();
251 it != args_to_parse.end();
252 ++it)
253 {
254 const std::string &argv_i=*it;
255
256 // options file?
257 if(has_prefix(argv_i, "@"))
258 {
259 std::ifstream opts_file(argv_i.substr(1));
260 std::ostringstream all_lines;
261 std::string line;
262
263 while(std::getline(opts_file, line))
264 all_lines << ' ' << line;
265
266 line = all_lines.str();
267 // erase leading whitespace
268 line.erase(0, line.find_first_not_of("\t "));
269
270 if(!line.empty())
271 parse_specs_line(line, false);
272
273 continue;
274 }
275
276 // file?
277 if(argv_i=="-" || !has_prefix(argv_i, "-"))
278 {
279 if(!in_spec_file)
280 add_infile_arg(argv_i);
281 continue;
282 }
283
284 if(!in_spec_file)
285 {
286 argst::const_iterator next=it;
287 ++next;
288
289 bool found=false;
290
291 if(in_list(argv_i.c_str(),
292 goto_cc_options_without_argument)) // without argument
293 {
294 set(argv_i);
295 found=true;
296 }
297
298 // separated only, and also allow concatenation with "="
300 *o!=nullptr && !found;
301 ++o)
302 {
303 if(argv_i==*o) // separated
304 {
305 found=true;
306 if(next != args_to_parse.end())
307 {
308 set(argv_i, *next);
309 ++it;
310 }
311 else
312 set(argv_i, "");
313 }
314 // concatenated with "="
315 else if(has_prefix(argv_i, std::string(*o)+"="))
316 {
317 found=true;
318 set(*o, argv_i.substr(strlen(*o)+1));
319 }
320 }
321
322 if(found)
323 continue;
324
325 // add to new_argv
326 add_arg(argv_i);
327 }
328
329 // also store in cmdlinet
330
331 if(has_prefix(argv_i, "-f")) // f-options
332 {
333 set(argv_i);
334 }
335 else if(has_prefix(argv_i, "-W")) // W-options
336 {
337 // "Wp,..." is s special case. These are to pass stuff
338 // to the preprocessor.
339 if(has_prefix(argv_i, "-Wp,"))
340 {
341 std::string value=argv_i.substr(4);
342 set("-WP,", value);
343 }
344 else
345 set(argv_i);
346 }
347 else if(has_prefix(argv_i, "-m")) // m-options
348 {
349 // these sometimes come with a value separated by '=', e.g.,
350 // -march=cpu_type
351 std::size_t equal_pos=argv_i.find('=');
352
353 if(equal_pos==std::string::npos)
354 set(argv_i); // no value
355 else
356 set(argv_i.substr(0, equal_pos), argv_i.substr(equal_pos+1));
357 }
358 // without argument
359 else if(in_list(argv_i.c_str(), gcc_options_without_argument))
360 {
361 set(argv_i);
362 }
363 else
364 {
365 argst::const_iterator next=it;
366 ++next;
367
368 bool found=false;
369
370 // separated only, and also allow concatenation with "="
371 for(const char **o=gcc_options_with_separated_argument;
372 *o!=nullptr && !found;
373 ++o)
374 {
375 if(argv_i==*o) // separated
376 {
377 found=true;
378 if(next != args_to_parse.end())
379 {
380 set(argv_i, *next);
381 if(!in_spec_file)
382 add_arg(*next);
383 ++it;
384 }
385 else
386 set(argv_i, "");
387 }
388 // concatenated with "="
389 else if(has_prefix(argv_i, std::string(*o)+"="))
390 {
391 found=true;
392 set(*o, argv_i.substr(strlen(*o)+1));
393 }
394 }
395
396 // concatenated _or_ separated, e.g., -I
397 for(const char **o=gcc_options_with_argument;
398 *o!=nullptr && !found;
399 ++o)
400 {
401 if(argv_i==*o) // separated
402 {
403 found=true;
404 if(next != args_to_parse.end())
405 {
406 set(argv_i, *next);
407 if(!in_spec_file)
408 add_arg(*next);
409 ++it;
410 }
411 else
412 set(argv_i, "");
413 }
414 else if(has_prefix(argv_i, *o)) // concatenated
415 {
416 found=true;
417 set(*o, argv_i.substr(strlen(*o)));
418 }
419 }
420
421 // concatenated only
423 *o!=nullptr && !found;
424 ++o)
425 {
426 if(has_prefix(argv_i, *o)) // concatenated
427 {
428 found=true;
429 set(*o, argv_i.substr(strlen(*o)));
430 }
431 }
432
433 if(!found)
434 {
435 // unrecognized option
436 std::cerr << "Warning: uninterpreted gcc option '" << argv_i
437 << "'\n";
438 }
439 }
440 }
441
442 return false;
443}
444
446void gcc_cmdlinet::parse_specs_line(const std::string &line, bool in_spec_file)
447{
448 // initial whitespace has been stripped
449 assert(!line.empty());
450 assert(line[0]!=' ' && line[0]!='\t');
451
452 argst args_from_specs;
453
454 for(std::string::size_type arg_start=0, arg_end=0;
455 arg_end!=std::string::npos;
456 arg_start=line.find_first_not_of("\t ", arg_end))
457 {
458 arg_end=line.find_first_of("\t ", arg_start);
459 args_from_specs.push_back(line.substr(arg_start, arg_end - arg_start));
460 }
461
462 parse_arguments(args_from_specs, in_spec_file);
463}
464
467{
468 const std::string &specs_file_name=get_value("specs");
469 if(specs_file_name.empty())
470 return;
471
472 std::ifstream specs_file(specs_file_name);
473 std::string line;
474 bool use_line=false;
475
476 while(std::getline(specs_file, line))
477 {
478 // erase leading whitespace
479 line.erase(0, line.find_first_not_of("\t "));
480
481 if(line.empty())
482 // blank lines reset the mode
483 use_line=false;
484 else if(!use_line &&
485 (line=="*link_libgcc:" ||
486 line=="*lib:" ||
487 line=="*libgcc:" ||
488 line=="*link:"))
489 use_line=true;
490 else if(use_line)
491 parse_specs_line(line, true);
492 else
493 {
494 // TODO need message interface
495 // debug() << "Warning: ignoring spec " << line << eom;
496 }
497 }
498}
std::string get_value(char option) const
Definition cmdline.cpp:48
bool parse_arguments(const argst &args_to_parse, bool in_spec_file)
void parse_specs()
Parse GCC spec files https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html.
std::vector< std::string > argst
Definition gcc_cmdline.h:30
virtual bool parse(int, const char **)
parses the command line options into a cmdlinet
void parse_specs_line(const std::string &line, bool in_spec_file)
Parse GCC spec files https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html.
void set(const std::string &opt, const char *value) override
Set option option to value.
void add_infile_arg(const std::string &arg)
static bool in_list(const char *option, const char **list)
void add_arg(const std::string &arg)
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
const char * gcc_options_with_concatenated_argument[]
const char * gcc_options_with_separated_argument[]
const char * goto_cc_options_with_separated_argument[]
const char * gcc_options_without_argument[]
const char * goto_cc_options_without_argument[]
const char * gcc_options_with_argument[]
A special command line object for the gcc-like options.