This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] AmigaOS 4 port contribution


Hello.

As I already explained in a message to the gcc list
(http://gcc.gnu.org/ml/gcc/2003-09/msg01074.html), I have been working
for some time on adding support for the upcoming PPC based AmigaOS 4.0
in the mainline GCC.  This work has now been completed, and I have
received authorization from Hyperion Enterntainment to publish the
patch for review, so here goes.  Since there is currently no AmigaOS
support at all in the mainline GCC (earlier efforts exist, but were
never formally contributed), the patch is somewhat largeish, but
please bear with me.  :-)

Regarding the legal stuff, copyright for the changes will be assigned
to the FSF, we are currently just waiting for the copyright-clerk@fsf
to tell us where to send the signed form.  Since this formality should
only affect the actual comitting of the code to the repository, I
would like to offer the code for reviewing at this point, so that it
can be ready for comitting before the end of stage2 (2003-10-15).

Please note that while the changes may look very substantial, 99% are
either inside #ifdefs or in new config/ files, and thus will not
affect existing targets at all.  Therefore I do not believe that they
conflict with the goals of stage2.


Well, so much for front matter.  Now onto the pieces of information
required by the patch submission.  Note that the patch has been split
into two for easier reviewing, one handling the target support for
AmigaOS4, and one handling the host support for AmigaOS4.  (There is
no build support at the moment, the native compiler has to be cross
compiled.  This is mainly because autoconf does not work on non-UNIX
systems.)


A description of the problem/bug and how my patch addresses it
==============================================================

Problems related to supporting AmigaOS 4 as a target:

  1) GCC does not know about the "powerpc-unknown-amigaos" target.

  2) AmigaOS uses a special calling convention to system libraries,
     where a pointer to the library interface is passed implicitly
     similar to how "this" works in C++.  That is, for the call

        IDOS->PutStr("Hello");

     two arguments actually have to be passed to PutStr, namely IDOS
     and "Hello".

  3) While AmigaOS uses the SysV ABI, there is a special varargs mode
     where all unprototyped arguments are passed on the stack, like in
     PowerOpen.  This is to provide compatibility with older, m68k
     based versions of the operating system, which uses pointers
     rather than va_lists to pass on varargs between functions.

  4) AmigaOS require binaries to be relocateable since a shared
     address space is used.  They are therefore linked with
     --relocateable.  This, however, causes ld to not report on
     missing symbols.

  5) The ltconfig scripts contain special "amigaos" handling which is
     intended for the old (no longer maintained) GeekGadgets system.
     These are not approprate for the new AmigaOS.

  6) libstdc++-v3 does not know how to cross-compile for AmigaOS.

How these problems are adressed:

  1) powerpc-*-amiga* is added to config.gcc, and the associated
     target specific files to config/rs6000/.

  2) A target specific "libcall" attribute is added which causes
     build_function_call to add the interface pointer to the head of
     the argument list.

  3) A target specific "linearvarargs" attribute is added which causes
     all unprototyped arguments to be passed on the stack.  This is
     handled in config/rs6000/amigaos.c by overriding some argument
     handling functions from rs6000.c.  Two support macros
     va_startlinear and va_getlinearva are added to ginclude/stdarg.h.

  4) Code to check for missing symbols in the resulting binary is
     added to collect2.

  5) All "amigaos" cases from the ltconfig scripts are removed.

  6) Rules for *-amigaos* are added to libstdc++-v3/crossconfig.m4

Problems related to supporting AmigaOS 4 as a host:

  1) GCC does not know about the "powerpc-unknown-amigaos" host.

  2) Libibery does not have a pexecute implementation for AmigaOS.

  3) AmigaOS pexecute implementation does not (currently) support
     pipelines.

  4) AmigaOS does not support fork/exec, used by collect2.c and gcc.c

  5) Because of the differences in pathname semantics, the "standard
     prefixes" listed in gcc.c cause undesired behaviour on AmigaOS.

  6) intl/dcigettext.c can not be compiled on AmigaOS because getcwd
     is a macro.

  7) The basename and make_relative_prefix functions in libiberty make
     assumptions on pathname semantics which do not hold on AmigaOS.

  8) realpath does not exist on AmigaOS.

  9) The make_temp_file function thinks that /tmp, /usr/tmp and
     /var/tmp are good places to look for a temp directory, but this
     is not the case on AmigaOS.

How these problems are adressed:

  1) powerpc-*-amiga* is added to config.host, and the associated
     x-amigaos file to config/rs6000.

  2) Add an AmigaOS implementation of pexecute to libiberty.

  3) Disable -pipe for AmigaOS in gcc.c.

  4) Provide alternate implementations for program spawning, using
     popen in collect2.c and pexecute in gcc.c.

  5) Remove the troublesome extra prefixes when OS is AmigaOS.

  6) Put #ifndef getcwd around the extern declaration of getcwd.

  7) Add code to handle AmigaOS pathname semantics to basename and
     make_relative_prefix.

  8) Add code to use readlink, which exists and does the right thing,
     to the realpath function in libibierty.

  9) Make make_temp_file use T: as the temporary directory on AmigaOS.


Testcases
=========

Three testcases are attached.  These are:

amigaos-libcall.c:  Test that the libcall attribute works.
amigaos-varargs.c:  Test that the linearvarargs attributes works.
amigaos-dblalign.c: Check that double load/stores to potentially
                    unaligned memory are not used when copying data
                    (as this gives a very large performance penalty).


ChangeLog
=========

The ChangeLog has been split into several parts to reflect the two
patch chunks and the partitioning of ChangeLog files in the GCC tree.
The parts are:

target related ChangeLogs:

  ChangeLog-target: Core changes, goes into gcc/ChangeLog
  ChangeLog-lt:     ltconfig changes, goes into toplevel ChangeLog
  ChangeLog-stdc++: libstdc++-v3 changes, goes into libstdc++-v3/ChangeLog

host related ChangeLogs:

  ChangeLog-host:      Core changes, goes into gcc/ChangeLog
  ChangeLog-intl:      libintl changes, goes into intl/ChangeLog
  ChangeLog-libiberty: libiberty changes, goes into libiberty/ChangeLog


Bootstrapping and testing
=========================

I have built the compiler as a cross-compiler from
sparc-sun-solaris2.8 to ppc-amigaos.  This cross-compiler has then
been used to build a native compiler for ppc-amigaos.  Both the cross
compiler and the native compiler have been tested with substantial
code corpora without fail.  Cross-compilers have also been built from
other platforms such as Linux/PPC, Linux/x86 and CygWin by third
parties.


The patch iself
===============

As already stated, the patch has been split into two parts, one for
target related changes and one for host related changes.  I think this
is more manageable than the 15 patches that would result from each of
the "problems" being handled separately.

The size of the patches are 35K and 18K respectively.  I don't think
this qualifies as a need for gzip, so I'm attaching them as cleartext.



Well, that's it I suppose.  Thank you for your patience, and hoping
for a speedy processing.  :-)


  // Marcus



	* config.gcc (powerpc-*-amiga*): Add.
	* config/rs6000/amigaos.c, config/rs6000/amigaos.h,
	config/rs6000/amigaos-protos.h, config/rs6000/t-amigaos: New.
	* config/rs6000/rs6000.c (rs6000_attribute_table): Add libcall and
	linearvarargs attributes when target is AmigaOS.
	* c-typeck.c, cp/typeck.c (build_function_call): Implement AmigaOS
        libcall attribute.
	* collect2.c: Add support for reporting undefined symbols when
        COLLECT_REPORT_UNDEF is defined.
	* ginclude/stdarg.h: Add AmigaOS specific macros va_startlinear()
	and va_getlinearva().
	* doc/extend.texi (Function Attributes): Document the libcall and
	linearvarargs attributes.
	* ltcf-c.sh, ltcf-cxx.sh, ltcf-gcj.sh, ltconfig: Remove obsolete 
	cases for AmigaOS.

	* crossconfig.m4 (*-amigaos*): Add.
	* config.host (powerpc-*-amiga*): Add.
	* config/rs6000/x-amigaos: New.
	* gcc.c (process_command): Use pexecute instead of execvp to handle
	-V and -b on AmigaOS.
	* gcc.c (execute): Add AmigaOS to list of systems not supporting
	-pipe.
	* gcc.c (process_command, main): Disable some standard prefixes on
	AmigaOS since they are not standard there.
	* collect2.c (scan_prog_file): Fix the spawning of nm to not rely
	on fork/exec on AmigaOS.
	* collect2.c (main): Provide a hardcoded tool prefix for AmigaOS.
	* dcigettext.c: Guard against getcwd being a macro.
	* configure.in, Makefile.in: Add pex-amigaos.
	* pex-amigaos.c: New.
	* basename.c, lbasename.c, make-relative-prefix.c: Support
	AmigaOS pathname semantics.
	* lrealpath.c: Use readlink as a fallback on AmigaOS.
	* make-temp-file.c (choose_tmpdir): Use T: as the tmpdir on AmigaOS.
