OS/2 patches by Andrew I MacIntyre for distutils.

Closes patch #435381.
diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py
index 21bf0c17..f4fc4bc 100644
--- a/Lib/distutils/ccompiler.py
+++ b/Lib/distutils/ccompiler.py
@@ -846,6 +846,7 @@
     # on a cygwin built python we can use gcc like an ordinary UNIXish
     # compiler
     ('cygwin.*', 'unix'),
+    ('os2emx', 'emx'),
 
     # OS name mappings
     ('posix', 'unix'),
@@ -892,6 +893,8 @@
                                "Borland C++ Compiler"),
                    'mwerks':  ('mwerkscompiler', 'MWerksCompiler',
                                "MetroWerks CodeWarrior"),
+                   'emx':     ('emxccompiler', 'EMXCCompiler',
+                               "EMX port of GNU C Compiler for OS/2"),
                  }
 
 def show_compilers():
diff --git a/Lib/distutils/command/bdist.py b/Lib/distutils/command/bdist.py
index fc18bd0..68609f3 100644
--- a/Lib/distutils/command/bdist.py
+++ b/Lib/distutils/command/bdist.py
@@ -57,7 +57,8 @@
     # This won't do in reality: will need to distinguish RPM-ish Linux,
     # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
     default_format = { 'posix': 'gztar',
-                       'nt': 'zip', }
+                       'nt': 'zip',
+                       'os2': 'zip', }
 
     # Establish the preferred order (for the --help-formats option).
     format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
diff --git a/Lib/distutils/command/bdist_dumb.py b/Lib/distutils/command/bdist_dumb.py
index dbe862b..b627a86 100644
--- a/Lib/distutils/command/bdist_dumb.py
+++ b/Lib/distutils/command/bdist_dumb.py
@@ -37,7 +37,8 @@
     boolean_options = ['keep-temp', 'skip-build']
 
     default_format = { 'posix': 'gztar',
-                       'nt': 'zip', }
+                       'nt': 'zip',
+                       'os2': 'zip' }
 
 
     def initialize_options (self):
@@ -88,6 +89,12 @@
         # pseudo-installation tree.
         archive_basename = "%s.%s" % (self.distribution.get_fullname(),
                                       self.plat_name)
+
+        # OS/2 objects to any ":" characters in a filename (such as when
+        # a timestamp is used in a version) so change them to hyphens.
+        if os.name == "os2":
+            archive_basename = archive_basename.replace(":", "-")
+
         self.make_archive(os.path.join(self.dist_dir, archive_basename),
                           self.format,
                           root_dir=self.bdist_dir)
diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py
index 98617f7..91fee5e 100644
--- a/Lib/distutils/command/build_ext.py
+++ b/Lib/distutils/command/build_ext.py
@@ -167,6 +167,11 @@
             else:
                 self.build_temp = os.path.join(self.build_temp, "Release")
 
+        # OS/2 (EMX) doesn't support Debug vs Release builds, but has the 
+        # import libraries in its "Config" subdirectory
+        if os.name == 'os2':
+            self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config'))
+
         # for extensions under Cygwin Python's library directory must be
         # appended to library_dirs
         if sys.platform[:6] == 'cygwin':
@@ -554,6 +559,10 @@
             else:
                 return "swig.exe"
 
+        elif os.name == "os2":
+            # assume swig available in the PATH.
+            return "swig.exe"
+
         else:
             raise DistutilsPlatformError, \
                   ("I don't know how to find (much less run) SWIG "
@@ -578,6 +587,9 @@
 
         from distutils.sysconfig import get_config_var
         ext_path = string.split(ext_name, '.')
+        # OS/2 has an 8 character module (extension) limit :-(
+        if os.name == "os2":
+            ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8]
         # extensions in debug_mode are named 'module_d.pyd' under windows
         so_ext = get_config_var('SO')
         if os.name == 'nt' and self.debug:
@@ -599,7 +611,7 @@
     def get_libraries (self, ext):
         """Return the list of libraries to link against when building a
         shared extension.  On most platforms, this is just 'ext.libraries';
-        on Windows, we add the Python library (eg. python20.dll).
+        on Windows and OS/2, we add the Python library (eg. python20.dll).
         """
         # The python library is always needed on Windows.  For MSVC, this
         # is redundant, since the library is mentioned in a pragma in
@@ -617,6 +629,19 @@
             # don't extend ext.libraries, it may be shared with other
             # extensions, it is a reference to the original list
             return ext.libraries + [pythonlib]
