From 62ed086ee059b4926f2de439d241f8ee2ab72ff6 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Thu, 10 Apr 2014 16:03:33 +0000
Subject: initial Haiku patch


diff --git a/Include/pyport.h b/Include/pyport.h
index 6ab0ae4..ad8c45c 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -850,7 +850,7 @@ extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
 #  define _Py_FORCE_UTF8_LOCALE
 #endif
 
-#if defined(_Py_FORCE_UTF8_LOCALE) || defined(__APPLE__)
+#if defined(_Py_FORCE_UTF8_LOCALE) || defined(__APPLE__) || defined(__HAIKU__)
    // Use UTF-8 as the filesystem encoding.
    // See PyUnicode_DecodeFSDefaultAndSize(), PyUnicode_EncodeFSDefault(),
    // Py_DecodeLocale() and Py_EncodeLocale().
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
index 01d5331..b109392 100644
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
@@ -33,13 +33,15 @@ SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
 # alter locations for packages installations in a single place.
 # Note that this module is deprecated (PEP 632); all consumers
 # of this information should switch to using sysconfig directly.
-INSTALL_SCHEMES = {"unix_prefix": {}, "unix_home": {}, "nt": {}}
+INSTALL_SCHEMES = {"unix_prefix": {}, "unix_home": {}, "nt": {},
+    "haiku": {}, "haiku_vendor": {}, "haiku_home": {}}
 
 # Copy from sysconfig._INSTALL_SCHEMES
 for key in SCHEME_KEYS:
     for distutils_scheme_name, sys_scheme_name in (
             ("unix_prefix", "posix_prefix"), ("unix_home", "posix_home"),
-            ("nt", "nt")):
+            ("nt", "nt"), ("haiku", "haiku"), ("haiku_vendor", "haiku_vendor"),
+            ("haiku_home", "haiku_home")):
         sys_key = key
         sys_scheme = sysconfig._INSTALL_SCHEMES[sys_scheme_name]
         if key == "headers" and key not in sys_scheme:
@@ -86,6 +88,13 @@ if HAS_USER_SITE:
         'data'   : '$userbase',
         }
 
+    INSTALL_SCHEMES['haiku_user'] = {
+        'purelib': '$usersite',
+        'platlib': '$usersite',
+        'headers': '$userbase/develop/headers/python$py_version_short/$dist_name',
+        'scripts': '$userbase/bin',
+        'data'   : '$userbase',
+        }
 
 class install(Command):
 
@@ -431,10 +440,16 @@ class install(Command):
                 raise DistutilsPlatformError(
                     "User base directory is not specified")
             self.install_base = self.install_platbase = self.install_userbase
-            self.select_scheme("unix_user")
+            if sys.platform.startswith('haiku'):
+                self.select_scheme("haiku_user")
+            else:
+                self.select_scheme("unix_user")
         elif self.home is not None:
             self.install_base = self.install_platbase = self.home
-            self.select_scheme("unix_home")
+            if sys.platform.startswith('haiku'):
+                self.select_scheme("haiku_home")
+            else:
+                self.select_scheme("unix_home")
         else:
             if self.prefix is None:
                 if self.exec_prefix is not None:
@@ -450,7 +465,13 @@ class install(Command):
 
             self.install_base = self.prefix
             self.install_platbase = self.exec_prefix
-            self.select_scheme("unix_prefix")
+            if sys.platform.startswith('haiku'):
+                if os.environ.get('HAIKU_USE_VENDOR_DIRECTORIES') == '1':
+                    self.select_scheme("haiku_vendor")
+                else:
+                    self.select_scheme("haiku")
+            else:
+                self.select_scheme("unix_prefix")
 
     def finalize_other(self):
         """Finalizes options for non-posix platforms"""
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index 3414a76..9115cdc 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -292,7 +292,8 @@ def get_python_inc(plat_specific=0, prefix=None):
                 incdir = os.path.join(get_config_var('srcdir'), 'Include')
                 return os.path.normpath(incdir)
         python_dir = 'python' + get_python_version() + build_flags
-        return os.path.join(prefix, "include", python_dir)
+        inc_dir = "include" if sys.platform != "haiku1" else "develop/headers"
+        return os.path.join(prefix, inc_dir, python_dir)
     elif os.name == "nt":
         if python_build:
             # Include both the include and PC dir to ensure we can find