/* { dg-do run { target *-*-amigaos* } } */

/* Test the libcall function attribute */

struct testlib {

  /* regular function */
  int (*func1) (int x, int y);

  /* libcall function */
  int (*func2) (struct testlib *l, int z) __attribute__((libcall));

  /* instance variable */
  int v;
};

int func1_impl (int x, int y)
{
  return x + y;
}

int func2_impl (struct testlib *l, int z)
{
  return z + l->v;
}

struct testlib testlib_inst = {
  func1_impl,
  func2_impl,
  42
};

int main ()
{
  struct testlib *lp = &testlib_inst;

  /* First, call struct directly */
  if (testlib_inst.func1 (73, 99) != 172 ||
      testlib_inst.func2 (19) != 61)
    abort();

  /* Next, try it with a pointer */
  if (lp->func1 (73, 99) != 172 ||
      lp->func2 (19) != 61)
    abort();

  return 0;
}
/* { dg-do run { target *-*-amigaos* } } */

/* Test varargs with and without the linearvarargs function attribute */

#include <stdarg.h>

extern void abort (void);

/* Test regular va_list */
int vva1 (int n, va_list v)
{
  int i, sum = 0;
  for (i=0; i<n; i++)
    sum += va_arg (v, int);
  return sum;
}

/* Test linearized varargs */
int vva2 (int n, int *v)
{
  int i, sum = 0;
  for (i=0; i<n; i++)
    sum += *v++;
  return sum;
}

/* Normal varargs function */
int va1 (int n, ...)
{
  int r;
  va_list l;
  va_start (l, n);
  r = vva1 (n, l);
  va_end (l);
  return r;
}

/* linearvarargs function */
int va2 (int n, ...) __attribute__((linearvarargs));
int va2 (int n, ...)
{
  int r;
  va_list l;
  va_startlinear (l, n);
  r = vva2 (n, va_getlinearva (l, int *));
  va_end (l);
  return r;
}

int main () {
  if (va1 (3, 17, 42, 4711) != 4770)
    abort ();
  if (va2 (3, 71, 24, 1174) != 1269)
    abort ();
  return 0;
}
/* { dg-do compile { target powerpc*-*-amigaos* } } */
/* { dg-final { scan-assembler-not "lfd" } } */
/* { dg-final { scan-assembler-not "stfd" } } */

/* Check that copying of structs does not generate
   possibly unaligned double load/stores.          */

/* This struct has 4 byte alignment */
struct x {
  int a;
  int b;
};

void q(struct x *y)
{
  struct x z;

  /* This copy should not use lfd/stfd since
     *y might not have 8 byte alignment.     */
  z = *y;
}
Index: ltcf-c.sh
===================================================================
RCS file: /cvsroot/gcc/gcc/ltcf-c.sh,v
retrieving revision 1.18
diff -u -r1.18 ltcf-c.sh
--- ltcf-c.sh	16 Dec 2002 18:18:42 -0000	1.18
+++ ltcf-c.sh	5 Oct 2003 13:03:11 -0000
@@ -73,20 +73,6 @@
     fi
     ;;
 
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
-    ;;
-
   beos*)
     if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
       allow_undefined_flag=unsupported
@@ -359,14 +345,6 @@
     fi
     ;;
 
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
   cygwin* | mingw*)
     # When not using gcc, we currently assume that we are using
     # Microsoft Visual C++.
@@ -652,12 +630,6 @@
       else
         lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
       fi
-      ;;
-    amigaos*)
-      # FIXME: we need at least 68020 code to build shared libraries, but
-      # adding the `-m68020' flag to GCC prevents building anything better,
-      # like `-m68040'.
-      ac_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
       ;;
     beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
       # PIC is the default for these OSes.
Index: ltcf-cxx.sh
===================================================================
RCS file: /cvsroot/gcc/gcc/ltcf-cxx.sh,v
retrieving revision 1.25
diff -u -r1.25 ltcf-cxx.sh
--- ltcf-cxx.sh	20 Feb 2003 01:11:51 -0000	1.25
+++ ltcf-cxx.sh	5 Oct 2003 13:03:12 -0000
@@ -695,12 +695,6 @@
       lt_cv_prog_cc_static='-bnso -bI:/lib/syscalls.exp'
     fi
     ;;
-  amigaos*)
-    # FIXME: we need at least 68020 code to build shared libraries, but
-    # adding the `-m68020' flag to GCC prevents building anything better,
-    # like `-m68040'.
-    ac_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
-    ;;
   beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
     # PIC is the default for these OSes.
     ;;
Index: ltcf-gcj.sh
===================================================================
RCS file: /cvsroot/gcc/gcc/ltcf-gcj.sh,v
retrieving revision 1.12
diff -u -r1.12 ltcf-gcj.sh
--- ltcf-gcj.sh	19 Feb 2003 23:50:23 -0000	1.12
+++ ltcf-gcj.sh	5 Oct 2003 13:03:12 -0000
@@ -76,20 +76,6 @@
     fi
     ;;
 
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
-    ;;
-
   beos*)
     if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
       allow_undefined_flag=unsupported
@@ -352,14 +338,6 @@
     fi
   ;;
 
-  amigaos*)
-    archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
   cygwin* | mingw*)
     # When not using gcc, we currently assume that we are using
     # Microsoft Visual C++.
@@ -627,12 +605,6 @@
       # This hack is so that the source file can tell whether it is being
       # built for inclusion in a dll (and should export symbols for example).
       ac_cv_prog_cc_pic='-DDLL_EXPORT'
-      ;;
-    amigaos*)
-      # FIXME: we need at least 68020 code to build shared libraries, but
-      # adding the `-m68020' flag to GCC prevents building anything better,
-      # like `-m68040'.
-      ac_cv_prog_cc_pic='-m68020 -resident32 -malways-restore-a4'
       ;;
     sysv4*MP*)
       if test -d /usr/nec; then
Index: ltconfig
===================================================================
RCS file: /cvsroot/gcc/gcc/ltconfig,v
retrieving revision 1.27
diff -u -r1.27 ltconfig
--- ltconfig	4 Oct 2003 04:54:17 -0000	1.27
+++ ltconfig	5 Oct 2003 13:03:14 -0000
@@ -1037,12 +1037,6 @@
   fi
   ;;
 
-amigaos*)
-  library_names_spec='$libname.ixlibrary $libname.a'
-  # Create ${libname}_ixlibrary.a entries in /sys/libs.
-  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
-  ;;
-
 beos*)
   library_names_spec='${libname}.so'
   dynamic_linker="$host_os ld.so"
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.259
diff -u -r1.259 c-typeck.c
--- gcc/c-typeck.c	28 Sep 2003 19:09:49 -0000	1.259
+++ gcc/c-typeck.c	5 Oct 2003 13:03:17 -0000
@@ -1684,6 +1684,16 @@
   /* fntype now gets the type of function pointed to.  */
   fntype = TREE_TYPE (fntype);
 
