[babl/wip/msvc: 11/20] babl: Build dirent for Visual Studio



commit ea4f9f9e79bfd17837f364b1a9c1d7b805fdf458
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Mon Jan 20 17:05:15 2020 +0800

    babl: Build dirent for Visual Studio
    
    The dirent headers and implementations are not available on Visual Studio,
    so use the implementation that is in GLib which is taken from
    mingw-3.3-runtime and released into the public domain, so that we have a dirent
    implementation that is ready for our use

 babl/dirent/README     |   2 +
 babl/dirent/dirent-zip |  19 +++
 babl/dirent/dirent.c   | 341 +++++++++++++++++++++++++++++++++++++++++++++++++
 babl/dirent/dirent.h   | 127 ++++++++++++++++++
 babl/dirent/wdirent.c  |   3 +
 babl/meson.build       |  12 +-
 6 files changed, 502 insertions(+), 2 deletions(-)
---
diff --git a/babl/dirent/README b/babl/dirent/README
new file mode 100644
index 000000000..e31ac1f90
--- /dev/null
+++ b/babl/dirent/README
@@ -0,0 +1,2 @@
+This is dirent from mingw-runtime-3.3, separated for MSVC user's
+benefit.
diff --git a/babl/dirent/dirent-zip b/babl/dirent/dirent-zip
new file mode 100644
index 000000000..7301987eb
--- /dev/null
+++ b/babl/dirent/dirent-zip
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Build developer package for the dirent library.
+
+ZIP=/tmp/dirent.zip
+
+mkdir -p dist/include dist/lib
+cp dirent.h dist/include
+cp dirent.lib dist/lib
+
+(cd dist
+rm $ZIP
+zip $ZIP -@ <<EOF
+include/dirent.h
+lib/dirent.lib
+EOF
+)
+
+rm -rf dist
diff --git a/babl/dirent/dirent.c b/babl/dirent/dirent.c
new file mode 100644
index 000000000..26b6cb1e5
--- /dev/null
+++ b/babl/dirent/dirent.c
@@ -0,0 +1,341 @@
+/*
+ * dirent.c
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is a part of the mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within the package.
+ *
+ * Derived from DIRLIB.C by Matt J. Weinstein
+ * This note appears in the DIRLIB.H
+ * DIRLIB.H by M. J. Weinstein   Released to public domain 1-Jan-89
+ *
+ * Updated by Jeremy Bettis <jeremy hksys com>
+ * Significantly revised and rewinddir, seekdir and telldir added by Colin
+ * Peters <colin fu is saga-u ac jp>
+ *     
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <io.h>
+#include <direct.h>
+
+#include "dirent.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h> /* for GetFileAttributes */
+
+#include <tchar.h>
+
+#ifdef _UNICODE
+#define _tdirent       _wdirent
+#define _TDIR          _WDIR
+#define _topendir      _wopendir
+#define _tclosedir     _wclosedir
+#define _treaddir      _wreaddir
+#define _trewinddir    _wrewinddir
+#define _ttelldir      _wtelldir
+#define _tseekdir      _wseekdir
+#else
+#define _tdirent       dirent
+#define _TDIR          DIR
+#define _topendir      opendir
+#define _tclosedir     closedir
+#define _treaddir      readdir
+#define _trewinddir    rewinddir
+#define _ttelldir      telldir
+#define _tseekdir      seekdir
+#endif
+
+#define SUFFIX _T("*")
+#define        SLASH   _T("\\")
+
+
+/*
+ * opendir
+ *
+ * Returns a pointer to a DIR structure appropriately filled in to begin
+ * searching a directory.
+ */
+_TDIR *
+_topendir (const _TCHAR *szPath)
+{
+  _TDIR *nd;
+  unsigned int rc;
+  _TCHAR szFullPath[MAX_PATH];
+       
+  errno = 0;
+
+  if (!szPath)
+    {
+      errno = EFAULT;
+      return (_TDIR *) 0;
+    }
+
+  if (szPath[0] == _T('\0'))
+    {
+      errno = ENOTDIR;
+      return (_TDIR *) 0;
+    }
+
+  /* Attempt to determine if the given path really is a directory. */
+  rc = GetFileAttributes (szPath);
+  if (rc == (unsigned int)-1)
+    {
+      /* call GetLastError for more error info */
+      errno = ENOENT;
+      return (_TDIR *) 0;
+    }
+  if (!(rc & FILE_ATTRIBUTE_DIRECTORY))
+    {
+      /* Error, entry exists but not a directory. */
+      errno = ENOTDIR;
+      return (_TDIR *) 0;
+    }
+
+  /* Make an absolute pathname.  */
+  _tfullpath (szFullPath, szPath, MAX_PATH);
+
+  /* Allocate enough space to store DIR structure and the complete
+   * directory path given. */
+  nd = (_TDIR *) malloc (sizeof (_TDIR) + (_tcslen(szFullPath) + _tcslen (SLASH) +
+                        _tcslen(SUFFIX) + 1) * sizeof(_TCHAR));
+
+  if (!nd)
+    {
+      /* Error, out of memory. */
+      errno = ENOMEM;
+      return (_TDIR *) 0;
+    }
+
+  /* Create the search expression. */
+  _tcscpy (nd->dd_name, szFullPath);
+
+  /* Add on a slash if the path does not end with one. */
+  if (nd->dd_name[0] != _T('\0') &&
+      nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('/') &&
+      nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('\\'))
+    {
+      _tcscat (nd->dd_name, SLASH);
+    }
+
+  /* Add on the search pattern */
+  _tcscat (nd->dd_name, SUFFIX);
+
+  /* Initialize handle to -1 so that a premature closedir doesn't try
+   * to call _findclose on it. */
+  nd->dd_handle = -1;
+
+  /* Initialize the status. */
+  nd->dd_stat = 0;
+
+  /* Initialize the dirent structure. ino and reclen are invalid under
+   * Win32, and name simply points at the appropriate part of the
+   * findfirst_t structure. */
+  nd->dd_dir.d_ino = 0;
+  nd->dd_dir.d_reclen = 0;
+  nd->dd_dir.d_namlen = 0;
+  memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
+
+  return nd;
+}
+
+
+/*
+ * readdir
+ *
+ * Return a pointer to a dirent structure filled with the information on the
+ * next entry in the directory.
+ */
+struct _tdirent *
+_treaddir (_TDIR * dirp)
+{
+  errno = 0;
+
+  /* Check for valid DIR struct. */
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return (struct _tdirent *) 0;
+    }
+
+  if (dirp->dd_stat < 0)
+    {
+      /* We have already returned all files in the directory
+       * (or the structure has an invalid dd_stat). */
+      return (struct _tdirent *) 0;
+    }
+  else if (dirp->dd_stat == 0)
+    {
+      /* We haven't started the search yet. */
+      /* Start the search */
+      dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta));
+
+         if (dirp->dd_handle == -1)
+       {
+         /* Whoops! Seems there are no files in that
+          * directory. */
+         dirp->dd_stat = -1;
+       }
+      else
+       {
+         dirp->dd_stat = 1;
+       }
+    }
+  else
+    {
+      /* Get the next search entry. */
+      if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta)))
+       {
+         /* We are off the end or otherwise error.     
+            _findnext sets errno to ENOENT if no more file
+            Undo this. */
+         DWORD winerr = GetLastError();
+         if (winerr == ERROR_NO_MORE_FILES)
+           errno = 0;  
+         _findclose (dirp->dd_handle);
+         dirp->dd_handle = -1;
+         dirp->dd_stat = -1;
+       }
+      else
+       {
+         /* Update the status to indicate the correct
+          * number. */
+         dirp->dd_stat++;
+       }
+    }
+
+  if (dirp->dd_stat > 0)
+    {
+      /* Successfully got an entry. Everything about the file is
+       * already appropriately filled in except the length of the
+       * file name. */
+      dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dta.name);
+      _tcscpy (dirp->dd_dir.d_name, dirp->dd_dta.name);
+      return &dirp->dd_dir;
+    }
+
+  return (struct _tdirent *) 0;
+}
+
+
+/*
+ * closedir
+ *
+ * Frees up resources allocated by opendir.
+ */
+int
+_tclosedir (_TDIR * dirp)
+{
+  int rc;
+
+  errno = 0;
+  rc = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+
+  if (dirp->dd_handle != -1)
+    {
+      rc = _findclose (dirp->dd_handle);
+    }
+
+  /* Delete the dir structure. */
+  free (dirp);
+
+  return rc;
+}
+
+/*
+ * rewinddir
+ *
+ * Return to the beginning of the directory "stream". We simply call findclose
+ * and then reset things like an opendir.
+ */
+void
+_trewinddir (_TDIR * dirp)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return;
+    }
+
+  if (dirp->dd_handle != -1)
+    {
+      _findclose (dirp->dd_handle);
+    }
+
+  dirp->dd_handle = -1;
+  dirp->dd_stat = 0;
+}
+
+/*
+ * telldir
+ *
+ * Returns the "position" in the "directory stream" which can be used with
+ * seekdir to go back to an old entry. We simply return the value in stat.
+ */
+long
+_ttelldir (_TDIR * dirp)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return -1;
+    }
+  return dirp->dd_stat;
+}
+
+/*
+ * seekdir
+ *
+ * Seek to an entry previously returned by telldir. We rewind the directory
+ * and call readdir repeatedly until either dd_stat is the position number
+ * or -1 (off the end). This is not perfect, in that the directory may
+ * have changed while we weren't looking. But that is probably the case with
+ * any such system.
+ */
+void
+_tseekdir (_TDIR * dirp, long lPos)
+{
+  errno = 0;
+
+  if (!dirp)
+    {
+      errno = EFAULT;
+      return;
+    }
+
+  if (lPos < -1)
+    {
+      /* Seeking to an invalid position. */
+      errno = EINVAL;
+      return;
+    }
+  else if (lPos == -1)
+    {
+      /* Seek past end. */
+      if (dirp->dd_handle != -1)
+       {
+         _findclose (dirp->dd_handle);
+       }
+      dirp->dd_handle = -1;
+      dirp->dd_stat = -1;
+    }
+  else
+    {
+      /* Rewind and read forward to the appropriate index. */
+      _trewinddir (dirp);
+
+      while ((dirp->dd_stat < lPos) && _treaddir (dirp))
+       ;
+    }
+}
diff --git a/babl/dirent/dirent.h b/babl/dirent/dirent.h
new file mode 100644
index 000000000..237665b4e
--- /dev/null
+++ b/babl/dirent/dirent.h
@@ -0,0 +1,127 @@
+/*
+ * DIRENT.H (formerly DIRLIB.H)
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is a part of the mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER within the package.
+ *
+ */
+#ifndef _DIRENT_H_
+#define _DIRENT_H_
+
+#include <stdio.h>
+#include <io.h>
+
+#ifndef RC_INVOKED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dirent
+{
+       long            d_ino;          /* Always zero. */
+       unsigned short  d_reclen;       /* Always zero. */
+       unsigned short  d_namlen;       /* Length of name in d_name. */
+       char            d_name[FILENAME_MAX]; /* File name. */
+};
+
+#ifdef _WIN64
+#define INTPTR __int64
+#else
+#define INTPTR long
+#endif
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ * dd_stat field is now int (was short in older versions).
+ */
+typedef struct
+{
+       /* disk transfer area for this dir */
+       struct _finddata_t      dd_dta;
+
+       /* dirent struct to return from dir (NOTE: this makes this thread
+        * safe as long as only one thread uses a particular DIR struct at
+        * a time) */
+       struct dirent           dd_dir;
+
+       /* _findnext handle */
+       INTPTR                  dd_handle;
+
+       /*
+         * Status of search:
+        *   0 = not started yet (next entry to read is first entry)
+        *  -1 = off the end
+        *   positive = 0 based index of next entry
+        */
+       int                     dd_stat;
+
+       /* given path for dir with search pattern (struct is extended) */
+       char                    dd_name[1];
+} DIR;
+
+DIR* __cdecl opendir (const char*);
+struct dirent* __cdecl readdir (DIR*);
+int __cdecl closedir (DIR*);
+void __cdecl rewinddir (DIR*);
+long __cdecl telldir (DIR*);
+void __cdecl seekdir (DIR*, long);
+
+
+/* wide char versions */
+
+struct _wdirent
+{
+       long            d_ino;          /* Always zero. */
+       unsigned short  d_reclen;       /* Always zero. */
+       unsigned short  d_namlen;       /* Length of name in d_name. */
+       wchar_t         d_name[FILENAME_MAX]; /* File name. */
+};
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ */
+typedef struct
+{
+       /* disk transfer area for this dir */
+       struct _wfinddata_t     dd_dta;
+
+       /* dirent struct to return from dir (NOTE: this makes this thread
+        * safe as long as only one thread uses a particular DIR struct at
+        * a time) */
+       struct _wdirent         dd_dir;
+
+       /* _findnext handle */
+       INTPTR                  dd_handle;
+
+       /*
+         * Status of search:
+        *   0 = not started yet (next entry to read is first entry)
+        *  -1 = off the end
+        *   positive = 0 based index of next entry
+        */
+       int                     dd_stat;
+
+       /* given path for dir with search pattern (struct is extended) */
+       wchar_t                 dd_name[1];
+} _WDIR;
+
+
+
+_WDIR* __cdecl _wopendir (const wchar_t*);
+struct _wdirent*  __cdecl _wreaddir (_WDIR*);
+int __cdecl _wclosedir (_WDIR*);
+void __cdecl _wrewinddir (_WDIR*);
+long __cdecl _wtelldir (_WDIR*);
+void __cdecl _wseekdir (_WDIR*, long);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Not RC_INVOKED */
+
+#endif /* Not _DIRENT_H_ */
diff --git a/babl/dirent/wdirent.c b/babl/dirent/wdirent.c
new file mode 100644
index 000000000..098d8542e
--- /dev/null
+++ b/babl/dirent/wdirent.c
@@ -0,0 +1,3 @@
+#define _UNICODE 1
+#define UNICODE 1
+#include "dirent.c"
diff --git a/babl/meson.build b/babl/meson.build
index ffe36a5a7..c86fbacc5 100644
--- a/babl/meson.build
+++ b/babl/meson.build
@@ -29,6 +29,14 @@ babl_c_args = [
   '-DLIBDIR="@0@"'.format(babl_libdir),
 ]
 
+if cc.get_id() == 'msvc'
+  bablExtraInclude = include_directories('dirent')
+  babl_extra_sources = [ 'dirent/dirent.c' ]
+else
+  bablExtraInclude = []
+  babl_extra_sources = []
+endif
+
 # Linker arguments
 if cc.get_id() != 'msvc'
   if cc.links('', name: '-Wl,--version-script', args: ['-shared', '-Wl,--version-script=' + 
babl_gnu_sym_path])
@@ -138,8 +146,8 @@ install_headers(babl_headers,
 
 babl = library(
   lib_name,
-  babl_sources,
-  include_directories: [ rootInclude, bablBaseInclude],
+  babl_sources, babl_extra_sources,
+  include_directories: [ rootInclude, bablBaseInclude, bablExtraInclude],
   c_args: babl_c_args,
   link_whole: [ babl_base, ],
   link_args: [ babl_link_args, ],


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]