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