+#ifdef TARGET_AMIGAOS_DECL_ATTRIBUTES
+  if (lookup_attribute("libcall", TYPE_ATTRIBUTES(fntype))) 
+    if (TREE_CODE(function)==COMPONENT_REF)
+      params = chainon (build_tree_list(NULL_TREE, 
+					build1(ADDR_EXPR,build_pointer_type(TREE_TYPE(TREE_OPERAND(function,0))),
+					       TREE_OPERAND(function,0))
+					)
+			, params);
+#endif
+
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
Index: gcc/config.gcc
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.393
diff -u -r1.393 config.gcc
--- gcc/config.gcc	2 Oct 2003 00:44:13 -0000	1.393
+++ gcc/config.gcc	5 Oct 2003 13:03:19 -0000
@@ -1567,6 +1567,13 @@
 avr-*-*)
 	use_fixproto=yes
 	;;
+powerpc-*-amiga*)
+	tm_file="${tm_file} dbxelf.h elfos.h svr4.h rs6000/sysv4.h rs6000/amigaos.h"
+	tm_p_file="${tm_p_file} rs6000/amigaos-protos.h"
+	tmake_file=rs6000/t-amigaos
+	extra_objs=amigaos.o
+	use_collect2=yes
+	;;
 # port not yet contributed
 #powerpc-*-openbsd*)
 #	tmake_file="${tmake_file} rs6000/t-fprules "
Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.522
diff -u -r1.522 rs6000.c
--- gcc/config/rs6000/rs6000.c	2 Oct 2003 00:44:27 -0000	1.522
+++ gcc/config/rs6000/rs6000.c	5 Oct 2003 13:03:36 -0000
@@ -13269,6 +13269,10 @@
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "longcall",  0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
   { "shortcall", 0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
+#ifdef TARGET_AMIGAOS_DECL_ATTRIBUTES
+  { "libcall",  0, 0, false, true,  true,  amigaos_handle_libcall_attribute },
+  { "linearvarargs", 0, 0, false, true,  true,  amigaos_handle_linearvarargs_attribute },
+#endif
   { NULL,        0, 0, false, false, false, NULL }
 };
 
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.506
diff -u -r1.506 typeck.c
--- gcc/cp/typeck.c	2 Oct 2003 23:14:01 -0000	1.506
+++ gcc/cp/typeck.c	5 Oct 2003 13:03:39 -0000
@@ -2410,6 +2410,16 @@
   /* fntype now gets the type of function pointed to.  */
   fntype = TREE_TYPE (fntype);
 
+#ifdef TARGET_AMIGAOS_DECL_ATTRIBUTES
+  if (lookup_attribute("libcall", TYPE_ATTRIBUTES(fntype))) 
+    if (TREE_CODE(function)==COMPONENT_REF)
+      params = chainon (build_tree_list(NULL_TREE, 
+					build1(ADDR_EXPR,build_pointer_type(TREE_TYPE(TREE_OPERAND(function,0))),
+					       TREE_OPERAND(function,0))
+					)
+			, params);
+#endif
+
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
Index: gcc/doc/extend.texi
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.163
diff -u -r1.163 extend.texi
--- gcc/doc/extend.texi	4 Oct 2003 10:53:09 -0000	1.163
+++ gcc/doc/extend.texi	5 Oct 2003 13:03:43 -0000
@@ -2673,6 +2673,20 @@
 are to use a .def file with an @code{EXPORTS} section or, with GNU ld,
 using the @option{--export-all} linker flag.
 
+@item libcall
+@cindex @code{AmigaOS specific function attributes}
+On AmigaOS, the @code{libcall} attribute is used to declare function
+pointers in an AmigaOS @emph{Interface}.  When such a function pointer
+is invoked, a pointer to the Interface itself is passed as a hidden
+first argument, similar to @code{this} in C++.
+
+@item linearvarargs
+@cindex @code{AmigaOS specific function attributes}
+On AmigaOS, the @code{linearvarargs} attribute causes all unprototyped
+arguments to a varargs function to be passed on the stack, and not in
+registers as the SVR4 ABI defines.  Please note that @code{libcall} also
+implies @code{linearvarargs}.
+
 @end table
 
 You can specify multiple attributes in a declaration by separating them
Index: gcc/ginclude/stdarg.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/ginclude/stdarg.h,v
retrieving revision 1.17
diff -u -r1.17 stdarg.h
--- gcc/ginclude/stdarg.h	13 Mar 2003 02:58:40 -0000	1.17
+++ gcc/ginclude/stdarg.h	5 Oct 2003 13:03:47 -0000
@@ -55,6 +55,19 @@
 #endif
 #define __va_copy(d,s)	__builtin_va_copy(d,s)
 
