/* Configuration for an i386 running emx (target). */

/* We do want to add an underscore to the front of each user symbol. */
#define YES_UNDERSCORES

/* Use atexit() in libgcc */
#define HAVE_ATEXIT

/* The system headers are C++-aware. */
#define NO_IMPLICIT_EXTERN_C

/* Enable #pragma pack. */
#define HANDLE_SYSV_PRAGMA

#define ASM_STABS_OP "\t.stabs"
#define ASM_STABN_OP "\t.stabn"

#include "i386/gstabs.h" /* GAS stabs */
#include "aoutos.h"	 /* constructors/destructors/garbage collectors */

/* This macros will stick a label to exception table for current file,
 * and also will put it in a 'ctor/dtor' - like list (using .stabs - this uses
 * same technique used in aoutos.h) which ld will collect into a single table
 * and then __ctordtorInit will use this table to make a call to
 * __register_frame_table
 */
#define EH_FRAME_SECTION()						       \
  data_section ();							       \
  fprintf (asm_out_file, "%s \"___eh_frame__\",24,0,0,___FRAME_BEGIN__\n", ASM_STABS_OP);

/* Put exception tables into .data section */
#define EXCEPTION_SECTION()						       \
  data_section()

/* We want DWARF2 frame unwind info for exception handling */
#define DWARF2_UNWIND_INFO 1

/* Terminate DWARF frame unwind info with a closing zero */
#define DWARF2_FRAMEINFO_NULL_TERMINATED 1

/* Generate stack probes for allocations bigger than */
#define CHECK_STACK_LIMIT 0x1000

/* wchar_t is unsigned short. */
#define WCHAR_TYPE              "short unsigned int"
#define WCHAR_TYPE_SIZE         16

/* Bitfields may cross alignment boundaries. */
#undef PCC_BITFIELD_TYPE_MATTERS
#define PCC_BITFIELD_TYPE_MATTERS 0

/* By default, return short structures in registers. */
#define DEFAULT_PCC_STRUCT_RETURN 0

/* Don't continue symbols.  I think all relevant tools can handle
   symbols of arbitrary length.  GAS does not correctly handle
   continued symbols: it sometimes emits another symbol before the
   continuation. */
#define DBX_CONTIN_LENGTH 0

/* Paths. */
#undef STANDARD_EXEC_PREFIX
#define STANDARD_EXEC_PREFIX       "/emx/bin/"
#undef STANDARD_STARTFILE_PREFIX
#define STANDARD_STARTFILE_PREFIX  "/emx/lib/"

#define INCLUDE_DEFAULTS						       \
{									       \
  {"/emx/include", 0, 0, 1},						       \
  {"/emx/include/sys", 0, 0, 1},					       \
  {"/emx/include/cpp", "G++", 1, 1},					       \
  {"/toolkit/h", 0, 0, 1},						       \
  {0, 0, 0}								       \
}

/* Predefine symbols `__32BIT__', `__EMX__', and `i386'. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-D__32BIT__ -D__EMX__ -Di386 "			       \
  "-Asystem(unix) -Asystem(emx) -Acpu(i386) -Amachine(i386)"

/* Predefine the symbol `__MT__' for multi-threaded programs (-Zmt) */
#undef CPP_SPEC
#define CPP_SPEC							       \
  "%{posix:-D_POSIX_SOURCE} "						       \
  "%{Zmt:-D__MT__} "							       \
  "%{Zomf} %{Zomf:-D__OS2__}"						       \
  "%{pg:-D__GPROF__} "							       \
  "%{mepilogue:-D__EPILOGUE__} "					       \
  "%{mprobe:-D__STACK_PROBE__} "					       \
  "%{mstack-arg-probe:-D__STACK_PROBE__} "

/* Pass -Zomf and -s (as -Zstrip) to the assembler. */
#define ASM_SPEC "%{Zomf} %{s:-Zstrip}"

