Issue #13959: Re-implement imp.get_suffixes() in Lib/imp.py.

This introduces a new function, imp.extension_suffixes(), which is
currently undocumented. That is forthcoming once issue #14657 is
resolved and how to expose file suffixes is decided.
diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c
index 9e8f536..b4f71f2 100644
--- a/Python/dynload_aix.c
+++ b/Python/dynload_aix.c
@@ -26,10 +26,7 @@
     void          *entry;
 } Module, *ModulePtr;
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-    {".so", "rb", C_EXTENSION},
-    {0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {".so", NULL};
 
 static int
 aix_getoldmodules(void **modlistptr)
diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c
index a914a08..5836cb3 100644
--- a/Python/dynload_dl.c
+++ b/Python/dynload_dl.c
@@ -9,10 +9,7 @@
 
 extern char *Py_GetProgramName(void);
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-    {".o", "rb", C_EXTENSION},
-    {0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {".o", NULL};
 
 
 dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c
index 6f0f252..c955414 100644
--- a/Python/dynload_hpux.c
+++ b/Python/dynload_hpux.c
@@ -13,10 +13,7 @@
 #define FUNCNAME_PATTERN "PyInit_%.200s"
 #endif
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-    {SHLIB_EXT, "rb", C_EXTENSION},
-    {0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL};
 
 dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
                                     const char *pathname, FILE *fp)
diff --git a/Python/dynload_next.c b/Python/dynload_next.c
index 5caff8b..85c95b4 100644
--- a/Python/dynload_next.c
+++ b/Python/dynload_next.c
@@ -8,10 +8,7 @@
 
 #include <mach-o/dyld.h>
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-    {".so", "rb", C_EXTENSION},
-    {0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {".so", NULL};
 
 /*
 ** Python modules are Mach-O MH_BUNDLE files. The best way to load these
diff --git a/Python/dynload_os2.c b/Python/dynload_os2.c
index f7264da..0e1b907 100644
--- a/Python/dynload_os2.c
+++ b/Python/dynload_os2.c
@@ -9,11 +9,7 @@
 #include "importdl.h"
 
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-    {".pyd", "rb", C_EXTENSION},
-    {".dll", "rb", C_EXTENSION},
-    {0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {".pyd", ".dll", NULL};
 
 dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname,
                                     const char *pathname, FILE *fp)
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
index 565faca..24e4ede 100644
--- a/Python/dynload_shlib.c
+++ b/Python/dynload_shlib.c
@@ -36,25 +36,25 @@
    live in the same directory.  E.g. foomodule.cpython-32.so
 */
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
+const char *_PyImport_DynLoadFiletab[] = {
 #ifdef __CYGWIN__
-    {".dll", "rb", C_EXTENSION},
+    ".dll",
 #else  /* !__CYGWIN__ */
 #if defined(PYOS_OS2) && defined(PYCC_GCC)
-    {".pyd", "rb", C_EXTENSION},
-    {".dll", "rb", C_EXTENSION},
+    ".pyd",
+    ".dll",
 #else  /* !(defined(PYOS_OS2) && defined(PYCC_GCC)) */
 #ifdef __VMS
-    {".exe", "rb", C_EXTENSION},
-    {".EXE", "rb", C_EXTENSION},
+    ".exe",
+    ".EXE",
 #else  /* !__VMS */
-    {"." SOABI ".so", "rb", C_EXTENSION},
-    {".abi" PYTHON_ABI_STRING ".so", "rb", C_EXTENSION},
-    {".so", "rb", C_EXTENSION},
+    "." SOABI ".so",
+    ".abi" PYTHON_ABI_STRING ".so",
+    ".so",
 #endif  /* __VMS */
 #endif  /* defined(PYOS_OS2) && defined(PYCC_GCC) */
 #endif  /* __CYGWIN__ */
-    {0, 0}
+    NULL,
 };
 
 static struct {
diff --git a/Python/dynload_stub.c b/Python/dynload_stub.c
index 69f8b45..5916048 100644
--- a/Python/dynload_stub.c
+++ b/Python/dynload_stub.c
@@ -6,6 +6,4 @@
 #include "importdl.h"
 
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
-	{0, 0}
-};
+const char *_PyImport_DynLoadFiletab[] = {NULL};
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index 7bf3dfc..9c48a2d 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -15,13 +15,13 @@
 extern ULONG_PTR _Py_ActivateActCtx();
 void _Py_DeactivateActCtx(ULONG_PTR cookie);
 
-const struct filedescr _PyImport_DynLoadFiletab[] = {
+const char *_PyImport_DynLoadFiletab[] = {
 #ifdef _DEBUG
-    {"_d.pyd", "rb", C_EXTENSION},
+    "_d.pyd",
 #else
-    {".pyd", "rb", C_EXTENSION},
+    ".pyd",
 #endif
-    {0, 0}
+    NULL
 };
 
 
diff --git a/Python/import.c b/Python/import.c
index 71485bd..8349b77 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -140,18 +140,6 @@
 
 struct _inittab *PyImport_Inittab = _PyImport_Inittab;
 
-/* these tables define the module suffixes that Python recognizes */
-struct filedescr * _PyImport_Filetab = NULL;
-
-static const struct filedescr _PyImport_StandardFiletab[] = {
-    {".py", "U", PY_SOURCE},
-#ifdef MS_WINDOWS
-    {".pyw", "U", PY_SOURCE},
-#endif
-    {".pyc", "rb", PY_COMPILED},
-    {0, 0}
-};
-
 static PyObject *initstr = NULL;
 
 /* Initialize things */
@@ -159,44 +147,9 @@
 void
 _PyImport_Init(void)
 {
-    const struct filedescr *scan;
-    struct filedescr *filetab;
-    int countD = 0;
-    int countS = 0;
-
     initstr = PyUnicode_InternFromString("__init__");
     if (initstr == NULL)
         Py_FatalError("Can't initialize import variables");
-
-    /* prepare _PyImport_Filetab: copy entries from
-       _PyImport_DynLoadFiletab and _PyImport_StandardFiletab.
-     */
-#ifdef HAVE_DYNAMIC_LOADING
-    for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan)
-        ++countD;
-#endif
-    for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan)
-        ++countS;
-    filetab = PyMem_NEW(struct filedescr, countD + countS + 1);
-    if (filetab == NULL)
-        Py_FatalError("Can't initialize import file table.");
-#ifdef HAVE_DYNAMIC_LOADING
-    memcpy(filetab, _PyImport_DynLoadFiletab,
-           countD * sizeof(struct filedescr));
-#endif
-    memcpy(filetab + countD, _PyImport_StandardFiletab,
-           countS * sizeof(struct filedescr));
-    filetab[countD + countS].suffix = NULL;
-
-    _PyImport_Filetab = filetab;
-
-    if (Py_OptimizeFlag) {
-        /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */
-        for (; filetab->suffix != NULL; filetab++) {
-            if (strcmp(filetab->suffix, ".pyc") == 0)
-                filetab->suffix = ".pyo";
-        }
-    }
 }
 
 void
@@ -400,8 +353,6 @@
 {
     Py_XDECREF(extensions);
     extensions = NULL;
-    PyMem_DEL(_PyImport_Filetab);
-    _PyImport_Filetab = NULL;
 #ifdef WITH_THREAD
     if (import_lock != NULL) {
         PyThread_free_lock(import_lock);
@@ -1911,17 +1862,18 @@
 }
 
 static PyObject *
-imp_get_suffixes(PyObject *self, PyObject *noargs)
+imp_extension_suffixes(PyObject *self, PyObject *noargs)
 {
     PyObject *list;
-    struct filedescr *fdp;
+    const char *suffix;
+    unsigned int index = 0;
 
     list = PyList_New(0);
     if (list == NULL)
         return NULL;
-    for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) {
-        PyObject *item = Py_BuildValue("ssi",
-                               fdp->suffix, fdp->mode, fdp->type);
+#ifdef HAVE_DYNAMIC_LOADING
+    while ((suffix = _PyImport_DynLoadFiletab[index])) {
+        PyObject *item = PyUnicode_FromString(suffix);
         if (item == NULL) {
             Py_DECREF(list);
             return NULL;
@@ -1932,7 +1884,9 @@
             return NULL;
         }
         Py_DECREF(item);
+        index += 1;
     }
+#endif
     return list;
 }
 
@@ -2101,10 +2055,9 @@
 "get_tag() -> string\n\
 Return the magic tag for .pyc or .pyo files.");
 
-PyDoc_STRVAR(doc_get_suffixes,
-"get_suffixes() -> [(suffix, mode, type), ...]\n\
-Return a list of (suffix, mode, type) tuples describing the files\n\
-that find_module() looks for.");
+PyDoc_STRVAR(doc_extension_suffixes,
+"extension_suffixes() -> list of strings\n\
+Returns the list of file suffixes used to identify extension modules.");
 
 PyDoc_STRVAR(doc_lock_held,
 "lock_held() -> boolean\n\
@@ -2126,7 +2079,8 @@
 static PyMethodDef imp_methods[] = {
     {"get_magic",        imp_get_magic,    METH_NOARGS,  doc_get_magic},
     {"get_tag",          imp_get_tag,      METH_NOARGS,  doc_get_tag},
-    {"get_suffixes", imp_get_suffixes, METH_NOARGS,  doc_get_suffixes},
+    {"extension_suffixes", imp_extension_suffixes, METH_NOARGS,
+        doc_extension_suffixes},
     {"lock_held",        imp_lock_held,    METH_NOARGS,  doc_lock_held},
     {"acquire_lock", imp_acquire_lock, METH_NOARGS,  doc_acquire_lock},
     {"release_lock", imp_release_lock, METH_NOARGS,  doc_release_lock},
diff --git a/Python/importdl.h b/Python/importdl.h
index e51e551..32c6b5b 100644
--- a/Python/importdl.h
+++ b/Python/importdl.h
@@ -20,13 +20,8 @@
     IMP_HOOK
 };
 
-struct filedescr {
-    char *suffix;
-    char *mode;
-    enum filetype type;
-};
-extern struct filedescr * _PyImport_Filetab;
-extern const struct filedescr _PyImport_DynLoadFiletab[];
+
+extern const char *_PyImport_DynLoadFiletab[];
 
 extern PyObject *_PyImport_LoadDynamicModule(PyObject *name, PyObject *pathname,
                                              FILE *);
diff --git a/Python/importlib.h b/Python/importlib.h
index e9f5faf..1681605 100644
--- a/Python/importlib.h
+++ b/Python/importlib.h
Binary files differ