+/* AmigaOS4 specific macros for use with __atribute__((linearvarargs)) */
+#if defined(__amigaos__) && defined (__PPC__)
+
+#define va_startlinear(AP, x)			\
+           va_start(AP, x);			\
+           (AP)->gpr = 8;			\
+           (AP)->fpr = 8;
+
+#define va_getlinearva(AP,TYPE)                 \
+           (TYPE)((AP)->overflow_arg_area)
+
+#endif /* __amigaos__ && __PPC__ */
+
 /* Define va_list, if desired, from __gnuc_va_list. */
 /* We deliberately do not define va_list when called from
    stdio.h, because ANSI C says that stdio.h is not supposed to define
Index: libstdc++-v3/crossconfig.m4
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/crossconfig.m4,v
retrieving revision 1.4
diff -u -r1.4 crossconfig.m4
--- libstdc++-v3/crossconfig.m4	1 Oct 2003 20:45:45 -0000	1.4
+++ libstdc++-v3/crossconfig.m4	5 Oct 2003 13:05:14 -0000
@@ -358,6 +358,17 @@
     AC_DEFINE(HAVE_TANF)
     AC_DEFINE(HAVE_TANHF)
     ;;
+  *-amigaos*)
+    AC_CHECK_HEADERS([nan.h ieeefp.h endian.h sys/isa_defs.h \
+      machine/endian.h machine/param.h sys/machine.h sys/types.h \
+      fp.h locale.h float.h inttypes.h])
+    SECTION_FLAGS='-ffunction-sections -fdata-sections'
+    AC_SUBST(SECTION_FLAGS)
+    GLIBCXX_CHECK_LINKER_FEATURES
+    GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT
+    GLIBCXX_CHECK_WCHAR_T_SUPPORT
+    AC_DEFINE(HAVE_COPYSIGN)
+    ;;
   *)
     AC_MSG_ERROR([No support for this host/target combination.])
    ;;
Index: gcc/config/rs6000/amigaos.c
===================================================================
diff -u /dev/null gcc/config/rs6000/amigaos.c
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ gcc/config/rs6000/amigaos.c	Mon Sep 15 00:31:36 2003
@@ -0,0 +1,273 @@
+/* Subroutines used for code generation on Amiga OS 4
+   Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
+   Contributed by Thomas Frieden (ThomasF@hyperion-entertainment.com)
+
+This file is part of GNU CC.
+
+GNU CC 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 2, or (at your option)
+any later version.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "obstack.h"
+#include "tree.h"
+#include "expr.h"
+#include "optabs.h"
+#include "except.h"
+#include "function.h"
+#include "output.h"
+#include "errors.h"
+#include "tm_p.h"
+
+#undef DEBUG
+#ifdef DEBUG
+#define dprintf(...)      			\
+printf("%s: ", __PRETTY_FUNCTION__);		\
+printf(__VA_ARGS__)
+#else
+#define dprintf(...) /* __VA_ARGS__ */
+#endif
+
+
+void
+amigaos_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
+	rtx libname ATTRIBUTE_UNUSED, int incoming)
+{
+    dprintf("enter\n");
+    init_cumulative_args(cum, fntype, libname, incoming, FALSE);
+
+    /* Check if either libcall or linear varargs, set appropriate cookie */
+    if (fntype && (lookup_attribute("libcall", TYPE_ATTRIBUTES (fntype))))
+		cum->call_cookie |= CALL_LINEARVARARGS;
+
+    if (fntype && (lookup_attribute("linearvarargs", TYPE_ATTRIBUTES (fntype))))
+		cum->call_cookie |= CALL_LINEARVARARGS;
+
+    dprintf("exit\n");
+}
+
+
+void
+amigaos_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+	tree type, int named)
+{
+    dprintf("enter\n");
+    function_arg_advance(cum, mode, type, named);
+ 
+    if (cum->call_cookie & CALL_LINEARVARARGS && cum->nargs_prototype < 0)
+    {
+	cum->sysv_gregno = GP_ARG_MAX_REG + 1;
+	cum->fregno = FP_ARG_V4_MAX_REG + 1;
+    }
+    dprintf("exit\n");
+}
+
+
+struct rtx_def *
+amigaos_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+	tree type, int named)
+{
+    struct rtx_def *res = 0;
+
+    dprintf("enter\n");
+    if (mode == VOIDmode && cum->call_cookie & CALL_LINEARVARARGS)
+	res = GEN_INT (cum->call_cookie);
+    else
+	res =  function_arg (cum, mode, type, named);
+
+    dprintf("exit\n");
+
+    return res;
+}
+
+
+
+void
+amigaos_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+	tree type, int *pretend_size, int no_rtl)
+{
+  CUMULATIVE_ARGS next_cum;
+  /*
+  int reg_size = TARGET_32BIT ? 4 : 8;
+  */
+  rtx save_area;
+  int first_reg_offset;
+
+  dprintf("enter\n");
+  if (cum->call_cookie & CALL_LINEARVARARGS)
+  {
+      tree fntype;
+      int stdarg_p;
+      
+      fntype = TREE_TYPE (current_function_decl);
+      stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
+		  && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+		      != void_type_node));
+      
+      /* For varargs, we do not want to skip the dummy va_dcl argument.
+	 For stdargs, we do want to skip the last named argument.  */
+      next_cum = *cum;
+      if (stdarg_p)
+	  function_arg_advance (&next_cum, mode, type, 1);
+      
+      /* Indicate to allocate space on the stack for varargs save area.  */
+      /* ??? Does this really have to be located at a magic spot on the
+	 stack, or can we allocate this with assign_stack_local instead.  */
+      cfun->machine->sysv_varargs_p = 1;
+      if (! no_rtl)
+	  save_area = plus_constant (virtual_stack_vars_rtx,
+				     - RS6000_VARARGS_SIZE);
+
+      first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
+
+  }
+  else
+  {
+      setup_incoming_varargs(cum, mode, type, pretend_size, no_rtl);
+  }
+
+  dprintf("exit\n");
+
+}
+
+
+struct rtx_def *
+amigaos_expand_builtin_saveregs (void)
+{
+  rtx block, mem_gpr_fpr, /*mem_reg_save_area,*/ mem_overflow, tmp;
+  tree fntype;
+  int stdarg_p;
+  HOST_WIDE_INT words, gpr/*, fpr*/;
+  struct rtx_def *res;
+
+  dprintf("enter\n");
+
+  if (current_function_args_info.call_cookie & CALL_LINEARVARARGS)
+  {
+      HOST_WIDE_INT bits;
+
+      fntype = TREE_TYPE (current_function_decl);
+      stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
+		  && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+		      != void_type_node));
+      
+      /* Allocate the va_list constructor.  */
+      block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
+      RTX_UNCHANGING_P (block) = 1;
+      RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
+      
+      mem_gpr_fpr = change_address (block, word_mode, XEXP (block, 0));
+      mem_overflow = change_address (block, ptr_mode,
+				     plus_constant (XEXP (block, 0),
+                                                UNITS_PER_WORD));
+      /*mem_reg_save_area = change_address (block, ptr_mode,
+	plus_constant (XEXP (block, 0),
+	2 * UNITS_PER_WORD));*/
+      
+      /* Construct the two characters of `gpr' and `fpr' as a unit.  */
+      words = current_function_args_info.words;
+      gpr = current_function_args_info.sysv_gregno - GP_ARG_MIN_REG;
+      
+      /* Varargs has the va_dcl argument, but we don't count it.  */
+      if (!stdarg_p)
+      {
+	  if (gpr > GP_ARG_NUM_REG)
+	      words -= 1;
+      }
+      
+      bits = (GP_ARG_MAX_REG - GP_ARG_MIN_REG + 1) << 8
+	  | (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1);
+      if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD)
+	  tmp = GEN_INT (bits << (BITS_PER_WORD - 16));
+      else
+      {
+	  bits <<= BITS_PER_WORD - HOST_BITS_PER_WIDE_INT - 16;
+	  tmp = immed_double_const (0, bits, word_mode);
+      }
+      
+      emit_move_insn (mem_gpr_fpr, tmp);
+      
+      /* Find the overflow area.  */
+      tmp = expand_binop (Pmode, add_optab, virtual_incoming_args_rtx,
+			  GEN_INT (words * UNITS_PER_WORD),
+			  mem_overflow, 0, OPTAB_WIDEN);
+      if (tmp != mem_overflow)
+	  emit_move_insn (mem_overflow, tmp);
+      
+      /*tmp = expand_binop (Pmode, add_optab, virtual_stack_vars_rtx,
+	GEN_INT (-RS6000_VARARGS_SIZE),
+	mem_reg_save_area, 0, OPTAB_WIDEN);
+	if (tmp != mem_reg_save_area)
+	emit_move_insn (mem_reg_save_area, tmp);*/
+      
+      /* Return the address of the va_list constructor.  */
+      res = XEXP (block, 0);
+  }
+  else
+  {
+      res = expand_builtin_saveregs();
+  }
+
+  dprintf("exit\n");
+  return res;
+}
+
+
+tree
+amigaos_handle_libcall_attribute (tree *node, tree name,
+	tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
+	bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+tree
+amigaos_handle_linearvarargs_attribute (tree *node, tree name,
+	tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED,
+	bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
Index: gcc/config/rs6000/amigaos.h
===================================================================
diff -u /dev/null gcc/config/rs6000/amigaos.h
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ gcc/config/rs6000/amigaos.h	Wed Oct  1 00:33:00 2003
@@ -0,0 +1,144 @@
+/* Definitions of target machine for GNU compiler, for AmigaOS.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+
+
+This file is part of GNU CC.
+
+GNU CC 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 2, or (at your option)
+any later version.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+/* On AmigaOS, binaries are linked with -r, so we'll rely on collect2
+   to inform us of any undefined symbols. */
+#define COLLECT_REPORT_UNDEF
+
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+/* Make CPU default to 604e. FIXME: Make this 750 later */
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC604e
+
+#undef DEFAULT_ABI
+#define DEFAULT_ABI ABI_V4
+
+/* Make most of the definitions from other compilers available */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS()                \
+  do                                            \
+    {                                           \
+      builtin_define_std ("PPC");		\
+      builtin_define ("__ELF__");		\
+      builtin_define ("powerpc");		\
+      builtin_assert ("cpu=powerpc");		\
+      builtin_assert ("machine=powerpc");	\
+      builtin_define ("AMIGA");			\
+      builtin_define ("AMIGAOS");		\
+      builtin_define ("AMIGAOS4");		\
+      builtin_define ("__amigaos__");		\
+      builtin_define ("__amiga__");		\
+      builtin_define ("__amigaos4__");		\
+      builtin_define ("amiga");			\
+      builtin_define ("amigaos");		\
+      builtin_define ("amigaos4");		\
+      TARGET_OS_SYSV_CPP_BUILTINS ();		\
+    }                                           \
+  while (0)
+
+
+#undef CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC "%(cpp_os_amigaos)"
+
+#define STANDARD_INCLUDE_DIR "gcc:include"
+#define SYSTEM_INCLUDE_DIR "gcc:os-include"
+#undef LOCAL_INCLUDE_DIR
+
+#undef LINK_SPEC
+#define LINK_SPEC "\
+--relocateable -d %{h*} %{v:-V} %{G*} \
+%{Wl,*:%*} %{YP,*} %{R*} \
+%{Qy:} %{!Qn:-Qy} \
+%(link_target) \
+%(link_os)"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC 	"crtbegin.o%s crt0.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC								\
+"--start-group -lc -lamiga --end-group"
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC AmigaOS 4)");
+
+#undef TARGET_DEFAULT
+#define	TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_REGNAMES)
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+
+
+#undef DEFAULT_VTABLE_THUNKS
+#ifndef USE_GNULIBC_1
+#define DEFAULT_VTABLE_THUNKS 1
+#endif
+
+#undef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 0
+
+/* Used as cookie for linear vararg passing */
+#define CALL_LINEARVARARGS      0x10000000
+
+/* Overrides */
+#undef INIT_CUMULATIVE_ARGS
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+    amigaos_init_cumulative_args(&CUM, FNTYPE, LIBNAME, FALSE)
+
+#undef INIT_CUMULATIVE_INCOMING_ARGS
+#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
+    amigaos_init_cumulative_args(&CUM, FNTYPE, LIBNAME, TRUE)
+
+#undef FUNCTION_ARG_ADVANCE
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)    \
+    amigaos_function_arg_advance(&CUM, MODE, TYPE, NAMED)
+
+#undef FUNCTION_ARG
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+    amigaos_function_arg(&CUM, MODE, TYPE, NAMED)
+
+#undef SETUP_INCOMING_VARARGS
+#define SETUP_INCOMING_VARARGS(CUM,MODE, TYPE,PRETEND_SIZE, NO_RTL) \
+    amigaos_setup_incoming_varargs(&CUM, MODE, TYPE, &PRETEND_SIZE, NO_RTL)
+
+#undef EXPAND_BUILTIN_SAVEREGS
+#define EXPAND_BUILTIN_SAVEREGS() \
+    amigaos_expand_builtin_saveregs()
+
+#undef SLOW_UNALIGNED_ACCESS
+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN)				\
+  (STRICT_ALIGNMENT							\
+   || (((MODE) == SFmode) && (ALIGN) < 32)				\
+   || (((MODE) == DFmode || (MODE) == TFmode || (MODE) == DImode)	\
+       && (ALIGN) < 64))
+
+#define TARGET_AMIGAOS_DECL_ATTRIBUTES
+
Index: gcc/config/rs6000/t-amigaos
===================================================================
diff -u /dev/null gcc/config/rs6000/t-amigaos
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ gcc/config/rs6000/t-amigaos	Fri Sep 12 21:17:46 2003
@@ -0,0 +1,28 @@
+# Do not build libgcc1.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so... [taken from t-sparclite]
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+	cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+	echo '#define FLOAT' > fp-bit.c
+	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+amigaos.o: $(srcdir)/config/rs6000/amigaos.c
+	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = msoft-float
+MULTILIB_DIRNAMES = soft-float
+
+NATIVE_SYSTEM_HEADER_DIR=gcc:include
+CROSS_SYSTEM_HEADER_DIR=${gcc_tooldir}/include
+
+# FIXME: do this
+# USE_COLLECT2 =
Index: gcc/config/rs6000/amigaos-protos.h
===================================================================
diff -u /dev/null gcc/config/rs6000/amigaos-protos.h
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ gcc/config/rs6000/amigaos-protos.h	Sun Sep 14 15:08:15 2003
@@ -0,0 +1,34 @@
+/* Prototypes.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC 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 2, or (at your option)
+any later version.
+
+GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+
+#ifdef RTX_CODE
+#ifdef TREE_CODE
+
+extern void amigaos_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int);
+extern void amigaos_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern struct rtx_def *amigaos_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern void amigaos_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
+extern struct rtx_def *amigaos_expand_builtin_saveregs (void);
+extern tree amigaos_handle_libcall_attribute (tree *, tree, tree, int, bool*);
+extern tree amigaos_handle_linearvarargs_attribute (tree *, tree, tree, int, bool*);
+
+#endif /* TREE_CODE */
+#endif /* RTX_CODE */
Index: gcc/collect2.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/collect2.c,v
retrieving revision 1.153
diff -u -r1.153 collect2.c
--- gcc/collect2.c	19 Jul 2003 14:47:00 -0000	1.153
+++ gcc/collect2.c	5 Oct 2003 13:03:18 -0000
@@ -144,6 +144,22 @@
 #define SCAN_LIBRARIES
 #endif
 
