#! /bin/sh -e

# Description: GNU/k*BSD support
# Author: Robert Millan <robertmh@gnu.org>
# Status: libtool bits are merged in upstream 3.5 branch, rest is pending.

dir=
if [ $# -eq 3 -a "$2" = '-d' ]; then
    pdir="-d $3"
    dir="$3/"
elif [ $# -ne 1 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch)
        patch $pdir -f --no-backup-if-mismatch -p1 < $0
	for i in libffi libf2c libjava/libltdl libobjc libstdc++-v3 zlib; do
		(set -x ; cd ${dir}/${i} ; autoreconf --force)
	done
        ;;
    -unpatch)
        patch $pdir -f --no-backup-if-mismatch -R -p1 < $0
        ;;
    *)
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
esac
exit 0

# append the patch here and adjust the -p? flag in the patch calls.

diff -Nur src.old/gcc/config/i386/kfreebsd-gnu.h src/gcc/config/i386/kfreebsd-gnu.h
--- src.old/gcc/config/i386/kfreebsd-gnu.h	1970-01-01 01:00:00.000000000 +0100
+++ src/gcc/config/i386/kfreebsd-gnu.h	2004-05-22 02:37:45.000000000 +0200
@@ -0,0 +1,26 @@
+/* Definitions for Intel 386 running kFreeBSD-based GNU systems with ELF format
+   Copyright (C) 2004
+   Free Software Foundation, Inc.
+   Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#undef LINK_EMULATION
+#define LINK_EMULATION "elf_i386_fbsd"
+#undef REG_NAME
+#define REG_NAME(reg) sc_ ## reg
diff -Nur src.old/gcc/config/i386/knetbsd-gnu.h src/gcc/config/i386/knetbsd-gnu.h
--- src.old/gcc/config/i386/knetbsd-gnu.h	1970-01-01 01:00:00.000000000 +0100
+++ src/gcc/config/i386/knetbsd-gnu.h	2004-05-22 02:37:45.000000000 +0200
@@ -0,0 +1,24 @@
+/* Definitions for Intel 386 running kNetBSD-based GNU systems with ELF format
+   Copyright (C) 2004
+   Free Software Foundation, Inc.
+   Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#undef REG_NAME
+#define REG_NAME(reg) sc_ ## reg
diff -Nur src.old/gcc/config/i386/linux.h src/gcc/config/i386/linux.h
--- src.old/gcc/config/i386/linux.h	2003-11-29 04:08:10.000000000 +0100
+++ src/gcc/config/i386/linux.h	2004-05-22 02:37:45.000000000 +0200
@@ -108,24 +108,30 @@
 
 /* If ELF is the default format, we should not use /lib/elf.  */
 
+#ifndef LINK_EMULATION
+# define LINK_EMULATION "elf_i386"
+#endif
+#ifndef DYNAMIC_LINKER
+# ifdef USE_GNULIBC_1
+#  define DYNAMIC_LINKER "/lib/ld-linux.so.1"
+# else
+#  define DYNAMIC_LINKER "/lib/ld-linux.so.2"
+# endif
+#endif
+
+#undef  SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+  { "link_emulation", LINK_EMULATION },\
+  { "dynamic_linker", DYNAMIC_LINKER }
+
 #undef	LINK_SPEC
