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 
24 // non-gcc options
26 {
27  "--verbosity",
28  "--function",
29  "--native-compiler",
30  "--native-linker",
31  "--print-rejected-preprocessed-source",
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  "-?",
55  nullptr
56 };
57 
58 // separated or concatenated
60 {
61  "-o",
62  "-x",
63  "-B",
64  "-iquote",
65  "-idirafter",
66  "-include",
67  "-I",
68  "-V",
69  "-D",
70  "-L",
71  "-l",
72  "-MT",
73  "-MQ",
74  "-MF",
75  "-U",
76  "-u", // goes to linker
77  "-T", // goes to linker
78  nullptr
79 };
80 
82 {
83  "-aux-info",
84  "--param", // Apple only
85  "-imacros",
86  "-iprefix",
87  "-iwithprefix",
88  "-iwithprefixbefore",
89  "-isystem",
90  "-isysroot",
91  "-imultilib",
92  "-imultiarch",
93  "-mcpu",
94  "-mtune",
95  "-march",
96  "-Xpreprocessor",
97  "-Xassembler",
98  "-Xlinker",
99  "-b",
100  "-std",
101  "--std",
102  "-print-file-name",
103  "-print-prog-name",
104  "-specs",
105  "--sysroot",
106  "--include", // undocumented
107  "-current_version", // on the Mac
108  "-compatibility_version", // on the Mac
109  "-z",
110  nullptr
111 };
112 
114 {
115  "-d",
116  "-g",
117  "-A",
118  nullptr
119 };
120 
122 {
123  "--help",
124  "-h",
125  "-r", // for ld mimicking
126  "-dylib", // for ld mimicking on MacOS
127  "-c",
128  "-S",
129  "-E",
130  "-combine",
131  "-pipe",
132  "-pass-exit-codes",
133  "-v",
134  "-###",
135  "-help",
136  "-target-help",
137  "--version",
138  "-ansi",
139  "-trigraphs",
140  "-no-integrated-cpp",
141  "-traditional",
142  "-traditional-cpp",
143  "-nostdinc++",
144  "-gen-decls",
145  "-pedantic",
146  "-pedantic-errors",
147  "-w",
148  "-dumpspecs",
149  "-dumpmachine",
150  "-dumpversion",
151  "-g",
152  "-gcoff",
153  "-gdwarf-2",
154  "-ggdb",
155  "-gstabs",
156  "-gstabs+",
157  "-gvms",
158  "-gxcoff",
159  "-gxcoff+",
160  "-p",
161  "-pg",
162  "-print-libgcc-file-name",
163  "-print-multi-directory",
164  "-print-multi-lib",
165  "-print-search-dirs",
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 
215 bool gcc_cmdlinet::parse(int argc, const char **argv)
216 {
217  assert(argc>0);
218  add_arg(argv[0]);
219 
220  argst args;
221  args.reserve(argc-1);
222 
223  for(int i=1; i<argc; i++)
224  args.push_back(argv[i]);
225 
226  bool result=parse_arguments(args, false);
227 
228  parse_specs();
229 
230  return result;
231 }
232 
234  const argst &args,
235  bool in_spec_file)
236 {
237  for(argst::const_iterator it=args.begin();
238  it!=args.end();
239  ++it)
240  {
241  const std::string &argv_i=*it;
242 
243  // options file?
244  if(has_prefix(argv_i, "@"))
245  {
246  std::ifstream opts_file(argv_i.substr(1));
247  std::string line;
248 
249  while(std::getline(opts_file, line))
250  {
251  // erase leading whitespace
252  line.erase(0, line.find_first_not_of("\t "));
253 
254  if(!line.empty())
255  parse_specs_line(line);
256  }
257 
258  continue;
259  }
260 
261  // file?
262  if(argv_i=="-" || !has_prefix(argv_i, "-"))
263  {
264  if(!in_spec_file)
265  add_infile_arg(argv_i);
266  continue;
267  }
268 
269  if(!in_spec_file)
270  {
271  argst::const_iterator next=it;
272  ++next;
273 
274  bool found=false;
275 
276  if(in_list(argv_i.c_str(),
277  goto_cc_options_without_argument)) // without argument
278  {
279  set(argv_i);
280  found=true;
281  }
282 
283  // separated only, and also allow concatenation with "="
284  for(const char **o=goto_cc_options_with_separated_argument;
285  *o!=nullptr && !found;
286  ++o)
287  {
288  if(argv_i==*o) // separated
289  {
290  found=true;
291  if(next!=args.end())
292  {
293  set(argv_i, *next);
294  ++it;
295  }
296  else
297  set(argv_i, "");
298  }
299  // concatenated with "="
300  else if(has_prefix(argv_i, std::string(*o)+"="))
301  {
302  found=true;
303  set(*o, argv_i.substr(strlen(*o)+1));
304  }
305  }
306 
307  if(found)
308  continue;
309 
310  // add to new_argv
311  add_arg(argv_i);
312  }
313 
314  // also store in cmdlinet
315 
316  if(has_prefix(argv_i, "-f")) // f-options
317  {
318  set(argv_i);
319  }
320  else if(has_prefix(argv_i, "-W")) // W-options
321  {
322  // "Wp,..." is s special case. These are to pass stuff
323  // to the preprocessor.
324  if(has_prefix(argv_i, "-Wp,"))
325  {
326  std::string value=argv_i.substr(4);
327  set("-WP,", value);
328  }
329  else
330  set(argv_i);
331  }
332  else if(has_prefix(argv_i, "-m")) // m-options
333  {
334  // these sometimes come with a value separated by '=', e.g.,
335  // -march=cpu_type
336  std::size_t equal_pos=argv_i.find('=');
337 
338  if(equal_pos==std::string::npos)
339  set(argv_i); // no value
340  else
341  set(argv_i.substr(0, equal_pos), argv_i.substr(equal_pos+1));
342  }
343  // without argument
344  else if(in_list(argv_i.c_str(), gcc_options_without_argument))
345  {
346  set(argv_i);
347  }
348  else
349  {
350  argst::const_iterator next=it;
351  ++next;
352 
353  bool found=false;
354 
355  // separated only, and also allow concatenation with "="
356  for(const char **o=gcc_options_with_separated_argument;
357  *o!=nullptr && !found;
358  ++o)
359  {
360  if(argv_i==*o) // separated
361  {
362  found=true;
363  if(next!=args.end())
364  {
365  set(argv_i, *next);
366  if(!in_spec_file)
367  add_arg(*next);
368  ++it;
369  }
370  else
371  set(argv_i, "");
372  }
373  // concatenated with "="
374  else if(has_prefix(argv_i, std::string(*o)+"="))
375  {
376  found=true;
377  set(*o, argv_i.substr(strlen(*o)+1));
378  }
379  }
380 
381  // concatenated _or_ separated, e.g., -I
382  for(const char **o=gcc_options_with_argument;
383  *o!=nullptr && !found;
384  ++o)
385  {
386  if(argv_i==*o) // separated
387  {
388  found=true;
389  if(next!=args.end())
390  {
391  set(argv_i, *next);
392  if(!in_spec_file)
393  add_arg(*next);
394  ++it;
395  }
396  else
397  set(argv_i, "");
398  }
399  else if(has_prefix(argv_i, *o)) // concatenated
400  {
401  found=true;
402  set(*o, argv_i.substr(strlen(*o)));
403  }
404  }
405 
406  // concatenated only
407  for(const char **o=gcc_options_with_concatenated_argument;
408  *o!=nullptr && !found;
409  ++o)
410  {
411  if(has_prefix(argv_i, *o)) // concatenated
412  {
413  found=true;
414  set(*o, argv_i.substr(strlen(*o)));
415  }
416  }
417 
418  if(!found)
419  {
420  // unrecognized option
421  std::cerr << "Warning: uninterpreted gcc option '" << argv_i
422  << "'\n";
423  }
424  }
425  }
426 
427  return false;
428 }
429 
431 void gcc_cmdlinet::parse_specs_line(const std::string &line)
432 {
433  // initial whitespace has been stripped
434  assert(!line.empty());
435  assert(line[0]!=' ' && line[0]!='\t');
436 
437  argst args;
438 
439  for(std::string::size_type arg_start=0, arg_end=0;
440  arg_end!=std::string::npos;
441  arg_start=line.find_first_not_of("\t ", arg_end))
442  {
443  arg_end=line.find_first_of("\t ", arg_start);
444  args.push_back(line.substr(arg_start, arg_end-arg_start));
445  }
446 
447  parse_arguments(args, true);
448 }
449 
452 {
453  const std::string &specs_file_name=get_value("specs");
454  if(specs_file_name.empty())
455  return;
456 
457  std::ifstream specs_file(specs_file_name);
458  std::string line;
459  bool use_line=false;
460 
461  while(std::getline(specs_file, line))
462  {
463  // erase leading whitespace
464  line.erase(0, line.find_first_not_of("\t "));
465 
466  if(line.empty())
467  // blank lines reset the mode
468  use_line=false;
469  else if(!use_line &&
470  (line=="*link_libgcc:" ||
471  line=="*lib:" ||
472  line=="*libgcc:" ||
473  line=="*link:"))
474  use_line=true;
475  else if(use_line)
476  parse_specs_line(line);
477  else
478  {
479  // TODO need message interface
480  // debug() << "Warning: ignoring spec " << line << eom;
481  }
482  }
483 }
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 **)
std::string get_value(char option) const
Definition: cmdline.cpp:46
unsignedbv_typet size_type()
Definition: c_types.cpp:57
const char * gcc_options_without_argument[]
const char * goto_cc_options_without_argument[]
Definition: gcc_cmdline.cpp:36
std::vector< std::string > argst
Definition: gcc_cmdline.h:30
const char * goto_cc_options_with_separated_argument[]
parses the command line options into a cmdlinet
Definition: gcc_cmdline.cpp:25
argst args
Definition: cmdline.h:35
const char * gcc_options_with_argument[]
Definition: gcc_cmdline.cpp:59
static bool in_list(const char *option, const char **list)
void add_arg(const std::string &arg)
const char * gcc_options_with_separated_argument[]
Definition: gcc_cmdline.cpp:81
void parse_specs()
Parse GCC spec files https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html.
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
void parse_specs_line(const std::string &line)
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[]