@@ -327,19 +328,27 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
             prefix = plat_specific and EXEC_PREFIX or PREFIX
 
     if os.name == "posix":
-        if plat_specific or standard_lib:
-            # Platform-specific modules (any module from a non-pure-Python
-            # module distribution) or standard Python library modules.
-            libdir = sys.platlibdir
+        if sys.platform.startswith('haiku'):
+            if standard_lib:
+                return os.path.join(prefix,
+                                    "lib", "python" + get_python_version())
+            return os.path.join(prefix, "non-packaged",
+                                "lib", "python" + get_python_version(),
+                                "site-packages")
         else:
-            # Pure Python
-            libdir = "lib"
-        libpython = os.path.join(prefix, libdir,
-                                 "python" + get_python_version())
-        if standard_lib:
-            return libpython
-        else:
-            return os.path.join(libpython, "site-packages")
+            if plat_specific or standard_lib:
+                # Platform-specific modules (any module from a non-pure-Python
+                # module distribution) or standard Python library modules.
+                libdir = sys.platlibdir
+
+                # Pure Python
+                libdir = "lib"
+            libpython = os.path.join(prefix, libdir,
+                                     "python" + get_python_version())
+            if standard_lib:
+                return libpython
+            else:
+                return os.path.join(libpython, "site-packages")
     elif os.name == "nt":
         if standard_lib:
             return os.path.join(prefix, "Lib")
diff --git a/Lib/plat-haiku1/regen b/Lib/plat-haiku1/regen
new file mode 100644
index 0000000..4372ee2
--- /dev/null
+++ b/Lib/plat-haiku1/regen
@@ -0,0 +1,4 @@
+#! /bin/sh
+HEADERS=/boot/develop/headers
+set -v
+eval $PYTHON_FOR_BUILD ../../Tools/scripts/h2py.py -i "'(u_long)'" $HEADERS/posix/netinet/in.h
diff --git a/Lib/site.py b/Lib/site.py
index 939893e..51f375e 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -281,6 +281,14 @@ def _getuserbase():
         return joinuser("~", "Library", sys._framework,
                         "%d.%d" % sys.version_info[:2])
 
+    if sys.platform.startswith('haiku'):
+        try:
+            import subprocess
+            return subprocess.run(['finddir', 'B_USER_NONPACKAGED_DIRECTORY'],
+                stdout=subprocess.PIPE, check=True).stdout.rstrip().decode('utf-8')
+        except:
+            pass
+
     return joinuser("~", ".local")
 
 
@@ -365,7 +373,14 @@ def getsitepackages(prefixes=None):
         if sys.platlibdir != "lib":
             libdirs.append("lib")
 
-        if os.sep == '/':
+        if sys.platform.startswith('haiku'):
+           sitepackages.append(os.path.join(prefix, "non-packaged", "lib",
+                                       "python%d.%d" % sys.version_info[:2],
+                                       "site-packages"))
+           sitepackages.append(os.path.join(prefix, "lib",
+                                       "python%d.%d" % sys.version_info[:2],
+                                       "vendor-packages"))
+        elif os.sep == '/':
             for libdir in libdirs:
                 path = os.path.join(prefix, libdir,
                                     "python%d.%d" % sys.version_info[:2],
@@ -471,8 +486,16 @@ def enablerlcompleter():
             # each interpreter exit when readline was already configured
             # through a PYTHONSTARTUP hook, see:
             # http://bugs.python.org/issue5845#msg198636
-            history = os.path.join(os.path.expanduser('~'),
-                                   '.python_history')
+            import subprocess
+            try:
+                history = os.path.join(subprocess.run(['finddir', 'B_USER_VAR_DIRECTORY'],
+                            check=True, stdout=subprocess.PIPE).stdout.rstrip().decode('utf-8'),
+                            'python', 'history')
+                if not os.path.exists(os.path.dirname(history)):
+                    os.makedirs(os.path.dirname(history))
+            except subprocess.CalledProcessError:
+                history = os.path.join(os.path.expanduser('~'),
+                                       '.python_history')
             try:
                 readline.read_history_file(history)
             except OSError:
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
index daf9f00..4f92119 100644
--- a/Lib/sysconfig.py
+++ b/Lib/sysconfig.py
@@ -56,6 +56,27 @@ _INSTALL_SCHEMES = {
         'scripts': '{base}/Scripts',
         'data': '{base}',
         },
+    'haiku': {
+        'purelib': '{base}/non-packaged/lib/python{py_version_short}/site-packages',
+        'platlib': '{platbase}/non-packaged/lib/python{py_version_short}/site-packages',
+        'headers': '{base}/non-packaged/develop/headers/python{py_version_short}',
+        'scripts': '{base}/non-packaged/bin',
+        'data'   : '{base}/non-packaged',
+        },
+    'haiku_vendor': {
+        'purelib': '{base}/lib/python{py_version_short}/vendor-packages',
+        'platlib': '{platbase}/lib/python{py_version_short}/vendor-packages',
+        'headers': '{base}/develop/headers/python{py_version_short}',
+        'scripts': '{base}/bin',
+        'data'   : '{base}',
+        },
+    'haiku_home': {
+        'purelib': '{base}/lib/python',
+        'platlib': '{base}/lib/python',
+        'headers': '{base}/develop/headers/python/',
+        'scripts': '{base}/bin',
+        'data'   : '{base}',
+        },
     }
 
 
diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
index 4269b0e..314aa75 100644
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -386,6 +386,7 @@ class OtherFileTests:
                     self.assertEqual(f.writable(), True)
                     if sys.platform != "darwin" and \
                        'bsd' not in sys.platform and \
+                       'haiku' not in sys.platform and \
                        not sys.platform.startswith(('sunos', 'aix')):
                         # Somehow /dev/tty appears seekable on some BSDs
                         self.assertEqual(f.seekable(), False)
diff --git a/Makefile.pre.in b/Makefile.pre.in
index ee85f35..445ad51 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -141,7 +141,7 @@ BINDIR=		@bindir@
 LIBDIR=		@libdir@
 MANDIR=		@mandir@
 INCLUDEDIR=	@includedir@
-CONFINCLUDEDIR=	$(exec_prefix)/include
+CONFINCLUDEDIR=	$(INCLUDEDIR)
 PLATLIBDIR=	@PLATLIBDIR@
 SCRIPTDIR=	$(prefix)/$(PLATLIBDIR)
 ABIFLAGS=	@ABIFLAGS@
diff --git a/Modules/resource.c b/Modules/resource.c
index 0d69c29..02f692d 100644
--- a/Modules/resource.c
+++ b/Modules/resource.c
@@ -112,6 +112,7 @@ resource_getrusage_impl(PyObject *module, int who)
                     PyFloat_FromDouble(doubletime(ru.ru_utime)));
     PyStructSequence_SET_ITEM(result, 1,
                     PyFloat_FromDouble(doubletime(ru.ru_stime)));
+#ifndef __HAIKU__
     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
@@ -126,7 +127,22 @@ resource_getrusage_impl(PyObject *module, int who)
     PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
     PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
     PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
-
+#else
+    PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(0));
+    PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(0));
+#endif
     if (PyErr_Occurred()) {
         Py_DECREF(result);
         return NULL;
@@ -376,19 +392,19 @@ resource_exec(PyObject *module)
     }
 
     /* insert constants */
-#ifdef RLIMIT_CPU
+#if !defined(__HAIKU__) && defined(RLIMIT_CPU)
     ADD_INT(module, RLIMIT_CPU);
 #endif
 
-#ifdef RLIMIT_FSIZE
+#if !defined(__HAIKU__) && defined(RLIMIT_FSIZE)
     ADD_INT(module, RLIMIT_FSIZE);
 #endif
 
-#ifdef RLIMIT_DATA
+#if !defined(__HAIKU__) && defined(RLIMIT_DATA)
     ADD_INT(module, RLIMIT_DATA);
 #endif
 
-#ifdef RLIMIT_STACK
+#if !defined(__HAIKU__) && defined(RLIMIT_STACK)
     ADD_INT(module, RLIMIT_STACK);
 #endif
 
@@ -400,31 +416,31 @@ resource_exec(PyObject *module)
     ADD_INT(module, RLIMIT_NOFILE);
 #endif
 
-#ifdef RLIMIT_OFILE
+#if !defined(__HAIKU__) && defined(RLIMIT_OFILE)
     ADD_INT(module, RLIMIT_OFILE);
 #endif
 
-#ifdef RLIMIT_VMEM
+#if !defined(__HAIKU__) && defined(RLIMIT_VMEM)
     ADD_INT(module, RLIMIT_VMEM);
 #endif
 