#define LINK_SPEC							       \
  "%{Zexe} %{Zstack*} %{Zmap*} %{Zomf:%{Zdll}} "			       \
  "%{!o*:-o %b%{Zdll:.dll}%{!Zdll:%{!Zexe:.exe}}} "			       \
  "%{static:%{Zcrtdll*:%e-static and -Zcrtdll are incompatible}}"	       \
  "%{Zdll:%{Zexe:%e-Zdll and -Zexe are incompatible}}"			       \
  "%{Zso:%{!Zsys:%e-Zso requires -Zsys}}"				       \
  "%{Zso:%{!Zdll:%e-Zso requires -Zdll}}"				       \
  "%{Zno-rte:%{!Zdll:%e-Zno-rte requires -Zdll}}"			       \
  "%{Zno-rte:%{!Zomf:%e-Zno-rte requires -Zomf}}"			       \
  "%{Zno-rte:%{Zsys:%e-Zno-rte and -Zsys are incompatible}}"		       \
  "%{Zno-rte:%{Zso:%e-Zno-rte and -Zso are incompatible}}"		       \
  "%{Zno-rte:%{Zcrtdll*:%e-Zcrtdll and -Zno-rte are incompatible}}"	       \
  "%{Zno-rte:%{Zmt:%e-Zmt and -Zno-rte are incompatible}}"		       \
  "%{Zsys:%{Zcrtdll*:%e-Zcrtdll and -Zsys are incompatible}}"		       \
  "%{Zsys:%{!Zomf:%e-Zsys requires -Zomf}}"				       \
  "%{Zsys:%{Zbsd-signals:%e-Zbsd-signals and -Zsys are incompatible}}"	       \
  "%{Zsys:%{Zsysv-signals:%e-Zsysv-signals and -Zsys are incompatible}}"       \
  "%{Zbsd-signals:%{Zsysv-signals:%e-Zbsd-signals and -Zsysv-signals are incompatible}}" \
  "%{Zsmall-conv:%{Zcrtdll*:%e-Zsmall-conv and -Zcrtdll are incompatible}}"

#ifndef USE_CXX_RUNTIME
#define LIBGCC_SPEC "-lgcc%{pg:_p}%{!pg:%{Zcrtdll*:" LIBGCC_VER "}}"
#else
#define LIBGCC_SPEC "-l"						       \
  "%{!pg:%{!Zcrtdll*:%{!fno-exceptions:gpp}}}"				       \
  "%{!pg:%{!Zcrtdll*:%{fno-exceptions:gcc}}}"				       \
  "%{!pg:%{Zcrtdll*:gcc" LIBGCC_VER "}}"				       \
  "%{pg:%{fno-exceptions:gcc_p}}"					       \
  "%{pg:%{!fno-exceptions:gpp_p}}"
#endif /* USE_CXX_RUNTIME */

/* "%{g*:-lg} " -- removed -- A.Z. */
#define LIB_SPEC							       \
  "%{p:-lc_p}%{pg:-lc_p} -lc "						       \
  "%{Zdll:%{Zso:-lc_dllso}%{Zno-rte:-lc_dllnrt}"			       \
         "%{!Zso:%{!Zno-rte:-lc_dllrt}}}"				       \
  "%{!Zdll:-lc_app%{pg:_p}} %{p:-lc_p}%{pg:-lc_p} -lc"

#define STARTFILE_SPEC							       \
  "%{Zdll:dll0%O%s}"							       \
  "%{!Zdll:%{pg:gcrt0%O%s}"						       \
         "%{!pg:%{pn:gcrt0%O%s}%{!pn:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"	       \
         " %{Zsysv-signals:sigsysv%O%s} %{Zbsd-signals:sigbsd%O%s}"	       \
         " %{Zbin-files:binmode%O%s}%{Zsmall-conv:smallcnv%O%s}}"

#define LINK_COMMAND_SPEC						       \
"%{!fsyntax-only: "							       \
"%{!c:%{!M:%{!MM:%{!E:%{!S:%{!Zomf:ld}%{Zomf:emxomfld} "		       \
			"%l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} "	       \
			"%{r} %{s} %{t} %{u*} %{x} %{z} %{Z} "		       \
			"%{!A:%{!nostdlib:%{!nostartfiles:%S}}} "	       \
			"%{static:} %{L*} %D %{T*} %o "			       \
			"%{!nostdlib:%{!nodefaultlibs:"			       \
			   "-lc_alias %G "				       \
			   "%{Zcrtdll=*:-lc_static -l%* -los2%{pg:_p} -lemx2}" \
			   "%{!Zcrtdll*:%L %G "			       \
			      "%{Zno-rte:-los2%{pg:_p}} "		       \
			      "%{!Zno-rte:%{Zsys:-lsys -los2} "		       \
			         "%{!Zsys:-lemx -los2%{pg:_p} -lemx2} "	       \
			       "}"					       \
			    "}"						       \
			    "%{Zomf:-lend}}"				       \
			 "}"						       \
			"%{!A:%{!nostdlib:%{!nostartfiles:%E}}} "	       \
                        "}}}}}}"


