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