OSDN Git Service

Initial CVS checkin of gold
[pf3gnuchains/pf3gnuchains3x.git] / gold / options.cc
1 // options.c -- handle command line options for gold
2
3 #include <iostream>
4
5 #include "gold.h"
6 #include "options.h"
7
8 // The information we keep for a single command line option.
9
10 struct gold::options::One_option
11 {
12   // The single character option name, or '\0' if this is only a long
13   // option.
14   char short_option;
15
16   // The long option name, or NULL if this is only a short option.
17   const char* long_option;
18
19   // Description of the option for --help output, or NULL if there is none.
20   const char* doc;
21
22   // How to print the option name in --help output, or NULL to use the
23   // default.
24   const char* help_output;
25
26   // Long option dash control.  This is ignored if long_option is
27   // NULL.
28   enum
29     {
30       // Long option normally takes one dash; two dashes are also
31       // accepted.
32       ONE_DASH,
33       // Long option normally takes two dashes; one dash is also
34       // accepted.
35       TWO_DASHES,
36       // Long option always takes two dashes.
37       EXACTLY_TWO_DASHES
38     } dash;
39
40   // Function for special handling, or NULL.  Returns the number of
41   // arguments to skip.  This will normally be at least 1, but it may
42   // be 0 if this function changes *argv.  ARG points to the location
43   // in *ARGV where the option starts, which may be helpful for a
44   // short option.
45   int (*special)(int argc, char** argv, char *arg, gold::Command_line*);
46
47   // If this is a position independent option which does not take an
48   // argument, this is the member function to call to record it.
49   void (gold::General_options::*general_noarg)();
50
51   // If this is a position independent function which takes an
52   // argument, this is the member function to call to record it.
53   void (gold::General_options::*general_arg)(const char*);
54
55   // If this is a position dependent option which does not take an
56   // argument, this is the member function to call to record it.
57   void (gold::Position_dependent_options::*dependent_noarg)();
58
59   // If this is a position dependent option which takes an argument,
60   // this is the member function to record it.
61   void (gold::Position_dependent_options::*dependent_arg)(const char*);
62
63   // Return whether this option takes an argument.
64   bool
65   takes_argument() const
66   { return this->general_arg != NULL || this->dependent_arg != NULL; }
67 };
68
69 class gold::options::Command_line_options
70 {
71  public:
72   static const One_option options[];
73   static const int options_size;
74 };
75
76 namespace
77 {
78
79 // Report usage information for ld --help, and exit.
80
81 int
82 help(int, char**, char*, gold::Command_line*)
83 {
84   printf(_("Usage: %s [options] file...\nOptions:\n"), gold::program_name);
85
86   const int options_size = gold::options::Command_line_options::options_size;
87   const gold::options::One_option* options =
88     gold::options::Command_line_options::options;
89   for (int i = 0; i < options_size; ++i)
90     {
91       if (options[i].doc == NULL)
92         continue;
93
94       printf("  ");
95       int len = 2;
96       bool comma = false;
97
98       int j = i;
99       do
100         {
101           if (options[j].help_output != NULL)
102             {
103               if (comma)
104                 {
105                   printf(", ");
106                   len += 2;
107                 }
108               printf(options[j].help_output);
109               len += std::strlen(options[i].help_output);
110             }
111           else
112             {
113               if (options[j].short_option != '\0')
114                 {
115                   if (comma)
116                     {
117                       printf(", ");
118                       len += 2;
119                     }
120                   printf("-%c", options[j].short_option);
121                   len += 2;
122                 }
123
124               if (options[j].long_option != NULL)
125                 {
126                   if (comma)
127                     {
128                       printf(", ");
129                       len += 2;
130                     }
131                   if (options[j].dash == gold::options::One_option::ONE_DASH)
132                     {
133                       printf("-");
134                       ++len;
135                     }
136                   else
137                     {
138                       printf("--");
139                       len += 2;
140                     }
141                   printf("%s", options[j].long_option);
142                   len += std::strlen(options[j].long_option);
143                 }
144             }
145           ++j;
146         }
147       while (j < options_size && options[j].doc == NULL);
148
149       if (len > 30)
150         {
151           printf("\n");
152           len = 0;
153         }
154       for (; len < 30; ++len)
155         std::putchar(' ');
156
157       std::puts(options[i].doc);
158     }
159
160   gold::gold_exit(true);
161
162   return 0;
163 }
164
165 } // End empty namespace.
166
167 // Helper macros used to specify the options.  We could also do this
168 // using constructors, but then g++ would generate code to initialize
169 // the array.  We want the array to be initialized statically so that
170 // we get better startup time.
171
172 #define GENERAL_NOARG(short_option, long_option, doc, help, dash, func) \
173   { short_option, long_option, doc, help, gold::options::One_option::dash, \
174       NULL, func, NULL, NULL, NULL }
175 #define GENERAL_ARG(short_option, long_option, doc, help, dash, func)   \
176   { short_option, long_option, doc, help, gold::options::One_option::dash, \
177       NULL, NULL, func, NULL, NULL }
178 #define POSDEP_NOARG(short_option, long_option, doc, help, dash, func)  \
179   { short_option, long_option, doc, help, gold::options::One_option::dash, \
180       NULL,  NULL, NULL, func, NULL }
181 #define POSDEP_ARG(short_option, long_option, doc, help, dash, func)    \
182   { short_option, long_option, doc, help, gold::options::One_option::dash, \
183       NULL, NULL, NULL, NULL, func }
184 #define SPECIAL(short_option, long_option, doc, help, dash, func)       \
185   { short_option, long_option, doc, help, gold::options::One_option::dash, \
186       func, NULL, NULL, NULL, NULL }
187
188 // Here is the actual list of options which we accept.
189
190 const gold::options::One_option
191 gold::options::Command_line_options::options[] =
192 {
193   GENERAL_ARG('L', "library-path", N_("Add directory to search path"),
194               N_("-L DIR, --library-path DIR"), TWO_DASHES,
195               &gold::General_options::add_to_search_path),
196   GENERAL_NOARG('r', NULL, N_("Generate relocatable output"), NULL,
197                 ONE_DASH, &gold::General_options::set_relocatable),
198   GENERAL_NOARG('\0', "static", N_("Do not link against shared libraries"),
199                 NULL, ONE_DASH, &gold::General_options::set_static),
200   SPECIAL('\0', "help", N_("Report usage information"), NULL,
201           TWO_DASHES, &help)
202 };
203
204 const int gold::options::Command_line_options::options_size =
205   sizeof (options) / sizeof (options[0]);
206
207 // The default values for the general options.
208
209 gold::General_options::General_options()
210   : is_relocatable_(false)
211 {
212 }
213
214 // The default values for the position dependent options.
215
216 gold::Position_dependent_options::Position_dependent_options()
217   : do_static_search_(false)
218 {
219 }
220
221 // Construct a Command_line.
222
223 gold::Command_line::Command_line()
224 {
225 }
226
227 // Process the command line options.
228
229 void
230 gold::Command_line::process(int argc, char** argv)
231 {
232   const int options_size = gold::options::Command_line_options::options_size;
233   const gold::options::One_option* options =
234     gold::options::Command_line_options::options;
235   bool no_more_options = false;
236   int i = 0;
237   while (i < argc)
238     {
239       if (argv[i][0] != '-' || no_more_options)
240         {
241           this->inputs_.push_back(Input_argument(argv[i],
242                                                  this->position_options_));
243           ++i;
244           continue;
245         }
246
247       // Option starting with '-'.
248       int dashes = 1;
249       if (argv[i][1] == '-')
250         {
251           dashes = 2;
252           if (argv[i][2] == '\0')
253             {
254               no_more_options = true;
255               continue;
256             }
257         }
258
259       // Look for a long option match.
260       char* opt = argv[i] + dashes;
261       char first = opt[0];
262       int skiparg = 0;
263       char* arg = strchr(opt, '=');
264       if (arg != NULL)
265         *arg = '\0';
266       else if (i + 1 < argc)
267         {
268           arg = argv[i + 1];
269           skiparg = 1;
270         }
271
272       int j;
273       for (j = 0; j < options_size; ++j)
274         {
275           if (options[j].long_option != NULL
276               && (dashes == 2
277                   || (options[j].dash
278                       != gold::options::One_option::EXACTLY_TWO_DASHES))
279               && first == options[j].long_option[0]
280               && strcmp(opt, options[j].long_option) == 0)
281             {
282               if (options[j].special)
283                 i += options[j].special(argc - 1, argv + i, opt, this);
284               else
285                 {
286                   if (!options[j].takes_argument())
287                     {
288                       arg = NULL;
289                       skiparg = 0;
290                     }
291                   else
292                     {
293                       if (arg == NULL)
294                         this->usage(_("missing argument"), argv[i]);
295                     }
296                   this->apply_option(options[j], arg);
297                   i += skiparg + 1;
298                 }
299               break;
300             }
301         }
302       if (j < options_size)
303         continue;
304
305       // If we saw two dashes, we need to see a long option.
306       if (dashes == 2)
307         this->usage(_("unknown option"), argv[i]);
308
309       // Look for a short option match.  There may be more than one
310       // short option in a given argument.
311       bool done = false;
312       char* s = argv[i] + 1;
313       ++i;
314       while (*s != '\0' && !done)
315         {
316           char opt = *s;
317           int j;
318           for (j = 0; j < options_size; ++j)
319             {
320               if (options[j].short_option == opt)
321                 {
322                   if (options[j].special)
323                     {
324                       // Undo the argument skip done above.
325                       --i;
326                       i += options[j].special(argc - i, argv + i, s, this);
327                       done = true;
328                     }
329                   else
330                     {
331                       arg = NULL;
332                       if (options[j].takes_argument())
333                         {
334                           if (s[1] != '\0')
335                             {
336                               arg = s + 1;
337                               done = true;
338                             }
339                           else if (i < argc)
340                             {
341                               arg = argv[i];
342                               ++i;
343                             }
344                           else
345                             this->usage(_("missing argument"), opt);
346                         }
347                       this->apply_option(options[j], arg);
348                     }
349                   break;
350                 }
351             }
352
353           if (j >= options_size)
354             this->usage(_("unknown option"), *s);
355
356           ++s;
357         }
358     }
359 }
360
361 // Apply a command line option.
362
363 void
364 gold::Command_line::apply_option(const gold::options::One_option& opt,
365                                  const char* arg)
366 {
367   if (arg == NULL)
368     {
369       if (opt.general_noarg)
370         (this->options_.*(opt.general_noarg))();
371       else if (opt.dependent_noarg)
372         (this->position_options_.*(opt.dependent_noarg))();
373       else
374         gold::gold_unreachable();
375     }
376   else
377     {
378       if (opt.general_arg)
379         (this->options_.*(opt.general_arg))(arg);
380       else if (opt.dependent_arg)
381         (this->position_options_.*(opt.dependent_arg))(arg);
382       else
383         gold::gold_unreachable();
384     }
385 }
386
387 // Report a usage error.  */
388
389 void
390 gold::Command_line::usage()
391 {
392   fprintf(stderr,
393           _("%s: use the --help option for usage information\n"),
394           gold::program_name);
395   gold::gold_exit(false);
396 }
397
398 void
399 gold::Command_line::usage(const char* msg, const char *opt)
400 {
401   fprintf(stderr,
402           _("%s: %s: %s\n"),
403           gold::program_name, opt, msg);
404   this->usage();
405 }
406
407 void
408 gold::Command_line::usage(const char* msg, char opt)
409 {
410   fprintf(stderr,
411           _("%s: -%c: %s\n"),
412           gold::program_name, opt, msg);
413   this->usage();
414 }