/******************************************************************************
 *                       - S - W - I - T - C - H - E - S -
 ******************************************************************************/

/* The -Zstack option takes an argument. */
#define WORD_SWITCH_TAKES_ARG(STR) (DEFAULT_WORD_SWITCH_TAKES_ARG (STR)	       \
                                    || !strcmp (STR, "Zstack"))

/* Define an additional switch -m(no-)probe for backward compatibility */
/* Also define the -m(no-)epilogue switch */

#define MASK_EPILOGUE		0x40000000      /* Use FUNCTION_EPILOGUE */

#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES						       \
    { "probe", MASK_STACK_PROBE},					       \
    { "no-probe", -MASK_STACK_PROBE},					       \
    { "epilogue", MASK_EPILOGUE},					       \
    { "no-epilogue", -MASK_EPILOGUE},

/* Use FUNCTION_EPILOGUE */
#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE)

/* Add a __POST$xxx label before epilogue if -mepilogue specified */
#define FUNCTION_BEGIN_EPILOGUE(FILE)					       \
 if (TARGET_EPILOGUE)							       \
 {									       \
  char *func_label = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));\
  char *lbl = alloca (strlen (func_label) + 8);				       \
  strcpy (lbl, "__POST$");						       \
  strcat (lbl, func_label);						       \
  ASM_OUTPUT_LABEL (asm_out_file, lbl);					       \
 }

/* Output assembler code to FILE to increment profiler label # LABELNO
   for profiling a function entry.  */

#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABELNO)				       \
{									       \
  fprintf (FILE, "\tcall __mcount\n");					       \
}

/* Calling conventions */

#undef VALID_MACHINE_TYPE_ATTRIBUTE
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS)	       \
  (emx_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))

#undef RETURN_POPS_ARGS
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE)				       \
  (emx_return_pops_args (FUNDECL, FUNTYPE, SIZE))

/* Dynamically compute the path prefix for tools */
#define MD_DYNAMIC_EXEC_PREFIX						       \
  char emx_exec_prefix_buffer [260 + 1];				       \
  if (_execname (emx_exec_prefix_buffer, sizeof (emx_exec_prefix_buffer)) == 0)\
  {									       \
    char *name = _getname (emx_exec_prefix_buffer);			       \
    if (name != emx_exec_prefix_buffer)					       \
      *name = 0;							       \
    add_prefix (&exec_prefixes, emx_exec_prefix_buffer, "GCC", 0, 0, NULL_PTR);\
    add_prefix (&startfile_prefixes, emx_exec_prefix_buffer, "GCC", 0, 0, NULL_PTR);\
  }

/* IBM's linker LINK386 does not understand filenames with '+' (shame!) */
#define CPLUS_LIBRARY "-lstdcpp"

/* emxomf does not understand stabs+, so for frontends we have to
   switch to standard stabs if -Zomf is used */
#define PREPROCESS_ARGV_GCC						\
  _emxload_env ("GCCLOAD");						\
  _envargs (&argc, &argv, "GCCOPT");					\
  _response (&argc, &argv);						\
  _wildcard (&argc, &argv);						\
  /* pipe() is supported under OS/2 and by RSX.  */			\
  pipes_supported = _osmode != DOS_MODE || (_emx_env & 0x1000);		\
  {									\
    int i, g_found = 0, z_omf_found = 0;				\
    for (i = 1; i < argc; i++)						\
      if (!strcmp (argv [i], "-Zomf"))					\
        z_omf_found = i;						\
      else if (!strncmp (argv [i], "-g", 2)				\
            && ((argv [i][2] == 0) || isdigit (argv [i][2])))		\
        g_found = i;							\
    if (g_found && z_omf_found)						\
    {									\
      char *temp = (char *)malloc (strlen (argv [g_found - 1]) + 5 + 1);\
      strcpy (temp, "-gstabs");						\
      strcat (temp, &argv [g_found][2]);				\
      argv [g_found] = temp;						\
    }									\
  }

