shithub: sox

Download patch

ref: b01b3221bf91883b73fb0b572cb816827d000759
parent: 1135e7d9c07c0835f1e28916d929facbed97f4f6
author: idigdoug <idigdoug>
date: Wed Dec 2 06:11:08 EST 2009

Add optional support for glob and ltdl on MS Windows via minimal substitute libraries.

--- a/src/sox.c
+++ b/src/sox.c
@@ -38,7 +38,10 @@
 #include <sys/types.h>
 #include <time.h>
 
-#ifdef HAVE_GLOB_H
+#if defined(HAVE_WIN32_GLOB_H)
+  #include "win32-glob.h"
+  #define HAVE_GLOB_H 1
+#elif defined(HAVE_GLOB_H)
   #include <glob.h>
 #endif
 
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -307,7 +307,11 @@
 
 /*--------------------------------- Dynamic Library ----------------------------------*/
 
-#if defined(HAVE_LIBLTDL)
+#if defined(HAVE_WIN32_LTDL_H)
+    #include "win32-ltdl.h"
+    #define HAVE_LIBLTDL 1
+    typedef lt_dlhandle lsx_dlhandle;
+#elif defined(HAVE_LIBLTDL)
     #include <ltdl.h>
     typedef lt_dlhandle lsx_dlhandle;
 #else
