// target-select.cc -- select a target for an object file

// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#include "gold.h"

#include <cstdio>
#include <cstring>

#include "elfcpp.h"
#include "options.h"
#include "parameters.h"
#include "target-select.h"

namespace
{

// The start of the list of target selectors.

gold::Target_selector* target_selectors;

} // End anonymous namespace.

namespace gold
{

// Class Set_target_once.

void
Set_target_once::do_run_once(void*)
{
  this->target_selector_->set_target();
}

// Construct a Target_selector, which means adding it to the linked
// list.  This runs at global constructor time, so we want it to be
// fast.

Target_selector::Target_selector(int machine, int size, bool is_big_endian,
				 const char* bfd_name, const char* emulation)
  : machine_(machine), size_(size), is_big_endian_(is_big_endian),
    bfd_name_(bfd_name), emulation_(emulation), instantiated_target_(NULL),
    set_target_once_(this)
{
  this->next_ = target_selectors;
  target_selectors = this;
}

// Instantiate the target and return it.  Use SET_TARGET_ONCE_ to
// avoid instantiating two instances of the same target.

Target*
Target_selector::instantiate_target()
{
  this->set_target_once_.run_once(NULL);
  return this->instantiated_target_;
}

// Instantiate the target.  This is called at most once.

void
Target_selector::set_target()
{
  gold_assert(this->instantiated_target_ == NULL);
  this->instantiated_target_ = this->do_instantiate_target();
}

// If we instantiated TARGET, return the corresponding BFD name.

const char*
Target_selector::do_target_bfd_name(const Target* target)
{
  if (!this->is_our_target(target))
    return NULL;
  const char* my_bfd_name = this->bfd_name();
  gold_assert(my_bfd_name != NULL);
  return my_bfd_name;
}

// Find the target for an ELF file.

Target*
select_target(int machine, int size, bool is_big_endian, int osabi,
	      int abiversion)
{
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    {
      int pmach = p->machine();
      if ((pmach == machine || pmach == elfcpp::EM_NONE)
	  && p->get_size() == size
	  && (p->is_big_endian() ? is_big_endian : !is_big_endian))
	{
	  Target* ret = p->recognize(machine, osabi, abiversion);
	  if (ret != NULL)
	    return ret;
	}
    }
  return NULL;
}

// Find a target using a BFD name.  This is used to support the
// --oformat option.

Target*
select_target_by_bfd_name(const char* name)
{
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    {
      const char* pname = p->bfd_name();
      if (pname == NULL || strcmp(pname, name) == 0)
	{
	  Target* ret = p->recognize_by_bfd_name(name);
	  if (ret != NULL)
	    return ret;
	}
    }
  return NULL;
}

// Find a target using a GNU linker emulation.  This is used to
// support the -m option.

Target*
select_target_by_emulation(const char* name)
{
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    {
      const char* pname = p->emulation();
      if (pname == NULL || strcmp(pname, name) == 0)
	{
	  Target* ret = p->recognize_by_emulation(name);
	  if (ret != NULL)
	    return ret;
	}
    }
  return NULL;
}

// Push all the supported BFD names onto a vector.

void
supported_target_names(std::vector<const char*>* names)
{
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    p->supported_bfd_names(names);
}

// Push all the supported emulations onto a vector.

void
supported_emulation_names(std::vector<const char*>* names)
{
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    p->supported_emulations(names);
}

// Implement the --print-output-format option.

void
print_output_format()
{
  if (!parameters->target_valid())
    {
      // This case arises when --print-output-format is used with no
      // input files.  We need to come up with the right string to
      // print based on the other options.  If the user specified the
      // format using a --oformat option, use that.  That saves each
      // target from having to remember the name that was used to
      // select it.  In other cases, we will just have to ask the
      // target.
      if (parameters->options().user_set_oformat())
	{
	  const char* bfd_name = parameters->options().oformat();
	  Target* target = select_target_by_bfd_name(bfd_name);
	  if (target != NULL)
	    printf("%s\n", bfd_name);
	  else
	    gold_error(_("unrecognized output format %s"), bfd_name);
	  return;
	}

      parameters_force_valid_target();
    }

  const Target* target = &parameters->target();
  for (Target_selector* p = target_selectors; p != NULL; p = p->next())
    {
      const char* bfd_name = p->target_bfd_name(target);
      if (bfd_name != NULL)
	{
	  printf("%s\n", bfd_name);
	  return;
	}
    }

  gold_unreachable();
}

} // End namespace gold.