+#ifdef COLLECT_REPORT_UNDEF
+struct undef_list_node
+{
+	struct undef_list_node *next;
+	char *name;
+	int reported;
+};
+
+struct undef_list_node undef_list = { NULL, NULL, 0 };
+
+void empty_undef_list(void);
+void report_undef_list(char **);
+void add_undef_list(char *);
+struct undef_list_node *find_undef_list(char *name);
+#endif
+
 #ifdef USE_COLLECT2
 int do_collecting = 1;
 #else
@@ -1305,7 +1325,13 @@
 
   /* On AIX we already scanned for global constructors/destructors.  */
 #ifndef COLLECT_EXPORT_LIST
+#ifdef COLLECT_REPORT_UNDEF
+  empty_undef_list();
+#endif
   scan_prog_file (output_file, PASS_FIRST);
+#ifdef COLLECT_REPORT_UNDEF
+  report_undef_list(object_lst);
+#endif
 #endif
 
 #ifdef SCAN_LIBRARIES
@@ -2066,7 +2161,24 @@
 
       for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++)
 	if (ch == ' ' && p[1] == 'U' && p[2] == ' ')
+#ifdef COLLECT_REPORT_UNDEF
+	  {
+	    /* Undefined symbol... find start and end */
+	    p += 3;
+	    for (end = p;
+		 (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2)
+		   && ch2 != '|';
+		 end++);
+	    *end = '\0';
+	    
+	    add_undef_list (p);
+	    if (debug)
+	      fprintf (stderr, "Undefined reference to `%s'\n", p);
+	    break;
+	  }
+#else
 	  break;
+#endif
 
       if (ch != '_')
 	continue;
@@ -2835,3 +2949,270 @@
   return (NULL);
 }
 #endif /* COLLECT_EXPORT_LIST */
