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 */