-#ifdef USE_GNULIBC_1
-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
-  %{!shared: \
-    %{!ibcs: \
-      %{!static: \
-	%{rdynamic:-export-dynamic} \
-	%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
-	%{static:-static}}}"
-#else
-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+#define LINK_SPEC "-m %(link_emulation) %{shared:-shared} \
   %{!shared: \
     %{!ibcs: \
       %{!static: \
 	%{rdynamic:-export-dynamic} \
-	%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+	%{!dynamic-linker:-dynamic-linker %(dynamic_linker)}} \
 	%{static:-static}}}"
-#endif
 
 /* A C statement (sans semicolon) to output to the stdio stream
    FILE the assembler definition of uninitialized global DECL named
@@ -217,6 +223,8 @@
 #include <signal.h>
 #include <sys/ucontext.h>
 
+#define REG_NAME(reg) reg
+
 #define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
   do {									\
     unsigned char *pc_ = (CONTEXT)->ra;					\
@@ -245,28 +253,28 @@
     else								\
       break;								\
 									\
-    new_cfa_ = sc_->esp;						\
+    new_cfa_ = sc_->REG_NAME(esp);						\
     (FS)->cfa_how = CFA_REG_OFFSET;					\
     (FS)->cfa_reg = 4;							\
     (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa;		\
 									\
     /* The SVR4 register numbering macros aren't usable in libgcc.  */	\
     (FS)->regs.reg[0].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[0].loc.offset = (long)&sc_->eax - new_cfa_;		\
+    (FS)->regs.reg[0].loc.offset = (long)&sc_->REG_NAME(eax) - new_cfa_;	\
     (FS)->regs.reg[3].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[3].loc.offset = (long)&sc_->ebx - new_cfa_;		\
+    (FS)->regs.reg[3].loc.offset = (long)&sc_->REG_NAME(ebx) - new_cfa_;	\
     (FS)->regs.reg[1].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[1].loc.offset = (long)&sc_->ecx - new_cfa_;		\
+    (FS)->regs.reg[1].loc.offset = (long)&sc_->REG_NAME(ecx) - new_cfa_;	\
     (FS)->regs.reg[2].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[2].loc.offset = (long)&sc_->edx - new_cfa_;		\
+    (FS)->regs.reg[2].loc.offset = (long)&sc_->REG_NAME(edx) - new_cfa_;	\
     (FS)->regs.reg[6].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[6].loc.offset = (long)&sc_->esi - new_cfa_;		\
+    (FS)->regs.reg[6].loc.offset = (long)&sc_->REG_NAME(esi) - new_cfa_;	\
     (FS)->regs.reg[7].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[7].loc.offset = (long)&sc_->edi - new_cfa_;		\
+    (FS)->regs.reg[7].loc.offset = (long)&sc_->REG_NAME(edi) - new_cfa_;	\
     (FS)->regs.reg[5].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[5].loc.offset = (long)&sc_->ebp - new_cfa_;		\
+    (FS)->regs.reg[5].loc.offset = (long)&sc_->REG_NAME(ebp) - new_cfa_;	\
     (FS)->regs.reg[8].how = REG_SAVED_OFFSET;				\
-    (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_;		\
+    (FS)->regs.reg[8].loc.offset = (long)&sc_->REG_NAME(eip) - new_cfa_;	\
     (FS)->retaddr_column = 8;						\
     goto SUCCESS;							\
   } while (0)
diff -Nur src.old/gcc/config/kfreebsd-gnu.h src/gcc/config/kfreebsd-gnu.h
--- src.old/gcc/config/kfreebsd-gnu.h	1970-01-01 01:00:00.000000000 +0100
+++ src/gcc/config/kfreebsd-gnu.h	2004-05-22 02:37:45.000000000 +0200
@@ -0,0 +1,36 @@
+/* Definitions for kFreeBSD-based GNU systems with ELF format
+   Copyright (C) 2004
+   Free Software Foundation, Inc.
+   Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#undef LINUX_TARGET_OS_CPP_BUILTINS    
+#define LINUX_TARGET_OS_CPP_BUILTINS()		\
+  do						\
+    {						\
+	builtin_define ("__FreeBSD_kernel__");	\
+	builtin_define ("__GLIBC__");		\
+	builtin_define_std ("unix");		\
+	builtin_assert ("system=unix");		\
+	builtin_assert ("system=posix");	\
+    }						\
+  while (0)
+
+#undef DYNAMIC_LINKER
+#define DYNAMIC_LINKER "/lib/ld.so.1"
diff -Nur src.old/gcc/config/knetbsd-gnu.h src/gcc/config/knetbsd-gnu.h
--- src.old/gcc/config/knetbsd-gnu.h	1970-01-01 01:00:00.000000000 +0100
+++ src/gcc/config/knetbsd-gnu.h	2004-05-22 02:37:45.000000000 +0200
@@ -0,0 +1,36 @@
+/* Definitions for kNetBSD-based GNU systems with ELF format
+   Copyright (C) 2004
+   Free Software Foundation, Inc.
+   Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#undef LINUX_TARGET_OS_CPP_BUILTINS    
+#define LINUX_TARGET_OS_CPP_BUILTINS()		\
+  do						\
+    {						\
+	builtin_define ("__NetBSD_kernel__");	\
+	builtin_define ("__GLIBC__");		\
+	builtin_define_std ("unix");		\
+	builtin_assert ("system=unix");		\
+	builtin_assert ("system=posix");	\
+    }						\
+  while (0)
+
+#undef DYNAMIC_LINKER
+#define DYNAMIC_LINKER "/lib/ld.so.1"
diff -Nur src.old/gcc/config/linux.h src/gcc/config/linux.h
--- src.old/gcc/config/linux.h	2003-11-29 04:08:10.000000000 +0100
+++ src/gcc/config/linux.h	2004-05-22 02:37:45.000000000 +0200
@@ -97,6 +97,7 @@
        %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}"
 #endif
 
+#ifndef LINUX_TARGET_OS_CPP_BUILTINS
 #define LINUX_TARGET_OS_CPP_BUILTINS()				\
     do {							\
 	builtin_define ("__gnu_linux__");			\
@@ -106,6 +107,7 @@
 	builtin_assert ("system=unix");				\
 	builtin_assert ("system=posix");			\
     } while (0)
+#endif
 
 #if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR)
 #define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
diff -Nur src.old/gcc/config.gcc src/gcc/config.gcc
--- src.old/gcc/config.gcc	2004-05-22 01:09:22.000000000 +0200
+++ src/gcc/config.gcc	2004-05-22 02:41:54.000000000 +0200
@@ -428,21 +428,10 @@
   esac
   fbsd_tm_file="${fbsd_tm_file} freebsd-spec.h freebsd.h"
   ;;
-*-*-kfreebsd*-gnu)
-  # Must come before *-*-gnu*
-  xm_defines=POSIX # needed for cross-compiling from FreeBSD?
-  extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
-  # GNU tools are the only tools.
-  gas=yes
-  gnu_ld=yes
-  case ${enable_threads} in
-    "" | yes | posix) thread_file='posix' ;;
-  esac
-  ;;
 *-*-linux*libc1* | *-*-linux*aout*)
   # Avoid the generic linux case.
   ;;
-*-*-linux*)
+*-*-linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu)
   # Must come before *-*-gnu* (because of *-*-linux-gnu* systems).
   extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
   gas=yes
@@ -988,23 +977,21 @@
 		thread_file='single'
 	fi
 	;;
-i[34567]86-*-linux*)	# Intel 80386's running GNU/Linux
+i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu)
+			# Intel 80386's running GNU/*
 			# with ELF format using glibc 2
-			# aka GNU/Linux C library 6
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
 	tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff"
+	case ${target} in
+	i[34567]86-*-knetbsd*-gnu) tm_file="${tm_file} knetbsd-gnu.h i386/knetbsd-gnu.h" ;;
+	i[34567]86-*-kfreebsd*-gnu) tm_file="${tm_file} kfreebsd-gnu.h i386/kfreebsd-gnu.h" ;;
+	esac
 	;;
 x86_64-*-linux*)
 	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h \
 		 i386/x86-64.h i386/linux64.h"
 	tmake_file="t-slibgcc-elf-ver t-linux i386/t-linux64"
 	;;
-i[34567]86-*-kfreebsd*-gnu) # must be before i[34567]86-*-gnu*
-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h kfreebsdgnu.h i386/kfreebsdgnu.h"
-	tmake_file="t-slibgcc-elf-ver t-kfreebsd-gnu i386/t-crtstuff"
-	float_format=i386
-	use_fixproto=no
-	;;
 i[34567]86-*-gnu*)
 	;;
 i[34567]86-pc-msdosdjgpp*)
diff -Nur src.old/libtool.m4 src/libtool.m4
--- src.old/libtool.m4	2003-11-19 06:29:32.000000000 +0100
+++ src/libtool.m4	2004-05-22 02:37:46.000000000 +0200
@@ -621,7 +621,7 @@
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-freebsd* )
+freebsd* | kfreebsd*-gnu)
   if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
     case $host_cpu in
     i*86 )
@@ -689,7 +689,7 @@
   lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
   ;;
 
-netbsd*)
+netbsd* | knetbsd*-gnu)
   if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
     [lt_cv_deplibs_check_method='match_pattern /lib[^/\.]+\.so\.[0-9]+\.[0-9]+$']
   else
diff -Nur src.old/ltcf-c.sh src/ltcf-c.sh
--- src.old/ltcf-c.sh	2003-11-19 06:29:32.000000000 +0100
+++ src/ltcf-c.sh	2004-05-22 02:37:46.000000000 +0200
@@ -175,7 +175,7 @@
       $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
     ;;
 
-  netbsd*)
+  netbsd* | knetbsd*-gnu)
     if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
       wlarc=
@@ -442,7 +442,7 @@
     ;;
 
   # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
+  freebsd* | kfreebsd*-gnu)
     archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
     hardcode_libdir_flag_spec='-R$libdir'
     hardcode_direct=yes
@@ -489,7 +489,7 @@
     link_all_deplibs=yes
     ;;
 
-  netbsd*)
+  netbsd* | knetbsd*-gnu)
     if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
     else
diff -Nur src.old/ltcf-cxx.sh src/ltcf-cxx.sh
--- src.old/ltcf-cxx.sh	2003-11-19 06:29:32.000000000 +0100
+++ src/ltcf-cxx.sh	2004-05-22 02:37:46.000000000 +0200
@@ -289,7 +289,7 @@
     # C++ shared libraries reported to be fairly broken before switch to ELF
     ld_shlibs=no
     ;;
-  freebsd*)
+  freebsd* | kfreebsd*-gnu)
     # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
     # conventions
     ld_shlibs=yes
@@ -449,7 +449,7 @@
         ;;
     esac
     ;;
-  netbsd*)
+  netbsd* | knetbsd*-gnu)
     # NetBSD uses g++ - do we need to do anything?
     ;;
   osf3*)
@@ -804,7 +804,7 @@
           ;;
       esac
       ;;
-    freebsd*)
+    freebsd* | kfreebsd*-gnu)
       # FreeBSD uses GNU C++
       ;;
     gnu*)
diff -Nur src.old/ltcf-gcj.sh src/ltcf-gcj.sh
--- src.old/ltcf-gcj.sh	2003-11-19 06:29:32.000000000 +0100
+++ src/ltcf-gcj.sh	2004-05-22 02:37:46.000000000 +0200
@@ -178,7 +178,7 @@
       $CC $output_objdir/$soname-exp '$lt_cv_cc_dll_switch' -Wl,-e,'$dll_entry' -o $output_objdir/$soname '$ltdll_obj'$libobjs $deplibs $compiler_flags'
     ;;
 
-  netbsd*)
+  netbsd* | knetbsd*-gnu)
     if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
       wlarc=
@@ -445,7 +445,7 @@
     ;;
 
   # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
+  freebsd* | kfreebsd*-gnu)
     archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
     hardcode_libdir_flag_spec='-R$libdir'
     hardcode_direct=yes
@@ -476,7 +476,7 @@
     link_all_deplibs=yes
     ;;
 
-  netbsd*)
+  netbsd* | knetbsd*-gnu)
     if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
     else
diff -Nur src.old/ltconfig src/ltconfig
--- src.old/ltconfig	2004-03-05 22:05:41.000000000 +0100
+++ src/ltconfig	2004-05-22 02:37:46.000000000 +0200
@@ -1168,6 +1168,17 @@
   hardcode_into_libs=yes
   ;;
 
+kfreebsd*-gnu | knetbsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+  soname_spec='${libname}${release}.so$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
 hpux9* | hpux10* | hpux11*)
   # Give a soname corresponding to the major version so that dld.sl refuses to
   # link against other versions.
