// options.h -- handle command line options for gold -*- C++ -*- // Command_line // Holds everything we get from the command line. // General_options (from Command_line::options()) // Options which are not position dependent. // Input_argument (from Command_line::inputs()) // The list of input files, including -l options. // Position_dependent_options (from Input_argument::options()) // Position dependent options which apply to this argument. #ifndef GOLD_OPTIONS_H #define GOLD_OPTIONS_H #include #include #include namespace gold { class Command_line; class Input_file_group; namespace options { class Command_line_options; struct One_option; } // End namespace gold::options. // The position independent options which apply to the whole link. // There are a lot of them. class General_options { public: General_options(); // -I: dynamic linker name. const char* dynamic_linker() const { return this->dynamic_linker_; } // -L: Library search path. typedef std::list Dir_list; const Dir_list& search_path() const { return this->search_path_; } // -o: Output file name. const char* output_file_name() const { return this->output_file_name_; } // -r: Whether we are doing a relocatable link. bool is_relocatable() const { return this->is_relocatable_; } // --shared: Whether generating a shared object. bool is_shared() const { return this->is_shared_; } // --static: Whether doing a static link. bool is_static() const { return this->is_static_; } private: // Don't copy this structure. General_options(const General_options&); General_options& operator=(const General_options&); friend class Command_line; friend class options::Command_line_options; void set_dynamic_linker(const char* arg) { this->dynamic_linker_ = arg; } void add_to_search_path(const char* arg) { this->search_path_.push_back(arg); } void set_output_file_name(const char* arg) { this->output_file_name_ = arg; } void set_relocatable() { this->is_relocatable_ = true; } void set_shared() { this->is_shared_ = true; } void set_static() { this->is_static_ = true; } void ignore(const char*) { } const char* dynamic_linker_; Dir_list search_path_; const char* output_file_name_; bool is_relocatable_; bool is_shared_; bool is_static_; }; // The current state of the position dependent options. class Position_dependent_options { public: Position_dependent_options(); // -Bstatic: Whether we are searching for a static archive rather // than a shared object. bool do_static_search() const { return this->do_static_search_; } // --as-needed: Whether to add a DT_NEEDED argument only if the // dynamic object is used. bool as_needed() const { return this->as_needed_; } void set_static_search() { this->do_static_search_ = true; } void set_dynamic_search() { this->do_static_search_ = false; } void set_as_needed() { this->as_needed_ = true; } void clear_as_needed() { this->as_needed_ = false; } private: bool do_static_search_; bool as_needed_; }; // A single file or library argument from the command line. class Input_file_argument { public: Input_file_argument() : name_(), is_lib_(false), options_() { } Input_file_argument(const char* name, bool is_lib, const Position_dependent_options& options) : name_(name), is_lib_(is_lib), options_(options) { } const char* name() const { return this->name_.c_str(); } const Position_dependent_options& options() const { return this->options_; } bool is_lib() const { return this->is_lib_; } private: // We use std::string, not const char*, here for convenience when // using script files, so that we do not have to preserve the string // in that case. std::string name_; bool is_lib_; Position_dependent_options options_; }; // A file or library, or a group, from the command line. class Input_argument { public: // Create a file or library argument. explicit Input_argument(Input_file_argument file) : is_file_(true), file_(file), group_(NULL) { } // Create a group argument. explicit Input_argument(Input_file_group* group) : is_file_(false), group_(group) { } // Return whether this is a file. bool is_file() const { return this->is_file_; } // Return whether this is a group. bool is_group() const { return !this->is_file_; } // Return the information about the file. const Input_file_argument& file() const { gold_assert(this->is_file_); return this->file_; } // Return the information about the group. const Input_file_group* group() const { gold_assert(!this->is_file_); return this->group_; } Input_file_group* group() { gold_assert(!this->is_file_); return this->group_; } private: bool is_file_; Input_file_argument file_; Input_file_group* group_; }; // A group from the command line. This is a set of arguments within // --start-group ... --end-group. class Input_file_group { public: typedef std::vector Files; typedef Files::const_iterator const_iterator; Input_file_group() : files_() { } // Add a file to the end of the group. void add_file(const Input_file_argument& arg) { this->files_.push_back(Input_argument(arg)); } // Iterators to iterate over the group contents. const_iterator begin() const { return this->files_.begin(); } const_iterator end() const { return this->files_.end(); } private: Files files_; }; // A list of files from the command line or a script. class Input_arguments { public: typedef std::vector Input_argument_list; typedef Input_argument_list::const_iterator const_iterator; Input_arguments() : input_argument_list_(), in_group_(false) { } // Add a file. void add_file(const Input_file_argument& arg); // Start a group (the --start-group option). void start_group(); // End a group (the --end-group option). void end_group(); // Return whether we are currently in a group. bool in_group() const { return this->in_group_; } // Iterators to iterate over the list of input files. const_iterator begin() const { return this->input_argument_list_.begin(); } const_iterator end() const { return this->input_argument_list_.end(); } // Return whether the list is empty. bool empty() const { return this->input_argument_list_.empty(); } private: Input_argument_list input_argument_list_; bool in_group_; }; // All the information read from the command line. class Command_line { public: typedef Input_arguments::const_iterator const_iterator; Command_line(); // Process the command line options. This will exit with an // appropriate error message if an unrecognized option is seen. void process(int argc, char** argv); // Handle a -l option. int process_l_option(int, char**, char*); // Handle a --start-group option. void start_group(const char* arg); // Handle a --end-group option. void end_group(const char* arg); // Get the general options. const General_options& options() const { return this->options_; } // Iterators to iterate over the list of input files. const_iterator begin() const { return this->inputs_.begin(); } const_iterator end() const { return this->inputs_.end(); } private: Command_line(const Command_line&); Command_line& operator=(const Command_line&); // Report usage error. void usage() ATTRIBUTE_NORETURN; void usage(const char* msg, const char* opt) ATTRIBUTE_NORETURN; void usage(const char* msg, char opt) ATTRIBUTE_NORETURN; // Apply a command line option. void apply_option(const gold::options::One_option&, const char*); // Add a file. void add_file(const char* name, bool is_lib); General_options options_; Position_dependent_options position_options_; Input_arguments inputs_; }; } // End namespace gold. #endif // !defined(GOLD_OPTIONS_H)