+
+#ifdef COLLECT_REPORT_UNDEF
+void empty_undef_list(void)
+{
+  struct undef_list_node *cur;
+  struct undef_list_node *next;
+
+  cur = undef_list.next; 
+
+  while (cur)
+    {
+      next = cur->next;
+
+      if (cur->name)
+	free (cur->name);
+		
+      free (cur);
+
+      cur = next;
+    }
+}
+
+struct undef_list_node *find_undef_list(char *name)
+{
+  struct undef_list_node *cur;
+
+  for (cur = undef_list.next; cur; cur = cur->next)
+    {
+      if (strcmp (cur->name, name) == 0)
+	return cur;
+    }
+
+  return 0;
+}
+
+
+void add_undef_list(char *name)
+{
+  struct undef_list_node *newnode;
+  struct undef_list_node *prev;
+  struct undef_list_node *cur;
+
+  newnode = xmalloc (sizeof (struct undef_list_node));
+  newnode->name = xstrdup (name);
+  newnode->reported = 0;
+
+  prev = &undef_list;
+  cur = undef_list.next;
+
+  do
+    {
+      int res;
+
+      if (cur)
+	res = strcmp (cur->name, newnode->name);
+      else
+	{
+	  prev->next = newnode;
+	  newnode->next = cur;
+	  return;
+	}
+
+      if (res == 0)
+	{
+	  free (newnode->name);
+	  free (newnode);
+	  return;
+	}
+
+      if (res > 0)
+	{
+	  prev->next = newnode;
+	  newnode->next = cur;
+	  return;
+	}
+
+      prev = cur;
+      cur = cur->next;
+    } while (cur);
+
+  prev->next = newnode;
+  newnode->next = cur;
+}
+
+void report_undef_list(char **object_lst)
+{
+  struct undef_list_node *cur;
+  int numargs;
+  const char **nm_argv;
+  int argc;
+  char buf[2048];
+  FILE *inf;
+  int print_head = 1;
+  char *scmd,*s;
+  int i,j,len,arglen,c,need_quote;
+
+  cur = undef_list.next; 
+  if (!cur)
+    return;
+
+  /* Count number of object files */
+  for (numargs = 0; object_lst[numargs]; numargs++)
+    {
+      if (debug)
+	fprintf (stderr, "Object file %s\n", object_lst[numargs]);
+    }
+
+  fflush (stderr);
+
+  /* Build arguments for nm */
+  if (nm_file_name == 0)
+    fatal ("cannot find `nm'");
+
+  nm_argv = xmalloc (sizeof(char *)*(numargs+5));
+	
+  argc = 0;
+
+  nm_argv[argc++] = nm_file_name;
+  nm_argv[argc++] = "-A";
+  nm_argv[argc++] = "-u";
+
+  for (i = 0; i < numargs; i++)
+    nm_argv[argc++] = object_lst[i];
+	
+  nm_argv[argc++] = 0;
+
+  len = 0;
+
+  for (i = 0 ; nm_argv[i] != NULL ; i++)
+    {
+      arglen = strlen (nm_argv[i]);
+
+      len += 1 + arglen;
+
+      for (j = 0, need_quote = 0 ; j < arglen ; j++)
+	{
+	  c = nm_argv[i][j];
+
+	  if(c == ' ')
+	    need_quote = 1;
+	  else if (c == '\"')
+	    len++;
+	}
+
+      if(need_quote)
+	len += 2;
+    }
+
+  s = scmd = (char *) xmalloc (len+1);
+
+  for (i = 0 ; nm_argv[i] != NULL ; i++)
+    {
+      arglen = strlen (nm_argv[i]);
+
+      for (j = 0, need_quote = 0 ; j < arglen ; j++)
+	{
+	  if (nm_argv[i][j] == ' ')
+	    need_quote = 1;
+	}
+
+      if (s != scmd)
+	(*s++) = ' ';
+
+      if (need_quote)
+	(*s++) = '\"';
+
+      for (j = 0 ; j < arglen ; j++)
+	{
+	  c = nm_argv[i][j];
+	  if (c == '\"')
+	    (*s++) = '*';
+
+	  (*s++) = c;
+	}
+
+      if(need_quote)
+	(*s++) = '\"';
+    }
+
+  (*s) = '\0';
+
+  /* Trace if needed.  */
+  if (vflag)
+    {
+      const char **p_argv;
+      const char *str;
+
+      for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++)
+	fprintf (stderr, " %s", str);
+
+      fprintf (stderr, "\n");
+    }
+
+  fflush (stdout);
+  fflush (stderr);
+
+  inf = popen (scmd,"r");
+  if (inf == (FILE *) NULL)
+    fatal_perror ("popen");
+
+  free (scmd);
+
+  while (fgets (buf, sizeof buf, inf) != (char *) 0)
+    {
+      char *filename;
+      char *symname;
+      char *end;
+      struct undef_list_node *node;
+
+      /* Scan the nm output */
+      filename = buf;
+      symname = strrchr (buf, ':');
+
+      /* Check for malformed line (shouldn't happen) */
+      if (!symname)
+	continue;
+
+      /* Seperate filename */
+      *symname++ = 0;
+
+      /* Kill off \n at end of line */
+      end = strchr(symname, '\n');
+      if (end)
+	*end = 0;
+
+      /* Skip past any spaces and U */
+      while (*symname == ' ')
+	symname++;
+
+      if (*symname == 'U' && symname[1] == ' ')
+	symname += 2;
+
+      /* Find the node */
+      node = find_undef_list (symname);
+
+      if (node)
+	{
+	  fprintf( stderr, "%s: Undefined reference to %s\n", filename, symname);
+	  node->reported++;
+	}	
+
+    }
+
+  if (fclose (inf) != 0)
+    fatal_perror ("fclose");
+	
+  /* Show remaining (if any) */
+  cur = undef_list.next; 
+
+  while (cur)
+    {
+      if (!cur->reported)
+	{
+	  if (print_head)
+	    {
+	      print_head = 0;
+	      fprintf (stderr, "Other undefined references:\n");
+	    }
+	  fprintf (stderr, "Undefined reference to `%s'\n", cur->name);
+	}
+      
+      cur = cur->next;
+    }
+  
+  collect_exit (FATAL_EXIT_CODE);
+}
+#endif /* COLLECT_REPORT_UNDEF */
Index: gcc/config.host
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config.host,v
retrieving revision 2.5
diff -u -r2.5 config.host
--- gcc/config.host	1 Oct 2003 23:51:10 -0000	2.5
+++ gcc/config.host	5 Oct 2003 13:03:19 -0000
@@ -145,6 +145,11 @@
   i860-*-sysv4*)
     host_xmake_file=i860/x-sysv4
     ;;
+  powerpc-*-amiga*) # AmigaOS 4
+    prefix=/gcc
+    local_prefix=/gcc
+    host_xmake_file=rs6000/x-amigaos
+    ;;
   powerpc-*-darwin*)
     # powerpc-darwin host support.
     out_host_hook_obj=host-darwin.o
Index: gcc/gcc.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.393
diff -u -r1.393 gcc.c
--- gcc/gcc.c	4 Sep 2003 06:30:02 -0000	1.393
+++ gcc/gcc.c	5 Oct 2003 13:03:24 -0000
@@ -2626,7 +2626,7 @@
   for (n_commands = 1, i = 0; i < argbuf_index; i++)
     if (strcmp (argbuf[i], "|") == 0)
       {				/* each command.  */
-#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
+#if defined (__MSDOS__) || defined (OS2) || defined (VMS) || defined(__amigaos__)
 	fatal ("-pipe not supported");
 #endif
 	argbuf[i] = 0;	/* termination of command args.  */
@@ -3148,15 +3148,28 @@
 			  (argc + 1) * sizeof (argv[0]));
       new_argv[0] = new_argv0;
 
+#ifndef __amigaos__
       execvp (new_argv0, new_argv);
       fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
+#else /* __amigaos__ */
+      {
+	char *errmsg_fmt, *errmsg_arg;
+	int pid, status;
+	pid = pexecute (new_argv0, new_argv, programname, NULL,
+			&errmsg_fmt, &errmsg_arg, PEXECUTE_ONE);
+	if (pid == -1)
+	  pfatal_pexecute (errmsg_fmt, errmsg_arg);
+	pwait (pid, &status, 0);
+	exit (status >> 8);
+      }      
+#endif /* __amigaos__ */
     }
 
   /* Set up the default search paths.  If there is no GCC_EXEC_PREFIX,
      see if we can create it from the pathname specified in argv[0].  */
 
   gcc_libexec_prefix = standard_libexec_prefix;
-#ifndef VMS
+#if !defined (VMS) && !defined (__amigaos__)
   /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
   if (!gcc_exec_prefix)
     {
@@ -3736,16 +3749,20 @@
 	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
   add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
 	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
+#ifndef __amigaos__
   add_prefix (&exec_prefixes, standard_exec_prefix_1, "BINUTILS",
 	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
   add_prefix (&exec_prefixes, standard_exec_prefix_2, "BINUTILS",
 	      PREFIX_PRIORITY_LAST, 2, warn_std_ptr, 0);
 #endif
+#endif
 
   add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
 	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
+#ifndef __amigaos__
   add_prefix (&startfile_prefixes, standard_exec_prefix_2, "BINUTILS",
 	      PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0);
+#endif
 
   tooldir_prefix = concat (tooldir_base_prefix, spec_machine,
 			   dir_separator_str, NULL);
@@ -6128,10 +6145,12 @@
 		      NULL, PREFIX_PRIORITY_LAST, 0, NULL, 1);
 	}
 