/* The following will be defined only when compiling libgcc2
 * to avoid including large .h files when they are not needed.
 * Including them is neccessary to avoid 'implicit declatation'
 * warnings, and also for __write.
 */
#ifdef IN_LIBGCC2
/* define "write" and some other external functions for libgcc */
#define write __write
//extern int __write (int handle, const void *buf, int nbyte);

#include <malloc.h>
#include <time.h>
#include <strings.h>

extern void __ctordtorInit (void);
extern void __ctordtorTerm (void);

/* Invoke static object constructors/destructors */
/* Also register/deregister frame unwind information */
#define DO_GLOBAL_CTORS_BODY __ctordtorInit ()
#define DO_GLOBAL_DTORS_BODY __ctordtorTerm ()

#endif

/* Command-line help facility support -
   avoid using termcap since its not too reliable on OS/2 */
#ifdef IN_CLH

static int emx_monochrome = 0;	/* 1 for monochrome output */
static int emx_textattr = 0;	/* current text attributes */

static int
emx_getwidth ()
{
  int wh[2];
  char *term;

  term = getenv ("CLH_TERM");
  if (!term)
    term = getenv ("TERM");
  if (term && stricmp (term, "mono") == 0)
    emx_monochrome = 1;

  _scrsize (wh);
  return (wh[0]);
}

static char *ansi_seq [] =
{
/*  color	monochrome */
  "\033[0;36m",	"\033[0m",	/* */
  "\033[1;36m",	"\033[1m",	/* header */
  "\033[1;37m",	"\033[7m",	/* option */
  "\033[1;37m",	"\033[7m",	/* option + header */
  "\033[1;37m",	"\033[1m",	/* bold */
  "\033[1;37m",	"\033[1m",	/* bold + header */
  "\033[1;37m",	"\033[7m",	/* bold + option */
  "\033[1;37m",	"\033[7m",	/* bold + option + header */
  "\033[1;32m",	"\033[1m",	/* italic */
  "\033[1;32m",	"\033[1m",	/* italic + header */
  "\033[1;32m",	"\033[1m",	/* italic + option */
  "\033[1;32m",	"\033[1m",	/* italic + option + header */
  "\033[1;32m",	"\033[1m",	/* italic + bold */
  "\033[1;32m",	"\033[1m",	/* italic + bold + header */
  "\033[1;32m",	"\033[1m",	/* italic + bold + option */
  "\033[1;32m",	"\033[1m",	/* italic + bold + option + header */
  "\033[1;33m",	"\033[4m",	/* underline */
  "\033[1;33m",	"\033[4m",	/* underline + header */
  "\033[1;37m",	"\033[4m",	/* underline + option */
  "\033[1;37m",	"\033[4m",	/* underline + option + header */
  "\033[1;37m",	"\033[4m",	/* underline + bold */
  "\033[1;37m",	"\033[4m",	/* underline + bold + header */
  "\033[1;37m",	"\033[4m",	/* underline + bold + option */
  "\033[1;37m",	"\033[4m",	/* underline + bold + option + header */
  "\033[1;33m",	"\033[4m",	/* underline + italic */
  "\033[1;37m",	"\033[4m",	/* underline + italic + header */
  "\033[1;37m",	"\033[4m",	/* underline + italic + option */
  "\033[1;37m",	"\033[4m",	/* underline + italic + option + header */
  "\033[1;37m",	"\033[4m",	/* underline + italic + bold */
  "\033[1;37m",	"\033[4m",	/* underline + italic + bold + header */
  "\033[1;37m",	"\033[4m",	/* underline + italic + bold + option */
  "\033[1;37m",	"\033[4m",	/* underline + italic + bold + option + header */
};

#define TERM_OUT(s) \
  write (1, s, strlen (s));

static int
emx_setattr (flags, flagmask)
{
  emx_textattr = (emx_textattr & ~flagmask) | flags;
  TERM_OUT (ansi_seq [emx_textattr * 2 + emx_monochrome]);
  return (0);
}

#define CLH_GET_WIDTH			emx_getwidth ()
#define CLH_GET_FILE_WIDTH		emx_getwidth ()
#define CLH_SET_ATTR(flags, flagmask)	emx_setattr (flags, flagmask)
#define CLH_FINISH			TERM_OUT (ansi_seq [emx_monochrome])

#endif /* IN_CLH */
