/* This file is is generated by a shell script.  DO NOT EDIT! */

/* emulate the original gld for the given i386elks
   Copyright (C) 1991-2022 Free Software Foundation, Inc.
   Written by Steve Chamberlain steve@cygnus.com

   This file is part of the GNU Binutils.

   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.  */

#define TARGET_IS_i386elks

#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "ctf-api.h"

#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"

#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"

#include "getopt.h"

#define OPTION_STACK		301
#define OPTION_HEAP		(OPTION_STACK + 1)
#define OPTION_CHMEM		(OPTION_HEAP + 1)
#define OPTION_TOTAL_DATA	(OPTION_CHMEM + 1)

static bfd_vma stack_size = 0, heap_size = 0, chmem = 0, total_data_size = 0;

static void
gldi386elks_add_options (int ns ATTRIBUTE_UNUSED,
				  char **shortopts ATTRIBUTE_UNUSED,
 				  int nl, struct option **longopts,
				  int nrl ATTRIBUTE_UNUSED,
				  struct option **really_longopts
						  ATTRIBUTE_UNUSED)
{
  static const struct option xtra_long[] =
  {
    { "stack", required_argument, NULL, OPTION_STACK },
    { "heap", required_argument, NULL, OPTION_HEAP },
    { "chmem", required_argument, NULL, OPTION_CHMEM },
    { "total-data", required_argument, NULL, OPTION_TOTAL_DATA },
    { NULL, no_argument, NULL, 0 }
  };
  *longopts = (struct option *)
    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
  memcpy (*longopts + nl, xtra_long, sizeof (xtra_long));
}

static bool
gldi386elks_handle_option (int optc)
{
  char *end;
  bfd_vma value;

  switch (optc)
    {
    default:
      return false;

    case OPTION_STACK:
      if (chmem || total_data_size)
	{
	  einfo (_("%F%P: cannot specify `--chmem'/`--total-data' "
		   "together with `--stack'"));
	  break;
	}
      value = strtoul (optarg, &end, 0);
      if (*end)
	einfo (_("%F%P: invalid stack size `%s'\n"), optarg);
      else
	stack_size = value;
      break;

    case OPTION_HEAP:
      if (chmem || total_data_size)
	{
	  einfo (_("%F%P: cannot specify `--chmem'/`--total-data' "
		   "together with `--heap'"));
	  break;
	}
      value = strtoul (optarg, &end, 0);
      if (*end)
	einfo (_("%F%P: invalid heap size `%s'\n"), optarg);
      else if (! value)
	{
	  einfo (_("%P: warning: using 1 instead of 0 for heap size\n"));
	  heap_size = 1;
	}
      else
	heap_size = value;
      break;

    case OPTION_CHMEM:
      if (total_data_size || stack_size || heap_size)
	{
	  einfo (_("%F%P: cannot specify `--chmem' "
		   "together with `--total-data'/`--stack'/`--heap'"));
	  break;
	}
      value = strtoul (optarg, &end, 0);
      if (*end)
	einfo (_("%F%P: invalid stack + heap size `%s'\n"), optarg);
      else
	chmem = value;
      break;

    case OPTION_TOTAL_DATA:
      if (chmem || stack_size || heap_size)
	{
	  einfo (_("%F%P: cannot specify `--total-data' "
		   "together with `--chmem'/`--stack'/`--heap'"));
	  break;
	}
      value = strtoul (optarg, &end, 0);
      if (*end)
	einfo (_("%F%P: invalid data segment size `%s'\n"), optarg);
      else
	total_data_size = value;
      break;
    }

  return true;
}

static void
gldi386elks_list_options (FILE *file)
{
  fprintf (file, _("  --stack <size>              "
		   "Set size of the initial stack\n"));
  fprintf (file, _("  --heap <size>               "
		   "Set maximum heap size\n"));
  fprintf (file, _("  --chmem <size>              "
		   "Set maximum stack + heap + env size\n"));
  fprintf (file, _("  --total-data <size>         "
		   "Set maximum data segment size\n"));
}

extern void elks_set_heap_and_minstack (bfd *, bfd_vma, bfd_vma, bfd_vma,
					bfd_vma);

static void
gldi386elks_after_allocation (void)
{
  bfd *abfd = link_info.output_bfd;

  if (strstr (bfd_get_target (abfd), "elks"))
    elks_set_heap_and_minstack (abfd, stack_size, heap_size, chmem,
				total_data_size);
}

static void
gldi386elks_before_parse (void)
{
#ifndef TARGET_			/* I.e., if not generic.  */
  ldfile_set_output_arch ("i386", bfd_arch_unknown);
#endif /* not TARGET_ */
}


static char *
gldi386elks_get_script (int *isfile)
{
  *isfile = 1;

  if (bfd_link_relocatable (&link_info) && config.build_constructors)
    return "ldscripts/i386elks.xu";
  else if (bfd_link_relocatable (&link_info))
    return "ldscripts/i386elks.xr";
  else if (!config.text_read_only)
    return "ldscripts/i386elks.xbn";
  else if (!config.magic_demand_paged)
    return "ldscripts/i386elks.xn";
  else
    return "ldscripts/i386elks.x";
}

struct ld_emulation_xfer_struct ld_i386elks_emulation =
{
  gldi386elks_before_parse,
  syslib_default,
  hll_default,
  after_parse_default,
  NULL,
  after_open_default,
  after_check_relocs_default,
  before_place_orphans_default,
  gldi386elks_after_allocation,
  set_output_arch_default,
  ldemul_default_target,
  before_allocation_default,
  gldi386elks_get_script,
  "i386elks",
  "elks",
  finish_default,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  gldi386elks_add_options,
  gldi386elks_handle_option,
  NULL,
  gldi386elks_list_options,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};