+        elif sys.platform == "os2emx":
+            # EMX/GCC requires the python library explicitly, and I
+            # believe VACPP does as well (though not confirmed) - AIM Apr01
+            template = "python%d%d"
+            # debug versions of the main DLL aren't supported, at least 
+            # not at this time - AIM Apr01
+            #if self.debug:
+            #    template = template + '_d'
+            pythonlib = (template %
+                   (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
+            # don't extend ext.libraries, it may be shared with other
+            # extensions, it is a reference to the original list
+            return ext.libraries + [pythonlib]
         elif sys.platform[:6] == "cygwin":
             template = "python%d.%d"
             pythonlib = (template %
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
index 8755a14..4d78d3a 100644
--- a/Lib/distutils/command/install.py
+++ b/Lib/distutils/command/install.py
@@ -55,6 +55,13 @@
         'headers': '$base/Include/$dist_name',
         'scripts': '$base/Scripts',
         'data'   : '$base',
+        },
+    'os2': {
+        'purelib': '$base/Lib/site-packages',
+        'platlib': '$base/Lib/site-packages',
+        'headers': '$base/Include/$dist_name',
+        'scripts': '$base/Scripts',
+        'data'   : '$base',
         }
     }
 
diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py
index 07dc814..5b6016e 100644
--- a/Lib/distutils/spawn.py
+++ b/Lib/distutils/spawn.py
@@ -38,6 +38,8 @@
         _spawn_posix(cmd, search_path, verbose, dry_run)
     elif os.name == 'nt':
         _spawn_nt(cmd, search_path, verbose, dry_run)
+    elif os.name == 'os2':
+        _spawn_os2(cmd, search_path, verbose, dry_run)
     else:
         raise DistutilsPlatformError, \
               "don't know how to spawn programs on platform '%s'" % os.name
@@ -88,6 +90,33 @@
                   "command '%s' failed with exit status %d" % (cmd[0], rc)
 
 
+def _spawn_os2 (cmd,
+                search_path=1,
+                verbose=0,
+                dry_run=0):
+
+    executable = cmd[0]
+    #cmd = _nt_quote_args(cmd)
+    if search_path:
+        # either we find one or it stays the same
+        executable = find_executable(executable) or executable 
+    if verbose:
+        print string.join([executable] + cmd[1:], ' ')
+    if not dry_run:
+        # spawnv for OS/2 EMX requires a full path to the .exe
+        try:
+            rc = os.spawnv(os.P_WAIT, executable, cmd)
+        except OSError, exc:
+            # this seems to happen when the command isn't found
+            raise DistutilsExecError, \
+                  "command '%s' failed: %s" % (cmd[0], exc[-1])
+        if rc != 0:
+            # and this reflects the command running but failing
+            print "command '%s' failed with exit status %d" % (cmd[0], rc)
+            raise DistutilsExecError, \
+                  "command '%s' failed with exit status %d" % (cmd[0], rc)
+
+
 def _spawn_posix (cmd,
                   search_path=1,
                   verbose=0,
@@ -154,7 +183,7 @@
         path = os.environ['PATH']
     paths = string.split(path, os.pathsep)
     (base, ext) = os.path.splitext(executable)
-    if (sys.platform == 'win32') and (ext != '.exe'):
+    if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'):
         executable = executable + '.exe'
     if not os.path.isfile(executable):
         for p in paths:
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index feaf318..d773f149 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -59,6 +59,8 @@
         return os.path.join(prefix, "include")
     elif os.name == "mac":
         return os.path.join(prefix, "Include")
+    elif os.name == "os2":
+        return os.path.join(prefix, "Include")
     else:
         raise DistutilsPlatformError(
             "I don't know where Python installs its C header files "
@@ -110,6 +112,13 @@
                 return os.path.join(prefix, "Lib")
             else:
                 return os.path.join(prefix, "Lib", "site-packages")
+
+    elif os.name == "os2":
+        if standard_lib:
+            return os.path.join(PREFIX, "Lib")
+        else:
+            return os.path.join(PREFIX, "Lib", "site-packages")
+
     else:
         raise DistutilsPlatformError(
             "I don't know where Python installs its library "
@@ -391,6 +400,23 @@
     _config_vars = g
 
 
+def _init_os2():
+    """Initialize the module as appropriate for OS/2"""
+    g = {}
+    # set basic install directories
+    g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
+    g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
+
+    # XXX hmmm.. a normal install puts include files here
+    g['INCLUDEPY'] = get_python_inc(plat_specific=0)
+
+    g['SO'] = '.pyd'
+    g['EXE'] = ".exe"
+
+    global _config_vars
+    _config_vars = g
+
+
 def get_config_vars(*args):
     """With no arguments, return a dictionary of all configuration
     variables relevant for the current platform.  Generally this includes
diff --git a/Lib/distutils/util.py b/Lib/distutils/util.py
index 1541e02..a51ce66 100644
--- a/Lib/distutils/util.py
+++ b/Lib/distutils/util.py
@@ -117,6 +117,12 @@
             path = path[1:]
         return os.path.join(new_root, path)
 
+    elif os.name == 'os2':
+        (drive, path) = os.path.splitdrive(pathname)
+        if path[0] == os.sep:
+            path = path[1:]
+        return os.path.join(new_root, path)
+
     elif os.name == 'mac':
         if not os.path.isabs(pathname):
             return os.path.join(new_root, pathname)