-#ifdef RLIMIT_AS
+#if !defined(__HAIKU__) && defined(RLIMIT_AS)
     ADD_INT(module, RLIMIT_AS);
 #endif
 
-#ifdef RLIMIT_RSS
+#if !defined(__HAIKU__) && defined(RLIMIT_RSS)
     ADD_INT(module, RLIMIT_RSS);
 #endif
 
-#ifdef RLIMIT_NPROC
+#if !defined(__HAIKU__) && defined(RLIMIT_NPROC)
     ADD_INT(module, RLIMIT_NPROC);
 #endif
 
-#ifdef RLIMIT_MEMLOCK
+#if !defined(__HAIKU__) && defined(RLIMIT_MEMLOCK)
     ADD_INT(module, RLIMIT_MEMLOCK);
 #endif
 
-#ifdef RLIMIT_SBSIZE
+#if !defined(__HAIKU__) && defined(RLIMIT_SBSIZE)
     ADD_INT(module, RLIMIT_SBSIZE);
 #endif
 
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index ab8618b..b2aee8b 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -7464,7 +7464,9 @@ PyInit__socket(void)
     /* SOCK_RAW is marked as optional in the POSIX specification */
     PyModule_AddIntMacro(m, SOCK_RAW);
 #endif
+#ifndef __HAIKU__
     PyModule_AddIntMacro(m, SOCK_SEQPACKET);
+#endif
 #if defined(SOCK_RDM)
     PyModule_AddIntMacro(m, SOCK_RDM);
 #endif
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index e4f375d..ce1bc6b 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -104,6 +104,10 @@ typedef int socklen_t;
 #  undef AF_QIPCRTR
 #endif
 
+#if defined(__HAIKU__)
+#undef HAVE_BLUETOOTH_BLUETOOTH_H
+#endif
+
 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/rfcomm.h>
diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c
index acea306..050a3d0 100644
--- a/Modules/spwdmodule.c
+++ b/Modules/spwdmodule.c
@@ -9,6 +9,7 @@
 #ifdef HAVE_SHADOW_H
 #include <shadow.h>
 #endif
+#include <errno.h>
 
 #include "clinic/spwdmodule.c.h"
 
@@ -148,7 +149,12 @@ spwd_getspnam_impl(PyObject *module, PyObject *arg)
     if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1)
         goto out;
     if ((p = getspnam(name)) == NULL) {
+// Haiku sets ENOENT if invalid user is specified. Ignore it to make KeyError is set.
+#ifdef __HAIKU__
+        if (errno != 0 && errno != ENOENT)
+#else
         if (errno != 0)
+#endif
             PyErr_SetFromErrno(PyExc_OSError);
         else
             PyErr_SetString(PyExc_KeyError, "getspnam(): name not found");
diff --git a/configure.ac b/configure.ac
index 0c06914..d3d980c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1154,6 +1154,16 @@ if test $enable_shared = "yes"; then
 	      PY3LIBRARY=libpython3.so
 	  fi
 	  ;;
+    Haiku*)
+	  LDLIBRARY='libpython$(LDVERSION).so'
+	  BLDLIBRARY='-L. -lpython$(LDVERSION)'
+	  RUNSHARED=LIBRARY_PATH=`pwd`${LIBRARY_PATH:+:${LIBRARY_PATH}}
+	  INSTSONAME="$LDLIBRARY".$SOVERSION
+	  if test "$with_pydebug" != yes
+          then
+	      PY3LIBRARY=libpython3.so
+	  fi
+	  ;;
     hp*|HP*)
 	  case `uname -m` in
 		ia64)
@@ -1229,6 +1239,7 @@ AC_PROG_MKDIR_P
 AC_SUBST(LN)
 if test -z "$LN" ; then
 	case $ac_sys_system in
+		Haiku*) LN="ln -s";;
 		CYGWIN*) LN="ln -s";;
 		*) LN=ln;;
 	esac
@@ -2707,7 +2718,7 @@ then
 			BLDSHARED="$LDSHARED"
 		fi
 		;;
-	Linux*|GNU*|QNX*|VxWorks*)
+	Linux*|GNU*|QNX*|VxWorks*|Haiku*)
 		LDSHARED='$(CC) -shared'
 		LDCXXSHARED='$(CXX) -shared';;
 	FreeBSD*)
