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 <util/invariant.h>
15#include <util/prefix.h>
16
17#include <cstring>
18#include <fstream> // IWYU pragma: keep
19#include <iostream>
20#include <sstream> // IWYU pragma: keep
21
22// clang-format off
23// non-gcc options
25{
26 "--verbosity",
27 "--function",
28 "--native-compiler",
29 "--native-linker",
30 "--print-rejected-preprocessed-source",
31 "--mangle-suffix",
32 "--object-bits",
33 nullptr
34};
35
36// non-gcc options
38{
39 "--show-symbol-table",
40 "--show-function-table",
41 "--ppc-macos",
42 "--i386-linux",
43 "--i386-win32",
44 "--i386-macos",
45 "--winx64",
46 "--string-abstraction",
47 "--no-library",
48 "--16",
49 "--32",
50 "--64",
51 "--little-endian",
52 "--big-endian",
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 "-target",
115 "--target",
116 "-z",
117 nullptr
118};
119
121{
122 "-d",
123 "-g",
124 "-A",
125 nullptr
126};
127
129{
130 "--help",
131 "-h",
132 "-r", // for ld mimicking
133 "-dylib", // for ld mimicking on MacOS
134 "-c",
135 "-S",
136 "-E",
137 "-combine",
138 "-pipe",
139 "-pass-exit-codes",
140 "-v",
141 "-###",
142 "-help",
143 "-target-help",
144 "--version",
145 "-ansi",
146 "-trigraphs",
147 "-no-integrated-cpp",
148 "-traditional",
149 "-traditional-cpp",
150 "-nostdinc++",
151 "-gen-decls",
152 "-pedantic",
153 "-pedantic-errors",
154 "-w",
155 "-dumpspecs",
156 "-dumpmachine",
157 "-dumpversion",
158 "-g",
159 "-gcoff",
160 "-gdwarf-2",
161 "-ggdb",
162 "-gstabs",
163 "-gstabs+",
164 "-gvms",
165 "-gxcoff",
166 "-gxcoff+",
167 "-p",
168 "-pg",
169 "-print-libgcc-file-name",
170 "-print-multi-directory",
171 "-print-multi-lib",
172 "-print-search-dirs",
173 "-print-sysroot",
174 "-print-sysroot-headers-suffix",
175 "-Q",
176 "-Qn",
177 "-Qy",
178 "-pthread",
179 "-save-temps",
180 "-time",
181 "-O",
182 "-O0",
183 "-O1",
184 "-O2",
185 "-O3",
186 "-O6",
187 "-Os",
188 "-Oz", // Apple only
189 "-C",
190 "-E",
191 "-H",
192 "-M",
193 "-MM",
194 "-MG",
195 "-MP",
196 "-MD",
197 "-MMD",
198 "-mno-unaligned-access",
199 "-mthumb",
200 "-mthumb-interwork",
201 "-nostdinc",
202 "-P",
203 "-remap",
204 "-undef",
205 "-nostdinc",
206 "-nostartfiles",
207 "-nodefaultlibs",
208 "-nostdlib",
209 "-pie",
210 "-rdynamic",
211 "-s",
212 "-static",
213 "-static-libgcc",
214 "--static",
215 "-shared",
216 "--shared",
217 "-shared-libgcc",
218 "-symbolic",
219 "-EB",
220 "-EL",
221 "-fast", // Apple only
222 "-coverage",
223 nullptr
224};
225// clang-format on
226
230bool gcc_cmdlinet::parse(int argc, const char **argv)
231{
232 PRECONDITION(argc > 0);
233 add_arg(argv[0]);
234
235 argst current_args;
236 current_args.reserve(argc - 1);
237
238 for(int i=1; i<argc; i++)
239 current_args.push_back(argv[i]);
240
241 bool result = parse_arguments(current_args, false);
242
243 parse_specs();
244
245 return result;
246}
247
249 const argst &args_to_parse,
250 bool in_spec_file)
251{
252 for(argst::const_iterator it = args_to_parse.begin();
253 it != args_to_parse.end();
254 ++it)
255 {
256 const std::string &argv_i=*it;
257
258 // options file?
259 if(has_prefix(argv_i, "@"))
260 {
261 std::ifstream opts_file(argv_i.substr(1));
262 std::ostringstream all_lines;
263 std::string line;
264
265 while(std::getline(opts_file, line))
266 all_lines << ' ' << line;
267
268 line = all_lines.str();
269 // erase leading whitespace
270 line.erase(0, line.find_first_not_of("\t "));
271
272 if(!line.empty())
273 parse_specs_line(line, false);
274
275 continue;
276 }
277
278 // file?
279 if(argv_i=="-" || !has_prefix(argv_i, "-"))
280 {
281 if(!in_spec_file)
282 add_infile_arg(argv_i);
283 continue;
284 }
285
286 if(!in_spec_file)
287 {
288 argst::const_iterator next=it;
289 ++next;
290
291 bool found=false;
292
293 if(in_list(argv_i.c_str(),
294 goto_cc_options_without_argument)) // without argument
295 {
296 set(argv_i);
297 found=true;
298 }
299
300 // separated only, and also allow concatenation with "="
302 *o!=nullptr && !found;
303 ++o)
304 {
305 if(argv_i==*o) // separated
306 {
307 found=true;
308 if(next != args_to_parse.end())
309 {
310 set(argv_i, *next);
311 ++it;
312 }
313 else
314 set(argv_i, "");
315 }
316 // concatenated with "="
317 else if(has_prefix(argv_i, std::string(*o)+"="))
318 {
319 found=true;
320 set(*o, argv_i.substr(strlen(*o)+1));
321 }
322 }
323
324 if(found)
325 continue;
326
327 // add to new_argv
328 add_arg(argv_i);
329 }
330
331 // also store in cmdlinet
332
333 if(has_prefix(argv_i, "-f")) // f-options
334 {
335 set(argv_i);
336 }
337 else if(has_prefix(argv_i, "-W")) // W-options
338 {
339 // "Wp,..." is s special case. These are to pass stuff
340 // to the preprocessor.
341 if(has_prefix(argv_i, "-Wp,"))
342 {
343 std::string value=argv_i.substr(4);
344 set("-WP,", value);
345 }
346 else
347 set(argv_i);
348 }
349 else if(has_prefix(argv_i, "-m")) // m-options
350 {
351 // these sometimes come with a value separated by '=', e.g.,
352 // -march=cpu_type
353 std::size_t equal_pos=argv_i.find('=');
354
355 if(equal_pos==std::string::npos)
356 set(argv_i); // no value
357 else
358 set(argv_i.substr(0, equal_pos), argv_i.substr(equal_pos+1));
359 }
360 // without argument
361 else if(in_list(argv_i.c_str(), gcc_options_without_argument))
362 {
363 set(argv_i);
364 }
365 else
366 {
367 argst::const_iterator next=it;
368 ++next;
369
370 bool found=false;
371
372 // separated only, and also allow concatenation with "="
373 for(const char **o=gcc_options_with_separated_argument;
374 *o!=nullptr && !found;
375 ++o)
376 {
377 if(argv_i==*o) // separated
378 {
379 found=true;
380 if(next != args_to_parse.end())
381 {
382 set(argv_i, *next);
383 if(!in_spec_file)
384 add_arg(*next);
385 ++it;
386 }
387 else
388 set(argv_i, "");
389 }
390 // concatenated with "="
391 else if(has_prefix(argv_i, std::string(*o)+"="))
392 {
393 found=true;
394 set(*o, argv_i.substr(strlen(*o)+1));
395 }
396 }
397
398 // concatenated _or_ separated, e.g., -I
399 for(const char **o=gcc_options_with_argument;
400 *o!=nullptr && !found;
401 ++o)
402 {
403 if(argv_i==*o) // separated
404 {
405 found=true;
406 if(next != args_to_parse.end())
407 {
408 set(argv_i, *next);
409 if(!in_spec_file)
410 add_arg(*next);
411 ++it;
412 }
413 else
414 set(argv_i, "");
415 }
416 else if(has_prefix(argv_i, *o)) // concatenated
417 {
418 found=true;
419 set(*o, argv_i.substr(strlen(*o)));
420 }
421 }
422
423 // concatenated only
425 *o!=nullptr && !found;
426 ++o)
427 {
428 if(has_prefix(argv_i, *o)) // concatenated
429 {
430 found=true;
431 set(*o, argv_i.substr(strlen(*o)));
432 }
433 }
434
435 if(!found)
436 {
437 // unrecognized option
438 std::cerr << "Warning: uninterpreted gcc option '" << argv_i
439 << "'\n";
440 }
441 }
442 }
443
444 return false;
445}
446
448void gcc_cmdlinet::parse_specs_line(const std::string &line, bool in_spec_file)
449{
450 // initial whitespace has been stripped
451 PRECONDITION(!line.empty());
452 PRECONDITION(line[0] != ' ' && line[0] != '\t');
453
454 argst args_from_specs;
455
456 for(std::string::size_type arg_start=0, arg_end=0;
457 arg_end!=std::string::npos;
458 arg_start=line.find_first_not_of("\t ", arg_end))
459 {
460 arg_end=line.find_first_of("\t ", arg_start);
461 args_from_specs.push_back(line.substr(arg_start, arg_end - arg_start));
462 }
463
464 parse_arguments(args_from_specs, in_spec_file);
465}
466
469{
470 const std::string &specs_file_name=get_value("specs");
471 if(specs_file_name.empty())
472 return;
473
474 std::ifstream specs_file(specs_file_name);
475 std::string line;
476 bool use_line=false;
477
478 while(std::getline(specs_file, line))
479 {
480 // erase leading whitespace
481 line.erase(0, line.find_first_not_of("\t "));
482
483 if(line.empty())
484 // blank lines reset the mode
485 use_line=false;
486 else if(!use_line &&
487 (line=="*link_libgcc:" ||
488 line=="*lib:" ||
489 line=="*libgcc:" ||
490 line=="*link:"))
491 use_line=true;
492 else if(use_line)
493 parse_specs_line(line, true);
494 else
495 {
496 // TODO need message interface
497 // debug() << "Warning: ignoring spec " << line << eom;
498 }
499 }
500}
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.
#define PRECONDITION(CONDITION)
Definition invariant.h:463