+#ifndef __amigaos__
       add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_1,
 			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
       add_sysrooted_prefix (&startfile_prefixes, standard_startfile_prefix_2,
 			    "BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
+#endif
 #if 0 /* Can cause surprises, and one can use -B./ instead.  */
       add_prefix (&startfile_prefixes, "./", NULL,
 		  PREFIX_PRIORITY_LAST, 1, NULL, 0);
Index: intl/dcigettext.c
===================================================================
RCS file: /cvsroot/gcc/gcc/intl/dcigettext.c,v
retrieving revision 1.1
diff -u -r1.1 dcigettext.c
--- intl/dcigettext.c	4 Jul 2003 18:18:54 -0000	1.1
+++ intl/dcigettext.c	5 Oct 2003 13:04:16 -0000
@@ -148,7 +148,9 @@
 char *getwd ();
 #  define getcwd(buf, max) getwd (buf)
 # else
+#   if !defined getcwd
 char *getcwd ();
+#   endif
 # endif
 # ifndef HAVE_STPCPY
 static char *stpcpy PARAMS ((char *dest, const char *src));
Index: libiberty/Makefile.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/Makefile.in,v
retrieving revision 1.93
diff -u -r1.93 Makefile.in
--- libiberty/Makefile.in	22 Jun 2003 15:59:49 -0000	1.93
+++ libiberty/Makefile.in	5 Oct 2003 13:04:18 -0000
@@ -143,7 +143,7 @@
 	 mempcpy.c memset.c mkstemps.c					\
 	objalloc.c obstack.c						\
 	partition.c							\
-	 pex-djgpp.c pex-mpw.c pex-msdos.c pex-os2.c			\
+	 pex-amigaos.c pex-djgpp.c pex-mpw.c pex-msdos.c pex-os2.c	\
 	 pex-unix.c pex-win32.c						\
          physmem.c putenv.c						\
 	random.c regex.c rename.c rindex.c				\
@@ -187,7 +187,7 @@
 	getcwd.o getpagesize.o						\
 	index.o insque.o						\
 	memchr.o memcmp.o memcpy.o memmove.o mempcpy.o memset.o mkstemps.o \
-	pex-djgpp.o pex-mpw.o pex-msdos.o pex-os2.o			\
+	pex-amigaos.o pex-djgpp.o pex-mpw.o pex-msdos.o pex-os2.o	\
 	 pex-unix.o pex-win32.o						\
 	 putenv.o							\
 	random.o rename.o rindex.o					\
@@ -467,6 +467,8 @@
 obstack.o: config.h $(INCDIR)/obstack.h
 partition.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
 	$(INCDIR)/partition.h
+pex-amigaos.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
+	$(srcdir)/pex-common.h
 pex-djgpp.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
 	$(srcdir)/pex-common.h
 pex-mpw.o: config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h \
Index: libiberty/basename.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/basename.c,v
retrieving revision 1.6
diff -u -r1.6 basename.c
--- libiberty/basename.c	26 Sep 2001 18:16:17 -0000	1.6
+++ libiberty/basename.c	5 Oct 2003 13:04:18 -0000
@@ -28,6 +28,12 @@
 #endif
 #endif
 
+#ifdef __amigaos__
+#  ifndef DIR_SEPARATOR_2 
+#    define DIR_SEPARATOR_2 ':'
+#  endif
+#endif
+
 /* Define IS_DIR_SEPARATOR.  */
 #ifndef DIR_SEPARATOR_2
 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
Index: libiberty/configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/configure.in,v
retrieving revision 1.73
diff -u -r1.73 configure.in
--- libiberty/configure.in	1 Oct 2003 17:11:29 -0000	1.73
+++ libiberty/configure.in	5 Oct 2003 13:04:21 -0000
@@ -481,6 +481,7 @@
      *-*-msdosdjgpp*)		pexecute=pex-djgpp.o  ;;
      *-*-msdos*)		pexecute=pex-msdos.o  ;;
      *-*-os2-emx*)		pexecute=pex-os2.o    ;;
+     *-*-amigaos*)		pexecute=pex-amigaos.o;;
      *)				pexecute=pex-unix.o   ;;
 esac
 AC_SUBST(pexecute)
Index: libiberty/lbasename.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/lbasename.c,v
retrieving revision 1.4
diff -u -r1.4 lbasename.c
--- libiberty/lbasename.c	18 Jun 2002 02:04:33 -0000	1.4
+++ libiberty/lbasename.c	5 Oct 2003 13:04:21 -0000
@@ -53,6 +53,12 @@
 #  endif
 #endif
 
+#ifdef __amigaos__
+#  ifndef DIR_SEPARATOR_2 
+#    define DIR_SEPARATOR_2 ':'
+#  endif
+#endif
+
 #ifndef DIR_SEPARATOR_2
 #  define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
 #else
Index: libiberty/lrealpath.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/lrealpath.c,v
retrieving revision 1.1
diff -u -r1.1 lrealpath.c
--- libiberty/lrealpath.c	20 Feb 2003 22:11:13 -0000	1.1
+++ libiberty/lrealpath.c	5 Oct 2003 13:04:21 -0000
@@ -49,6 +49,7 @@
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
+#include <stdio.h> /* for MAXPATHLEN */
 
 /* On GNU libc systems the declaration is only visible with _GNU_SOURCE.  */
 #if defined(HAVE_CANONICALIZE_FILE_NAME) \
@@ -121,6 +122,16 @@
 	return ret;
       }
   }
+#endif
+
+#ifdef __amigaos__
+  /* Special case for AmigaOS 4:
+     Here readlink actually works as a realpath, so try using it. */
+  {
+    char buf[MAXPATHLEN];
+    if (readlink (filename, buf, sizeof buf) >= 0)
+      return strdup (buf);
+  }  
 #endif
 
   /* This system is a lost cause, just duplicate the filename.  */
Index: libiberty/make-relative-prefix.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/make-relative-prefix.c,v
retrieving revision 1.4
diff -u -r1.4 make-relative-prefix.c
--- libiberty/make-relative-prefix.c	20 Feb 2003 22:10:58 -0000	1.4
+++ libiberty/make-relative-prefix.c	5 Oct 2003 13:04:21 -0000
@@ -82,8 +82,14 @@
 #    define DIR_SEPARATOR_2 '\\'
 #  endif
 #  define PATH_SEPARATOR ';'
-#else
-#  define PATH_SEPARATOR ':'
+#endif
+
+#ifdef __amigaos__
+#  ifndef DIR_SEPARATOR_2 
+#    define DIR_SEPARATOR_2 ':'
+#  endif
+#  define PATH_SEPARATOR '|'
+#  define DIR_UP ""
 #endif
 
 #ifndef DIR_SEPARATOR_2
@@ -93,7 +99,13 @@
 	(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
 #endif
 
-#define DIR_UP ".."
+#ifndef PATH_SEPARATOR
+#  define PATH_SEPARATOR ':'
+#endif
+
+#ifndef DIR_UP
+#  define DIR_UP ".."
+#endif
 
 static char *save_string PARAMS ((const char *, int));
 static char **split_directories	PARAMS ((const char *, int *));
@@ -241,6 +253,7 @@
      of the directories specified in the PATH environment variable.  */
   if (lbasename (progname) == progname)
     {
+#ifndef __amigaos__
       char *temp;
 
       temp = getenv ("PATH");
@@ -294,6 +307,13 @@
 		endp++;
 	    }
 	}
+#else /* __amigaos__ */
+      /* On AmigaOS there is PROGDIR:, so no need to look... */
+      char * nstore = (char *) alloca (strlen (progname) + 9);
+      strcpy (nstore, "PROGDIR:");
+      strcat (nstore, progname);
+      progname = nstore;
+#endif /* __amigaos__ */
     }
 
   full_progname = lrealpath (progname);
Index: libiberty/make-temp-file.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libiberty/make-temp-file.c,v
retrieving revision 1.5
diff -u -r1.5 make-temp-file.c
--- libiberty/make-temp-file.c	17 Oct 2001 21:15:41 -0000	1.5
+++ libiberty/make-temp-file.c	5 Oct 2003 13:04:21 -0000
@@ -75,11 +75,15 @@
   return 0;
 }
 