@@ -2774,7 +2785,7 @@ then
 		 else CCSHARED="+z";
 		 fi;;
 	Linux-android*) ;;
-	Linux*|GNU*) CCSHARED="-fPIC";;
+	Linux*|GNU*|Haiku*) CCSHARED="-fPIC";;
 	FreeBSD*|NetBSD*|OpenBSD*|DragonFly*) CCSHARED="-fPIC";;
 	OpenUNIX*|UnixWare*)
 		if test "$GCC" = "yes"
@@ -2802,7 +2813,7 @@ then
 	    LINKFORSHARED="-Wl,-E -Wl,+s";;
 #	    LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
 	Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
-	Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
+	Linux*|GNU*|Haiku*) LINKFORSHARED="-Xlinker -export-dynamic";;
 	# -u libsys_s pulls in all symbols in libsys
 	Darwin/*)
 		LINKFORSHARED="$extra_undefs -framework CoreFoundation"
@@ -3074,6 +3085,12 @@ AC_SUBST(TZPATH)
 AC_CHECK_LIB(nsl, t_open, [LIBS="-lnsl $LIBS"]) # SVR4
 AC_CHECK_LIB(socket, socket, [LIBS="-lsocket $LIBS"], [], $LIBS) # SVR4 sockets
 
+# Haiku's sockets are stashed in libnetwork.
+case "$ac_sys_system" in
+	Haiku*)
+		AC_CHECK_LIB(network, socket, [LIBS="-lnetwork $LIBS"], [], $LIBS);;
+esac
+
 AC_MSG_CHECKING(for --with-libs)
 AC_ARG_WITH(libs,
             AS_HELP_STRING([--with-libs='lib1 ...'], [link against additional libs (default is no)]),
@@ -4467,6 +4484,7 @@ AC_CHECK_FUNC(__fpu_control,
 AC_SUBST(LIBM)
 case $ac_sys_system in
 Darwin) ;;
+Haiku) ;;
 *) LIBM=-lm
 esac
 AC_MSG_CHECKING(for --with-libm=STRING)
diff --git a/setup.py b/setup.py
index 43e807f..6834df3 100644
--- a/setup.py
+++ b/setup.py
@@ -86,6 +86,7 @@ CYGWIN = (HOST_PLATFORM == 'cygwin')
 MACOS = (HOST_PLATFORM == 'darwin')
 AIX = (HOST_PLATFORM.startswith('aix'))
 VXWORKS = ('vxworks' in HOST_PLATFORM)
+HAIKU = (HOST_PLATFORM == 'haiku1')
 CC = os.environ.get("CC")
 if not CC:
     CC = sysconfig.get_config_var("CC")
@@ -868,6 +869,11 @@ class PyBuildExt(build_ext):
         with open(config_h) as file:
             self.config_h_vars = sysconfig.parse_config_h(file)
 
+        # Haiku-specific library locations
+        if HAIKU:
+            self.inc_dirs += ['/boot/develop/headers/posix',
+                         '/boot/system/develop/headers']
+            self.lib_dirs += ['/boot/system/develop/lib']
         # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
         if HOST_PLATFORM in ['osf1', 'unixware7', 'openunix8']:
             self.lib_dirs += ['/usr/ccs/lib']
@@ -914,14 +920,14 @@ class PyBuildExt(build_ext):
                            extra_compile_args=['-DPy_BUILD_CORE_MODULE'],
                            extra_objects=[shared_math],
                            depends=['_math.h', shared_math],
-                           libraries=['m']))
+                           libraries=[]))
 
         # complex math library functions
         self.add(Extension('cmath', ['cmathmodule.c'],
                            extra_compile_args=['-DPy_BUILD_CORE_MODULE'],
                            extra_objects=[shared_math],
                            depends=['_math.h', shared_math],
-                           libraries=['m']))
+                           libraries=[]))
 
         # time libraries: librt may be needed for clock_gettime()
         time_libs = []
@@ -935,7 +941,7 @@ class PyBuildExt(build_ext):
         # libm is needed by delta_new() that uses round() and by accum() that
         # uses modf().
         self.add(Extension('_datetime', ['_datetimemodule.c'],
-                           libraries=['m'],
+                           libraries=[],
                            extra_compile_args=['-DPy_BUILD_CORE_MODULE']))
         # zoneinfo module
         self.add(Extension('_zoneinfo', ['_zoneinfo.c'],
@@ -1028,7 +1034,7 @@ class PyBuildExt(build_ext):
         #
         # audioop needs libm for floor() in multiple functions.
         self.add(Extension('audioop', ['audioop.c'],
-                           libraries=['m']))
+                           libraries=[]))
 
         # CSV files
         self.add(Extension('_csv', ['_csv.c']))
@@ -2265,7 +2271,7 @@ class PyBuildExt(build_ext):
             # function my_sqrt() needs libm for sqrt()
             self.add(Extension('_ctypes_test',
                                sources=['_ctypes/_ctypes_test.c'],
-                               libraries=['m']))
+                               libraries=[]))
 
         ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR")
         ffi_lib = None
@@ -2330,7 +2336,7 @@ class PyBuildExt(build_ext):
                                                          'Modules',
                                                          '_decimal',
                                                          'libmpdec'))]
-            libraries = ['m']
+            libraries = []
             sources = [
               '_decimal/_decimal.c',
               '_decimal/libmpdec/basearith.c',
@@ -2587,7 +2593,7 @@ class PyBuildExt(build_ext):
             ))
 
     def detect_nis(self):
-        if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6':
+        if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6' or HAIKU:
             self.missing.append('nis')
             return
 
-- 
2.30.2


From d9cebf903832a1f364da9b702bcf17767ece7acd Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Sun, 16 Apr 2017 10:05:42 +0200
Subject: fix for negative errnos


diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index ccb46a6..4a8ef65 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1830,6 +1830,8 @@ class Popen:
                         SubprocessError)
                 if issubclass(child_exception_type, OSError) and hex_errno:
                     errno_num = int(hex_errno, 16)
+                    if sys.platform.startswith('haiku'):
+                        errno_num = -errno_num;
                     child_exec_never_called = (err_msg == "noexec")
                     if child_exec_never_called:
                         err_msg = ""
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index a58159a..aa938be 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -623,6 +623,10 @@ error:
         char *cur;
         _Py_write_noraise(errpipe_write, "OSError:", 8);
         cur = hex_errno + sizeof(hex_errno);
+#ifdef __HAIKU__
+        if (saved_errno < 0)
+            saved_errno = -saved_errno;
+#endif
         while (saved_errno != 0 && cur != hex_errno) {
             *--cur = Py_hexdigits[saved_errno % 16];
             saved_errno /= 16;
-- 
2.30.2


From b6d2c9b36b2a2560e164f5a3026bbf8ca5aea368 Mon Sep 17 00:00:00 2001
From: Philippe Houdoin <philippe.houdoin@gmail.com>
Date: Wed, 24 May 2017 11:09:43 +0000
Subject: Implement CTypes's find_library for Haiku


diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py
index 0c2510e..2b4f04c 100644
--- a/Lib/ctypes/util.py
+++ b/Lib/ctypes/util.py
@@ -265,6 +265,56 @@ elif os.name == "posix":
         def find_library(name, is64 = False):
             return _get_soname(_findLib_crle(name, is64) or _findLib_gcc(name))
 
+    elif sys.platform.startswith("haiku"):
+
+        def _num_version(libname):
+            # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ]
+            parts = libname.split('.')
+            nums = []
+            try:
+                while parts:
+                    nums.insert(0, int(parts.pop()))
+            except ValueError:
+                pass
+            return nums or [sys.maxint]
+
+        def find_library(name):
+            if name in ('c', 'm'):
+                return find_library('root')
+            for directory in os.environ['LIBRARY_PATH'].split(os.pathsep):
+                if directory.startswith("%A/"):
+                    directory = directory.replace('%A',
+                        os.path.dirname(os.path.abspath(sys.argv[0] or os.getcwd())))
+
+                if not os.path.isdir(directory):
+                    continue
+
+                # try direct match
+                fname = os.path.join(directory, name)
+                if os.path.isfile(fname):
+                    return fname
+
+                fname = os.path.join(directory, 'lib%s.so' % name)
+                if os.path.isfile(fname):
+                    return fname
+
+                # no exact matching in this directroy
+                # collect versioned candidates, if any
+                candidates = []
+                pattern = re.compile(r'lib%s\.so\.\S+' % re.escape(name))
+                for entry in os.listdir(directory):
+                    if not os.path.isfile(os.path.join(directory, entry)):
+                        continue
+
+                    if re.match(pattern, entry):
+                        candidates.append(os.path.join(directory, entry))
+
+                if candidates:
+                    # return latest version found
+                    candidates.sort(key=_num_version)
+                    return candidates[-1]
+
+            return None
     else:
 
         def _findSoname_ldconfig(name):
@@ -367,6 +417,12 @@ def test():
             print(f"crypt\t:: {cdll.LoadLibrary(find_library('crypt'))}")
             print(f"crypto\t:: {find_library('crypto')}")
             print(f"crypto\t:: {cdll.LoadLibrary(find_library('crypto'))}")
+        elif sys.platform.startswith("haiku"):
+            print(find_library("libbz2.so.1.0"))
+            print(find_library("tracker"))
+            print(find_library("media"))
+            print(cdll.LoadLibrary(find_library("tracker")))
+            print(cdll.LoadLibrary("libmedia.so"))
         else:
             print(cdll.LoadLibrary("libm.so"))
             print(cdll.LoadLibrary("libcrypt.so"))
-- 
2.30.2


From 2c1eddce5a0e37a961428a0745c6fd67ab6fae63 Mon Sep 17 00:00:00 2001
From: Philipp Wolfer <phil@parolu.io>
Date: Mon, 23 Sep 2019 09:14:58 +0200
Subject: webbrowser: Support for default browsers on Haiku


diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
index ec3cece..6a29d2a 100755
--- a/Lib/webbrowser.py
+++ b/Lib/webbrowser.py
@@ -547,6 +547,11 @@ def register_standard_browsers():
                         "netscape", "opera", iexplore):
             if shutil.which(browser):
                 register(browser, None, BackgroundBrowser(browser))
+    elif sys.platform[:5] == "haiku":
+        # First try to use the default configured browser
+        register("haiku-default", None, GenericBrowser("open"))
+        # Fall back to WebPositive as the standard browser of Haiku
+        register("webpositive", None, BackgroundBrowser("WebPositive"))
     else:
         # Prefer X browsers if present
         if os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"):
-- 
2.30.2


From e71e66cd48a32e7b41a770755b84c7a4f9dbefc2 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Fri, 4 Oct 2019 22:02:35 +0200
Subject: since 3.8, don't reinit locks on fork.


diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 555f598..f151fd0 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -235,7 +235,7 @@ def _releaseLock():
 
 # Prevent a held logging lock from blocking a child from logging.
 
-if not hasattr(os, 'register_at_fork'):  # Windows and friends.
+if sys.platform.startswith('haiku') or not hasattr(os, 'register_at_fork'):  # Windows and friends.
     def _register_at_fork_reinit_lock(instance):
         pass  # no-op when os.register_at_fork does not exist.
 else:
-- 
2.30.2


From 0c2158b279579bd9e01e2009b58433a774f38b55 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Fri, 15 May 2020 15:20:57 +0200
Subject: handle errors returned by internal_connect()

upstream bug #40628 by Ryan C. Gordon

diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index b2aee8b..1c43b96 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -3280,7 +3280,7 @@ sock_connect(PySocketSockObject *s, PyObject *addro)
     }
 
     res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1);
-    if (res < 0)
+    if (res == -1)
         return NULL;
 
     Py_RETURN_NONE;
@@ -3311,7 +3311,7 @@ sock_connect_ex(PySocketSockObject *s, PyObject *addro)
     }
 
     res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0);
-    if (res < 0)
+    if (res == -1)
         return NULL;
 
     return PyLong_FromLong((long) res);
-- 
2.30.2


From 1213f8a74b3940676029784407a5acc633d83345 Mon Sep 17 00:00:00 2001
From: Jerome Duval <jerome.duval@gmail.com>
Date: Mon, 19 Oct 2020 18:03:09 +0200
Subject: ttyname_r can use MAXPATHLEN


diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 03de470..663e6cc 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -3073,11 +3073,14 @@ static PyObject *
 os_ttyname_impl(PyObject *module, int fd)
 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
 {
-
+#ifndef __HAIKU__
     long size = sysconf(_SC_TTY_NAME_MAX);
     if (size == -1) {
         return posix_error();
     }
+#else
+    long size = MAXPATHLEN;
+#endif
     char *buffer = (char *)PyMem_RawMalloc(size);
     if (buffer == NULL) {
         return PyErr_NoMemory();
-- 
2.30.2