--- /dev/null
+++ b/src/win32-glob.c
@@ -1,0 +1,167 @@
+/* libSoX minimal glob for MS-Windows: (c) 2009 SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "win32-glob.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+typedef struct file_entry
+{
+    char name[MAX_PATH];
+    struct file_entry *next;
+} file_entry;
+
+static int
+insert(
+    const char* path,
+    const char* name,
+    file_entry** phead)
+{
+    int len;
+    file_entry* cur = malloc(sizeof(file_entry));
+    if (!cur)
+    {
+        return ENOMEM;
+    }
+
+    len = _snprintf(cur->name, MAX_PATH, "%s%s", path, name);
+    cur->name[MAX_PATH - 1] = 0;
+    cur->next = *phead;
+    *phead = cur;
+
+    return len < 0 || len >= MAX_PATH ? ENAMETOOLONG : 0;
+}
+
+static int
+entry_comparer(
+    const file_entry** pe1,
+    const file_entry** pe2)
+{
+    return _stricmp((*pe1)->name, (*pe2)->name);
+}
+
+int
+glob(
+    const char *pattern,
+    int flags,
+    void *unused,
+    glob_t *pglob)
+{
+    char path[MAX_PATH];
+    file_entry *head = NULL;
+    int err = 0;
+    size_t len;
+    unsigned entries = 0;
+    WIN32_FIND_DATAA finddata;
+    HANDLE hfindfile = FindFirstFileA(pattern, &finddata);
+
+    if (!pattern || flags != (flags & GLOB_FLAGS) || unused || !pglob)
+    {
+        errno = EINVAL;
+        return EINVAL;
+    }
+
+    path[MAX_PATH - 1] = 0;
+    strncpy(path, pattern, MAX_PATH);
+    if (path[MAX_PATH - 1] != 0)
+    {
+        errno = ENAMETOOLONG;
+        return ENAMETOOLONG;
+    }
+
+    len = strlen(path);
+    while (len > 0 && path[len - 1] != '/' && path[len - 1] != '\\')
+        len--;
+    path[len] = 0;
+
+    if (hfindfile == INVALID_HANDLE_VALUE)
+    {
+        if (flags & GLOB_NOCHECK)
+        {
+            err = insert("", pattern, &head);
+            entries++;
+        }
+    }
+    else
+    {
+        do
+        {
+            err = insert(path, finddata.cFileName, &head);
+            entries++;
+        } while (!err && FindNextFileA(hfindfile, &finddata));
+
+        FindClose(hfindfile);
+    }
+
+    if (err == 0)
+    {
+        pglob->gl_pathv = malloc((entries + 1) * sizeof(char*));
+        if (pglob->gl_pathv)
+        {
+            pglob->gl_pathc = entries;
+            pglob->gl_pathv[entries] = NULL;
+            for (; head; head = head->next, entries--)
+                pglob->gl_pathv[entries - 1] = (char*)head;
+            qsort(pglob->gl_pathv, pglob->gl_pathc, sizeof(char*), entry_comparer);
+        }
+        else
+        {
+            pglob->gl_pathc = 0;
+            err = ENOMEM;
+        }
+    }
+    else if (pglob)
+    {
+        pglob->gl_pathc = 0;
+        pglob->gl_pathv = NULL;
+    }
+
+    if (err)
+    {
+        file_entry *cur;
+        while (head)
+        {
+            cur = head;
+            head = head->next;
+            free(cur);
+        }
+
+        errno = err;
+    }
+
+    return err;
+}
+
+void
+globfree(
+    glob_t* pglob)
+{
+    if (pglob)
+    {
+        char** cur;
+        for (cur = pglob->gl_pathv; *cur; cur++)
+        {
+            free(*cur);
+        }
+
+        pglob->gl_pathc = 0;
+        pglob->gl_pathv = NULL;
+    }
+}
--- /dev/null
+++ b/src/win32-glob.h
@@ -1,0 +1,49 @@
+/* libSoX minimal glob for MS-Windows: (c) 2009 SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef GLOB_H
+#define GLOB_H 1
+
+#define GLOB_NOCHECK (16)
+#define GLOB_FLAGS (GLOB_NOCHECK)
+
+typedef struct glob_t
+{
+    unsigned gl_pathc;
+    char **gl_pathv;
+} glob_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+glob(
+    const char *pattern,
+    int flags,
+    void *unused,
+    glob_t *pglob);
+
+void
+globfree(
+    glob_t* pglob);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef GLOB_H */
--- /dev/null
+++ b/src/win32-ltdl.c
@@ -1,0 +1,310 @@
+/* libSoX minimal libtool-ltdl for MS-Windows: (c) 2009 SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "win32-ltdl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+static DWORD
+s_dwLastError;
+
+static char
+s_szLastError[MAX_PATH];
+
+static int
+CopyPath(
+    const char* szSource,
+    char* szDest,
+    unsigned cchDest,
+    char chStop)
+{
+    unsigned i = 0;
+    char ch;
+    if (szSource != 0 && cchDest != 0)
+    {
+        for (; i < cchDest - 1 && (ch = szSource[i]) != 0 && ch != chStop; i++)
+        {
+            if (ch == '/')
+            {
+                ch = '\\';
+            }
+
+            szDest[i] = ch;
+        }
+    }
+
+    szDest[i] = 0;
+    return i;
+}
+
+static lt_dlhandle
+LoadLib(
+    const char* szFileName,
+    const char* const szExtensions[])
+{
+    lt_dlhandle hMod = 0;
+    char szFull[MAX_PATH];
+    const char* szExt;
+    unsigned iExtension;
+    unsigned iCur;
+    unsigned iEnd = CopyPath(szFileName, szFull, _countof(szFull), 0);
+    if (iEnd == 0)
+    {
+        s_dwLastError = ERROR_INVALID_PARAMETER;
+        goto Done;
+    }
+
+    for (iExtension = 0; !hMod && szExtensions[iExtension]; iExtension++)
+    {
+        szExt = szExtensions[iExtension];
+        for (iCur = 0; szExt[iCur] && iEnd + iCur < _countof(szFull); iCur++)
+        {
+            szFull[iEnd + iCur] = szExt[iCur];
+        }
+
+        if (iEnd + iCur >= _countof(szFull))
+        {
+            s_dwLastError = ERROR_BUFFER_OVERFLOW;
+            goto Done;
+        }
+        else
+        {
+            szFull[iEnd + iCur] = 0;
+        }
+
+        hMod = (lt_dlhandle)LoadLibraryA(szFull);
+    }
+
+    s_dwLastError = hMod ? 0 : GetLastError();
+
+Done:
+    return hMod;
+}
+
+int
+lt_dlinit(void)
+{
+    int cErrors = 0;
+    s_dwLastError = 0;
+    return cErrors;
+}
+
+int
+lt_dlexit(void)
+{
+    int cErrors = 0;
+    s_dwLastError = 0;
+    return cErrors;
+}
+
+int
+lt_dlforeachfile(
+    const char *szSearchPath,
+    int (*pfCallback)(const char *szFileName, lt_ptr pData),
+    lt_ptr pData)
+{
+    char szExePath[MAX_PATH];
+    char szOnePath[MAX_PATH];
+    int cErrors = 0;
+    unsigned iSearchPath = 0;
+    unsigned iOnePath;
+    unsigned iExePath;
+    unsigned cchCopied;
+    HANDLE hFind;
+    WIN32_FIND_DATAA data;
+
+    szExePath[0] = 0;
+
+    if (pfCallback == 0)
+    {
+        s_dwLastError = ERROR_INVALID_PARAMETER;
+        cErrors++;
+        goto Done;
+    }
+
+    if (szSearchPath != 0)
+    {
+        while (1)
+        {
+            while (szSearchPath[iSearchPath] == LT_PATHSEP_CHAR)
+            {
+                iSearchPath++;
+            }
+
+            if (szSearchPath[iSearchPath] == 0)
+            {
+                s_dwLastError = 0;
+                break;
+            }
+
+            if (szSearchPath[iSearchPath] == '.' &&
+                (szSearchPath[iSearchPath + 1] == '\\' || szSearchPath[iSearchPath + 1] == '/'))
+            {
+                if (szExePath[0] == 0)
+                {
+                    iExePath = GetModuleFileNameA(0, szExePath, _countof(szExePath));
+                    if (iExePath == 0)
+                    {
+                        s_dwLastError = GetLastError();
+                        cErrors++;
+                        goto Done;
+                    }
+                    else if (iExePath == _countof(szExePath))
+                    {
+                        s_dwLastError = ERROR_BUFFER_OVERFLOW;
+                        cErrors++;
+                        goto Done;
+                    }
+
+                    while (iExePath > 0 && szExePath[iExePath - 1] != '\\')
+                    {
+                        iExePath--;
+                    }
+
+                    if (iExePath > 0)
+                    {
+                        iExePath--;
+                    }
+
+                    szExePath[iExePath] = 0;
+                }
+
+                strcpy(szOnePath, szExePath);
+                iOnePath = iExePath;
+                iSearchPath++;
+            }
+            else
+            {
+                iOnePath = 0;
+            }
+
+            cchCopied = CopyPath(
+                szSearchPath + iSearchPath,
+                szOnePath + iOnePath,
+                _countof(szOnePath) - iOnePath,
+                LT_PATHSEP_CHAR);
+            iSearchPath += cchCopied;
+            iOnePath += cchCopied;
+
+            if (0 < iOnePath && iOnePath + 1 < _countof(szOnePath) && szOnePath[iOnePath - 1] != '\\')
+            {
+                szOnePath[iOnePath++] = '\\';
+            }
+
+            if (iOnePath + 1 >= _countof(szOnePath))
+            {
+                s_dwLastError = ERROR_BUFFER_OVERFLOW;
+                cErrors++;
+                goto Done;
+            }
+
+            szOnePath[iOnePath++] = '*';
+            szOnePath[iOnePath] = 0;
+
+            hFind = FindFirstFileA(szOnePath, &data);
+            while (hFind != INVALID_HANDLE_VALUE)
+            {
+                if (0 == (data.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_OFFLINE)))
+                {
+                    cErrors = pfCallback(data.cFileName, pData);
+                    if (cErrors)
+                    {
+                        s_dwLastError = ERROR_CANCELLED;
+                        FindClose(hFind);
+                        goto Done;
+                    }
+                }
+
+                if (!FindNextFileA(hFind, &data))
+                {
+                    s_dwLastError = ERROR_SUCCESS;
+                    FindClose(hFind);
+                    hFind = INVALID_HANDLE_VALUE;
+                }
+            }
+        }
+    }
+
+Done:
+    return cErrors;
+}
+
+lt_dlhandle
+lt_dlopen(
+    const char *szFileName)
+{
+    const char* const szExtensions[] = { ".", 0 };
+    lt_dlhandle hModule = LoadLib(szFileName, szExtensions);
+    return hModule;
+}
+
+lt_dlhandle
+lt_dlopenext(
+    const char *szFileName)
+{
+    const char* const szExtensions[] = { ".", ".la.", ".dll.", 0 };
+    lt_dlhandle hModule = LoadLib(szFileName, szExtensions);
+    return hModule;
+}
+
+int
+lt_dlclose(
+    lt_dlhandle handle)
+{
+    int cErrors = 0;
+    if (FreeLibrary((HMODULE)handle))
+    {
+        s_dwLastError = 0;
+    }
+    else
+    {
+        s_dwLastError = GetLastError();
+        cErrors++;
+    }
+
+    return cErrors;
+}
+
+lt_ptr
+lt_dlsym(
+    lt_dlhandle hModule,
+    const char *szSymbolName)
+{
+    lt_ptr pf = (lt_ptr)GetProcAddress((HMODULE)hModule, szSymbolName);
+    s_dwLastError = pf ? 0 : GetLastError();
+    return pf;
+}
+
+const char *
+lt_dlerror(void)
+{
+    if (!FormatMessageA(
+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        0,
+        s_dwLastError,
+        0,
+        s_szLastError,
+        _countof(s_szLastError),
+        0))
+    {
+        _snprintf(s_szLastError, _countof(s_szLastError), "Unknown error %u occurred.", s_dwLastError);
+    }
+
+    return s_szLastError;
+}
--- /dev/null
+++ b/src/win32-ltdl.h
@@ -1,0 +1,68 @@
+/* libSoX minimal libtool-ltdl for MS-Windows: (c) 2009 SoX contributors
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef LTDL_H
+#define LTDL_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LT_PATHSEP_CHAR ';'
+#define LT_DIRSEP_CHAR '\\'
+
+struct lt__handle;
+typedef struct lt__handle *lt_dlhandle;
+typedef void *lt_ptr;
+
+int
+lt_dlinit(void);
+
+int
+lt_dlexit(void);
+
+int
+lt_dlforeachfile(
+  const char *szSearchPath,
+  int (*pfCallback)(const char *szFileName, lt_ptr pData),
+  lt_ptr pData);
+
+lt_dlhandle
+lt_dlopen(
+  const char *szFileName);
+
+lt_dlhandle
+lt_dlopenext(
+  const char *szFileName);
+
+lt_ptr
+lt_dlsym(
+  lt_dlhandle hModule,
+  const char *szSymbolName);
+
+const char *
+lt_dlerror(void);
+
+int
+lt_dlclose(
+  lt_dlhandle handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef LTDL_H */