+#ifndef __amigaos__
 static const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
 static const char usrtmp[] =
 { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
 static const char vartmp[] =
 { DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
+#else /* __amigaos__ */
+static const char t[] = { 'T', ':', 0 };
+#endif /* __amigaos__ */
 
 static char *memoized_tmpdir;
 
@@ -112,10 +116,15 @@
   base = try (P_tmpdir, base);
 #endif
 
+#ifndef __amigaos__
   /* Try /var/tmp, /usr/tmp, then /tmp.  */
   base = try (vartmp, base);
   base = try (usrtmp, base);
   base = try (tmp, base);
+#else /* __amigaos__ */
+  /* Try T: */
+  base = try (t, base);
+#endif /* __amigaos__ */
  
   /* If all else fails, use the current directory!  */
   if (base == 0)
@@ -126,6 +135,13 @@
   len = strlen (base);
   tmpdir = xmalloc (len + 2);
   strcpy (tmpdir, base);
+#ifdef __amigaos__
+  /* On AmigaOS, don't add DIR_SEPARATOR if base already
+     ends with / or :, since that would mean parent directory */
+  if (base[len-1] == DIR_SEPARATOR || base[len-1] == ':')
+    tmpdir[len] = '\0';
+  else
+#endif
   tmpdir[len] = DIR_SEPARATOR;
   tmpdir[len+1] = '\0';
 
Index: gcc/config/rs6000/x-amigaos
===================================================================
diff -u /dev/null gcc/config/rs6000/x-amigaos
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ gcc/config/rs6000/x-amigaos	Sat Oct  4 19:13:23 2003
@@ -0,0 +1 @@
+override LIBS = $(LIBIBERTY) $(LIBINTL) $(LIBICONV) -lunix
Index: libiberty/pex-amigaos.c
===================================================================
diff -u /dev/null libiberty/pex-amigaos.c
--- /dev/null	Sun Oct  5 15:28:39 2003
+++ libiberty/pex-amigaos.c	Mon Sep 15 21:26:06 2003
@@ -0,0 +1,153 @@
+/* Utilities to execute a program in a subprocess (possibly linked by pipes
+   with other subprocesses), and wait for it.  Generic AmigaOS specialization.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
+   Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include "pex-common.h"
+
+#include <stdio.h>
+#include <errno.h>
+#ifdef NEED_DECLARATION_ERRNO
+extern int errno;
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/* For communicating information from pexecute to pwait.  */
+static int last_pid = 0;
+static int last_status = 0;
+static int last_reaped = 0;
+
+int
+pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
+     const char *program;
+     char * const *argv;
+     const char *this_pname;
+     const char *temp_base;
+     char **errmsg_fmt, **errmsg_arg;
+     int flags;
+{
+  int rc;
+  char *scmd,*s;
+  int i,j,c,len,arglen;
+  int need_quote;
+
+  last_pid++;
+  if (last_pid < 0)
+    last_pid = 1;
+
+  if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
+    abort ();
+
+  len = 0;
+
+  for(i = 0 ; argv[i] != NULL ; i++)
+  {
+    arglen = strlen(argv[i]);
+
+    len += 1 + arglen;
+
+    for(j = 0, need_quote = 0 ; j < arglen ; j++)
+    {
+      c = argv[i][j];
+
+      if(isspace(c))
+        need_quote = 1;
+      else if (c == '\"')
+        len++;
+    }
+
+    if(need_quote)
+      len += 2;
+  }
+
+  s = scmd = (char *) xmalloc (len+1);
+
+  for(i = 0 ; argv[i] != NULL ; i++)
+  {
+    arglen = strlen(argv[i]);
+
+    for(j = 0, need_quote = 0 ; j < arglen ; j++)
+    {
+      if(isspace(argv[i][j]))
+        need_quote = 1;
+    }
+
+    if(s != scmd)
+      (*s++) = ' ';
+
+    if(need_quote)
+      (*s++) = '\"';
+
+    for(j = 0 ; j < arglen ; j++)
+    {
+      c = argv[i][j];
+      if(c == '\"')
+        (*s++) = '*';
+
+      (*s++) = c;
+    }
+
+    if(need_quote)
+      (*s++) = '\"';
+  }
+
+  (*s) = '\0';
+
+  rc = system (scmd);
+
+  free (scmd);
+
+  if (rc == -1)
+    {
+      *errmsg_fmt = install_error_msg;
+      *errmsg_arg = program;
+      return -1;
+    }
+
+  /* Tuck the status away for pwait, and return a "pid".  */
+  last_status = rc << 8;
+  return last_pid;
+}
+
+int
+pwait (pid, status, flags)
+     int pid;
+     int *status;
+     int flags;
+{
+  /* On AmigaOS each pexecute must be followed by it's associated pwait.  */
+  if (pid != last_pid
+      /* Called twice for the same child?  */
+      || pid == last_reaped)
+    {
+      /* ??? ECHILD would be a better choice.  Can we use it here?  */
+      errno = EINVAL;
+      return -1;
+    }
+  /* ??? Here's an opportunity to canonicalize the values in STATUS.
+     Needed?  */
+  *status = last_status;
+  last_reaped = last_pid;
+  return last_pid;
+}
Index: gcc/collect2.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/collect2.c,v
retrieving revision 1.153
diff -u -r1.153 collect2.c
--- gcc/collect2.c	19 Jul 2003 14:47:00 -0000	1.153
+++ gcc/collect2.c	5 Oct 2003 13:03:18 -0000
@@ -909,6 +925,10 @@
   /* Extract COMPILER_PATH and PATH into our prefix list.  */
   prefix_from_env ("COMPILER_PATH", &cpath);
   prefix_from_env ("PATH", &path);
+#ifdef __amigaos__
+  /* AmigaOS doesn't use $PATH, but binutils can be found here: */
+  add_prefix (&path, "gcc:bin/");
+#endif
 
   /* Try to discover a valid linker/nm/strip to use.  */
 
@@ -1985,6 +2011,10 @@
   int pipe_fd[2];
   char *p, buf[1024];
   FILE *inf;
+#ifdef __amigaos__
+  char *scmd,*s;
+  int i, j,len,arglen,c,need_quote;
+#endif
 
   if (which_pass == PASS_SECOND)
     return;
@@ -2000,12 +2030,69 @@
   nm_argv[argc++] = prog_name;
   nm_argv[argc++] = (char *) 0;
 
+#ifndef __amigaos__
   if (pipe (pipe_fd) < 0)
     fatal_perror ("pipe");
 
   inf = fdopen (pipe_fd[0], "r");
   if (inf == (FILE *) 0)
     fatal_perror ("fdopen");
+#else /* __amigaos__ */
+  len = 0;
+
+  for(i = 0 ; nm_argv[i] != NULL ; i++)
+  {
+    arglen = strlen(nm_argv[i]);
+
+    len += 1 + arglen;
+
+    for(j = 0, need_quote = 0 ; j < arglen ; j++)
+    {
+      c = nm_argv[i][j];
+
+      if(c == ' ')
+        need_quote = 1;
+      else if (c == '\"')
+        len++;
+    }
+
+    if(need_quote)
+      len += 2;
+  }
+
+  s = scmd = (char *) xmalloc (len+1);
+
+  for(i = 0 ; nm_argv[i] != NULL ; i++)
+  {
+    arglen = strlen(nm_argv[i]);
+
+    for(j = 0, need_quote = 0 ; j < arglen ; j++)
+    {
+      if(nm_argv[i][j] == ' ')
+        need_quote = 1;
+    }
+
+    if(s != scmd)
+      (*s++) = ' ';
+
+    if(need_quote)
+      (*s++) = '\"';
+
+    for(j = 0 ; j < arglen ; j++)
+    {
+      c = nm_argv[i][j];
+      if(c == '\"')
+        (*s++) = '*';
+
+      (*s++) = c;
+    }
+
+    if(need_quote)
+      (*s++) = '\"';
+  }
+
+  (*s) = '\0';
+#endif /* __amigaos__ */
 
   /* Trace if needed.  */
   if (vflag)
@@ -2022,6 +2109,7 @@
   fflush (stdout);
   fflush (stderr);
 
+#ifndef __amigaos__
   /* Spawn child nm on pipe.  */
   pid = vfork ();
   if (pid == -1)
@@ -2051,6 +2139,13 @@
 
   if (close (pipe_fd[1]) < 0)
     fatal_perror ("close %d", pipe_fd[1]);
+#else /* __amigaos__ */
+  inf = popen (scmd, "r");
+  if (inf == (FILE *) NULL)
+    fatal_perror ("popen");
+
+  free (scmd);
+#endif /* __amigaos__ */
 
   if (debug)
     fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -2127,12 +2239,14 @@
   if (fclose (inf) != 0)
     fatal_perror ("fclose");
 
+#ifndef __amigaos__
   do_wait (nm_file_name);
 
   signal (SIGINT,  int_handler);
 #ifdef SIGQUIT
   signal (SIGQUIT, quit_handler);
 #endif
+#endif
 }
 
 #if SUNOS4_SHARED_LIBRARIES

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]