[med-svn] [htslib] 04/10: Further Windows/Mingw/MSYS improvements.
Andreas Tille
tille at debian.org
Wed Jul 19 19:54:43 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository htslib.
commit 75d9f0d9a973898686a51b60277f239c7e729ea5
Author: James Bonfield <jkb at sanegr.ac.uk>
Date: Thu Apr 27 09:01:10 2017 +0100
Further Windows/Mingw/MSYS improvements.
- Added an AppVeyor config (travis equivalent for Windows).
- The test harness now copes with windows style pathnames under msys
by using 'cygpath'. You will likely already also need to set
MSYS2_ARG_CONV_EXCL=* environment variable prior to "make check".
Thanks to Anders Kaplan for hints at pathname handling.
https://github.com/anderskaplan/htslib/commit/0c52ae6711659e2cf072bb2a3de01bf6bf42c626
It also now handles nl vs cr-nl and the extra digits that appear in
printf %g output.
- Fixed the code looking for connect/recv calls. The previous
-lsocket check was incomplete but we also now work with -lws2_32
on windows.
- Setting of _POSIX_C_SOURCE=600 define so that snprintf return values
work and to enable %lld and %z formatting options.
- Fixed various shared library types in the Makefile. The existing
cygwin code there is unmodified, but also untested.
- Added hts_os.[ch] for operating system specific tweaks. This only
affects windows/mingw at the moment and includes various
drand/random implementations and a tweak to handle 1 less argument
in mkdir.
win/rand.[ch] contains a BSD implementation of the drand48 code,
which produces identical random numbers to linux (needed for the
tests to work).
- Added fseeko and fsync checks to autoconf with appropriate ifdefs in
the code.
- Cope with seek on pipes returning EINVAL instead of ESPIPE.
- Cope with the lack of SIGPIPE. We spot this is fd_write and raise a
SIGTERM instead in lieu of anything better to do.
- Additional enabling of O_BINARY mode in various places.
- Avoidance for enum / define clases in windows (cram block method
ERROR and MF_APPEND).
- Support for windows C:/path as a full pathname.
- Work around the gcc __format__ attribute requiring a different type
(printf vs gnu_printf).
---
.appveyor.yml | 43 +++++++++++++++++++++
INSTALL | 6 +++
Makefile | 25 +++++++++++-
bgzf.c | 4 ++
bgzip.c | 18 ++++++++-
configure.ac | 22 ++++++++---
cram/cram_io.c | 8 +++-
cram/cram_structs.h | 2 +-
cram/mFILE.h | 5 +++
cram/os.h | 7 +++-
errmod.c | 2 +
hfile.c | 26 +++++++++++--
hfile_libcurl.c | 4 +-
hts.c | 1 +
hts_os.c | 35 +++++++++++++++++
htslib/hts_defs.h | 12 ++++++
htslib/hts_os.h | 49 ++++++++++++++++++++++++
tabix.c | 2 +-
test/hfile.c | 2 +-
test/sam.c | 2 +-
test/tabix/test-tabix.sh | 7 ++--
test/test-bcf-sr.pl | 6 ++-
test/test.pl | 24 +++++++++++-
win/rand.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++
win/rand.h | 23 ++++++++++++
25 files changed, 407 insertions(+), 26 deletions(-)
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..f90c61d
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,43 @@
+# version format.
+# you can use {branch} name in version format too
+# version: 1.0.{build}-{branch}
+version: 'vers.{build}'
+
+# branches to build
+branches:
+ # Whitelist
+ only:
+ - develop
+
+ # Blacklist
+ except:
+ - gh-pages
+
+# Do not build on tags (GitHub and BitBucket)
+skip_tags: true
+
+# Skipping commits affecting specific files (GitHub only). More details here: /docs/appveyor-yml
+#skip_commits:
+# files:
+# - docs/*
+# - '**/*.html'
+
+# We use Mingw/Msys, so use pacman for installs
+install:
+ - set HOME=.
+ - set MSYSTEM=MINGW64
+ - set PATH=C:/msys64/usr/bin;C:/msys64/mingw64/bin;%PATH%
+ - set MINGWPREFIX=x86_64-w64-mingw32
+ - "sh -lc \"pacman -S --noconfirm --needed base-devel mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib mingw-w64-x86_64-bzip2 mingw-w64-x86_64-xz mingw-w64-x86_64-curl\""
+
+build_script:
+ - set HOME=.
+ - set MSYSTEM=MINGW64
+ - set PATH=C:/msys64/usr/bin;C:/msys64/mingw64/bin;%PATH%
+ - "sh -lc \"aclocal && autoheader && autoconf && ./configure && make -j2\""
+
+#build_script:
+# - make
+
+test_script:
+ - "sh -lc \"make test\""
diff --git a/INSTALL b/INSTALL
index 2413ba6..8d9c3b6 100644
--- a/INSTALL
+++ b/INSTALL
@@ -48,6 +48,12 @@ library is used. Systems that do not have CChmac will get this from
libcrypto. libcrypto is part of OpenSSL or one of its derivatives (LibreSSL
or BoringSSL).
+On Microsoft Windows we recommend use of Mingw64/Msys2. Note that
+currently for the test harness to work you will need to override the
+test temporary directory with e.g.: make check TEST_OPTS="-t C:/msys64/tmp/_"
+Whilst the code may work on Windows with other environments, these have
+not be verified.
+
Building Configure
==================
diff --git a/Makefile b/Makefile
index 9a44b62..da08cbf 100644
--- a/Makefile
+++ b/Makefile
@@ -138,6 +138,7 @@ print-version:
LIBHTS_OBJS = \
+ hts_os.o\
kfunc.o \
knetfile.o \
kstring.o \
@@ -208,6 +209,8 @@ config.h:
echo '/* Default config.h generated by Makefile */' > $@
echo '#define HAVE_LIBBZ2 1' >> $@
echo '#define HAVE_LIBLZMA 1' >> $@
+ echo '#define HAVE_FSEEKO 1' >> $@
+ echo '#define HAVE_DRAND48 1' >> $@
# And similarly for htslib.pc.tmp ("pkg-config template"). No dependency
# on htslib.pc.in listed, as if that file is newer the usual way to regenerate
@@ -235,6 +238,9 @@ lib-shared: libhts.dylib
else ifeq "$(findstring CYGWIN,$(PLATFORM))" "CYGWIN"
SHLIB_FLAVOUR = cygdll
lib-shared: cyghts-$(LIBHTS_SOVERSION).dll
+else ifeq "$(findstring MSYS,$(PLATFORM))" "MSYS"
+SHLIB_FLAVOUR = dll
+lib-shared: hts-$(LIBHTS_SOVERSION).dll
else
SHLIB_FLAVOUR = so
lib-shared: libhts.so
@@ -276,6 +282,9 @@ libhts.dylib: $(LIBHTS_OBJS)
cyghts-$(LIBHTS_SOVERSION).dll: $(LIBHTS_OBJS)
$(CC) -shared -Wl,--out-implib=libhts.dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import $(LDFLAGS) -o $@ -Wl,--whole-archive $(LIBHTS_OBJS) -Wl,--no-whole-archive $(LIBS) -lpthread
+hts-$(LIBHTS_SOVERSION).dll: $(LIBHTS_OBJS)
+ $(CC) -shared -Wl,--out-implib=hts.dll.a -Wl,--export-all-symbols -Wl,--enable-auto-import $(LDFLAGS) -o $@ -Wl,--whole-archive $(LIBHTS_OBJS) -Wl,--no-whole-archive $(LIBS) -lpthread
+
.pico.so:
$(CC) -shared -Wl,-E $(LDFLAGS) -o $@ $< $(LIBS) -lpthread
@@ -286,6 +295,9 @@ cyghts-$(LIBHTS_SOVERSION).dll: $(LIBHTS_OBJS)
.o.cygdll:
$(CC) -shared $(LDFLAGS) -o $@ $< libhts.dll.a $(LIBS)
+.o.dll:
+ $(CC) -shared $(LDFLAGS) -o $@ $< hts.dll.a $(LIBS)
+
bgzf.o bgzf.pico: bgzf.c config.h $(htslib_hts_h) $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_thread_pool_h) cram/pooled_alloc.h $(htslib_khash_h)
errmod.o errmod.pico: errmod.c config.h $(htslib_hts_h) $(htslib_ksort_h)
@@ -348,6 +360,9 @@ tabix.o: tabix.c config.h $(htslib_tbx_h) $(htslib_sam_h) $(htslib_vcf_h) $(htsl
# For tests that might use it, set $REF_PATH explicitly to use only reference
# areas within the test suite (or set it to ':' to use no reference areas).
+#
+# If using MSYS, avoid poor shell expansion via:
+# MSYS2_ARG_CONV_EXCL="*" make check
check test: $(BUILT_PROGRAMS) $(BUILT_TEST_PROGRAMS)
test/hts_endian
test/fieldarith test/fieldarith.sam
@@ -356,7 +371,7 @@ check test: $(BUILT_PROGRAMS) $(BUILT_TEST_PROGRAMS)
cd test/tabix && ./test-tabix.sh tabix.tst
REF_PATH=: test/sam test/ce.fa test/faidx.fa
test/test-regidx
- cd test && REF_PATH=: ./test.pl
+ cd test && REF_PATH=: ./test.pl $${TEST_OPTS:-}
test/hts_endian: test/hts_endian.o
$(CC) $(LDFLAGS) -o $@ test/hts_endian.o $(LIBS)
@@ -446,6 +461,10 @@ install-cygdll: cyghts-$(LIBHTS_SOVERSION).dll installdirs
$(INSTALL_PROGRAM) cyghts-$(LIBHTS_SOVERSION).dll $(DESTDIR)$(bindir)/cyghts-$(LIBHTS_SOVERSION).dll
$(INSTALL_PROGRAM) libhts.dll.a $(DESTDIR)$(libdir)/libhts.dll.a
+install-dll: hts-$(LIBHTS_SOVERSION).dll installdirs
+ $(INSTALL_PROGRAM) hts-$(LIBHTS_SOVERSION).dll $(DESTDIR)$(bindir)/hts-$(LIBHTS_SOVERSION).dll
+ $(INSTALL_PROGRAM) hts.dll.a $(DESTDIR)$(libdir)/hts.dll.a
+
install-dylib: libhts.dylib installdirs
$(INSTALL_PROGRAM) libhts.dylib $(DESTDIR)$(libdir)/libhts.$(PACKAGE_VERSION).dylib
ln -sf libhts.$(PACKAGE_VERSION).dylib $(DESTDIR)$(libdir)/libhts.dylib
@@ -483,6 +502,9 @@ clean-so:
clean-cygdll:
-rm -f cyghts-*.dll libhts.dll.a
+clean-dll:
+ -rm -f hts-*.dll hts.dll.a
+
clean-dylib:
-rm -f libhts.dylib libhts.*.dylib
@@ -510,4 +532,5 @@ force:
.PHONY: tags test testclean
.PHONY: clean-so install-so
.PHONY: clean-cygdll install-cygdll
+.PHONY: clean-dll install-dll
.PHONY: clean-dylib install-dylib
diff --git a/bgzf.c b/bgzf.c
index 7e80b8c..0f62173 100644
--- a/bgzf.c
+++ b/bgzf.c
@@ -1038,6 +1038,9 @@ static int bgzf_check_EOF_common(BGZF *fp)
off_t offset = htell(fp->fp);
if (hseek(fp->fp, -28, SEEK_END) < 0) {
if (errno == ESPIPE) { hclearerr(fp->fp); return 2; }
+#ifdef _WIN32
+ if (errno == EINVAL) { hclearerr(fp->fp); return 2; }
+#endif
else return -1;
}
if ( hread(fp->fp, buf, 28) != 28 ) return -1;
@@ -1179,6 +1182,7 @@ restart:
pthread_exit(NULL);
}
}
+ return NULL;
}
int bgzf_thread_pool(BGZF *fp, hts_tpool *pool, int qsize) {
diff --git a/bgzip.c b/bgzip.c
index e078185..931e7a0 100644
--- a/bgzip.c
+++ b/bgzip.c
@@ -36,6 +36,11 @@
#include "htslib/bgzf.h"
#include "htslib/hts.h"
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
static const int WINDOW_SIZE = 64 * 1024;
static void error(const char *format, ...)
@@ -198,6 +203,9 @@ int main(int argc, char **argv)
if ( index ) bgzf_index_build_init(fp);
buffer = malloc(WINDOW_SIZE);
+#ifdef _WIN32
+ _setmode(f_src, O_BINARY);
+#endif
if (rebgzip){
if ( bgzf_index_load(fp, index_fname, NULL) < 0 ) error("Could not load index: %s.gzi\n", argv[optind]);
@@ -319,13 +327,21 @@ int main(int argc, char **argv)
if ( bgzf_index_load(fp, argv[optind], ".gzi") < 0 ) error("Could not load index: %s.gzi\n", argv[optind]);
if ( bgzf_useek(fp, start, SEEK_SET) < 0 ) error("Could not seek to %d-th (uncompressd) byte\n", start);
}
+#ifdef _WIN32
+ _setmode(f_dst, O_BINARY);
+#endif
while (1) {
if (end < 0) c = bgzf_read(fp, buffer, WINDOW_SIZE);
else c = bgzf_read(fp, buffer, (end - start > WINDOW_SIZE)? WINDOW_SIZE:(end - start));
if (c == 0) break;
if (c < 0) error("Could not read %d bytes: Error %d\n", (end - start > WINDOW_SIZE)? WINDOW_SIZE:(end - start), fp->errcode);
start += c;
- if ( write(f_dst, buffer, c) != c ) error("Could not write %d bytes\n", c);
+ if ( write(f_dst, buffer, c) != c ) {
+#ifdef _WIN32
+ if (GetLastError() != ERROR_NO_DATA)
+#endif
+ error("Could not write %d bytes\n", c);
+ }
if (end >= 0 && start >= end) break;
}
free(buffer);
diff --git a/configure.ac b/configure.ac
index 308a5c1..5cfffaa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,6 +71,7 @@ AC_ARG_ENABLE([gcs],
[], [enable_gcs=check])
AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
AC_ARG_ENABLE([libcurl],
[AS_HELP_STRING([--enable-libcurl],
@@ -112,8 +113,8 @@ AC_ARG_ENABLE([s3],
[support Amazon AWS S3 URLs])],
[], [enable_s3=check])
-AC_MSG_CHECKING([shared library type])
test -n "$host_alias" || host_alias=unknown-`uname -s`
+AC_MSG_CHECKING([shared library type for $host_alias])
case $host_alias in
*-cygwin* | *-CYGWIN*)
host_result="Cygwin DLL"
@@ -125,6 +126,15 @@ case $host_alias in
PLATFORM=Darwin
PLUGIN_EXT=.bundle
;;
+ *-msys* | *-MSYS* | *-mingw* | *-MINGW*)
+ host_result="MSYS dll"
+ PLATFORM=MSYS
+ PLUGIN_EXT=.dll
+ # This also sets __USE_MINGW_ANSI_STDIO which in turn makes PRId64,
+ # %lld and %z printf formats work. It also enforces the snprintf to
+ # be C99 compliant so it returns the correct values (in kstring.c).
+ CPPFLAGS="$CPPCFLAGS -D_POSIX_C_SOURCE=600"
+ ;;
*)
host_result="plain .so"
PLATFORM=default
@@ -136,7 +146,7 @@ AC_SUBST([PLATFORM])
dnl FIXME This pulls in dozens of standard header checks
AC_FUNC_MMAP
-AC_CHECK_FUNCS(gmtime_r)
+AC_CHECK_FUNCS([gmtime_r fsync drand48])
# Darwin has a dubious fdatasync() symbol, but no declaration in <unistd.h>
AC_CHECK_DECL([fdatasync(int)], [AC_CHECK_FUNCS(fdatasync)])
@@ -183,9 +193,11 @@ FAILED. This error must be resolved in order to build HTSlib successfully.])
fi
dnl connect() etc. fns are in libc on linux, but libsocket on illumos/Solaris
-libsocket=unneeded
-AC_SEARCH_LIBS(connect, socket, [libsocket=needed], [])
-
+AC_SEARCH_LIBS([recv], [socket ws2_32], [
+if test "$ac_cv_search_recv" != "none required"
+then
+ static_LIBS="$static_LIBS $ac_cv_search_recv"
+fi], [AC_MSG_ERROR([unable to find the recv() function])])
if test "$enable_bz2" != no; then
bz2_devel=ok
diff --git a/cram/cram_io.c b/cram/cram_io.c
index 8e2f1ea..e2b416f 100644
--- a/cram/cram_io.c
+++ b/cram/cram_io.c
@@ -1446,7 +1446,7 @@ char *cram_block_method2str(enum cram_block_method m) {
case RANS0: return "RANS0";
case RANS1: return "RANS1";
case GZIP_RLE: return "GZIP_RLE";
- case ERROR: break;
+ case BM_ERROR: break;
}
return "?";
}
@@ -3663,7 +3663,11 @@ SAM_hdr *cram_read_SAM_hdr(cram_fd *fd) {
* Out must be at least PATH_MAX bytes long.
*/
static void full_path(char *out, char *in) {
- if (*in == '/') {
+ size_t in_l = strlen(in);
+ if (*in == '/' ||
+ // Windows paths
+ (in_l > 3 && toupper(*in) >= 'A' && toupper(*in) <= 'Z' &&
+ in[1] == ':' && (in[2] == '/' || in[2] == '\\'))) {
strncpy(out, in, PATH_MAX);
out[PATH_MAX-1] = 0;
} else {
diff --git a/cram/cram_structs.h b/cram/cram_structs.h
index 5165605..eeba679 100644
--- a/cram/cram_structs.h
+++ b/cram/cram_structs.h
@@ -192,7 +192,7 @@ typedef struct cram_file_def {
struct cram_slice;
enum cram_block_method {
- ERROR = -1,
+ BM_ERROR = -1,
RAW = 0,
GZIP = 1,
BZIP2 = 2,
diff --git a/cram/mFILE.h b/cram/mFILE.h
index 05a3a88..a6b067a 100644
--- a/cram/mFILE.h
+++ b/cram/mFILE.h
@@ -48,6 +48,11 @@ typedef struct {
size_t flush_pos;
} mFILE;
+// Work around a clash with winuser.h
+#ifdef MF_APPEND
+# undef MF_APPEND
+#endif
+
#define MF_READ 1
#define MF_WRITE 2
#define MF_APPEND 4
diff --git a/cram/os.h b/cram/os.h
index b1fdca6..ad3d441 100644
--- a/cram/os.h
+++ b/cram/os.h
@@ -205,9 +205,12 @@ static inline uint16_t le_int2(uint16_t x) {
* Microsoft Windows running MinGW
*/
#if defined(__MINGW32__)
-/* #define mkdir(filename,mode) mkdir((filename)) */
+#include <io.h>
+#define mkdir(filename,mode) mkdir((filename))
#define sysconf(x) 512
-#define ftruncate(fd,len) _chsize(fd,len)
+#ifndef ftruncate
+# define ftruncate(fd,len) _chsize(fd,len)
+#endif
#endif
/* Generic WIN32 API issues */
diff --git a/errmod.c b/errmod.c
index ee4823b..bb9fc28 100644
--- a/errmod.c
+++ b/errmod.c
@@ -28,6 +28,8 @@ DEALINGS IN THE SOFTWARE. */
#include <math.h>
#include "htslib/hts.h"
#include "htslib/ksort.h"
+#include "htslib/hts_os.h" // for drand48
+
KSORT_INIT_GENERIC(uint16_t)
struct errmod_t {
diff --git a/hfile.c b/hfile.c
index 57e2b89..ce0899e 100644
--- a/hfile.c
+++ b/hfile.c
@@ -526,6 +526,18 @@ static ssize_t fd_write(hFILE *fpv, const void *buffer, size_t nbytes)
n = fp->is_socket? send(fp->fd, buffer, nbytes, 0)
: write(fp->fd, buffer, nbytes);
} while (n < 0 && errno == EINTR);
+#ifdef _WIN32
+ // On windows we have no SIGPIPE. Instead write returns
+ // EINVAL. We check for this and our fd being a pipe.
+ // If so, we raise SIGTERM instead of SIGPIPE. It's not
+ // ideal, but I think the only alternative is extra checking
+ // in every single piece of code.
+ if (n < 0 && errno == EINVAL &&
+ GetLastError() == ERROR_NO_DATA &&
+ GetFileType((HANDLE)_get_osfhandle(fp->fd)) == FILE_TYPE_PIPE) {
+ raise(SIGTERM);
+ }
+#endif
return n;
}
@@ -537,12 +549,13 @@ static off_t fd_seek(hFILE *fpv, off_t offset, int whence)
static int fd_flush(hFILE *fpv)
{
- hFILE_fd *fp = (hFILE_fd *) fpv;
- int ret;
+ int ret = 0;
do {
#ifdef HAVE_FDATASYNC
+ hFILE_fd *fp = (hFILE_fd *) fpv;
ret = fdatasync(fp->fd);
-#else
+#elif defined(HAVE_FSYNC)
+ hFILE_fd *fp = (hFILE_fd *) fpv;
ret = fsync(fp->fd);
#endif
// Ignore invalid-for-fsync(2) errors due to being, e.g., a pipe,
@@ -616,7 +629,11 @@ hFILE *hdopen(int fd, const char *mode)
static hFILE *hopen_fd_fileuri(const char *url, const char *mode)
{
if (strncmp(url, "file://localhost/", 17) == 0) url += 16;
+#ifdef _WIN32
+ else if (strncmp(url, "file:///", 8) == 0) url += 8;
+#else
else if (strncmp(url, "file:///", 8) == 0) url += 7;
+#endif
else { errno = EPROTONOSUPPORT; return NULL; }
return hopen_fd(url, mode);
@@ -876,7 +893,8 @@ static const struct hFILE_scheme_handler *find_scheme_handler(const char *s)
else if (s[i] == ':') break;
else return NULL;
- if (i == 0 || i >= sizeof scheme) return NULL;
+ // 1 byte schemes are likely windows C:/foo pathnames
+ if (i <= 1 || i >= sizeof scheme) return NULL;
scheme[i] = '\0';
pthread_mutex_lock(&plugins_lock);
diff --git a/hfile_libcurl.c b/hfile_libcurl.c
index ea99aa7..461e891 100644
--- a/hfile_libcurl.c
+++ b/hfile_libcurl.c
@@ -28,7 +28,9 @@ DEALINGS IN THE SOFTWARE. */
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <sys/select.h>
+#ifndef _WIN32
+# include <sys/select.h>
+#endif
#include "hfile_internal.h"
#ifdef ENABLE_PLUGINS
diff --git a/hts.c b/hts.c
index 1c6ca8a..fe35d78 100644
--- a/hts.c
+++ b/hts.c
@@ -44,6 +44,7 @@ DEALINGS IN THE SOFTWARE. */
#include "version.h"
#include "hts_internal.h"
#include "hfile_internal.h"
+#include "htslib/hts_os.h" // drand48
#include "htslib/khash.h"
#include "htslib/kseq.h"
diff --git a/hts_os.c b/hts_os.c
new file mode 100644
index 0000000..eb0a5ca
--- /dev/null
+++ b/hts_os.c
@@ -0,0 +1,35 @@
+/// @file hts_os.c
+/// Operating System specific tweaks, for compatibility with POSIX.
+/*
+ Copyright (C) 2017 Genome Research Ltd.
+
+ Author: James Bonfield <jkb at sanger.ac.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. */
+
+// Windows (maybe more) lack a drand48 implementation.
+#ifndef HAVE_DRAND48
+#include "win/rand.c"
+#endif
+
+// // On Windows when using the MSYS or Cygwin terminals, isatty fails
+// #ifdef _WIN32
+// #define USE_FILEEXTD
+// #include "win/iscygpty.c"
+// #endif
diff --git a/htslib/hts_defs.h b/htslib/hts_defs.h
index 1602303..5a8d921 100644
--- a/htslib/hts_defs.h
+++ b/htslib/hts_defs.h
@@ -69,6 +69,18 @@ DEALINGS IN THE SOFTWARE. */
#define HTS_DEPRECATED(message)
#endif
+// On mingw the "printf" format type doesn't work. It needs "gnu_printf"
+// in order to check %lld and %z, otherwise it defaults to checking against
+// the Microsoft library printf format options despite linking against the
+// GNU posix implementation of printf. The __MINGW_PRINTF_FORMAT macro
+// expands to printf or gnu_printf as required, but obviously may not
+// exist
+#ifdef __MINGW_PRINTF_FORMAT
+#define HTS_PRINTF_FMT __MINGW_PRINTF_FORMAT
+#else
+#define HTS_PRINTF_FMT printf
+#endif
+
#if HTS_COMPILER_HAS(__format__) || HTS_GCC_AT_LEAST(3,0)
#define HTS_FORMAT(type, idx, first) __attribute__((__format__ (type, idx, first)))
#else
diff --git a/htslib/hts_os.h b/htslib/hts_os.h
new file mode 100644
index 0000000..edb23a2
--- /dev/null
+++ b/htslib/hts_os.h
@@ -0,0 +1,49 @@
+/// @file hts_os.h
+/// Operating System specific tweaks, for compatibility with POSIX.
+/*
+ Copyright (C) 2017 Genome Research Ltd.
+
+ Author: James Bonfield <jkb at sanger.ac.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. */
+
+#ifndef HTSLIB_HTS_OS_H
+#define HTSLIB_HTS_OS_H
+
+extern void srand48(long seed);
+extern double drand48(void);
+extern long lrand48(void);
+
+#ifdef _WIN32
+/* Check if the fd is a cygwin/msys's pty. */
+extern int is_cygpty(int fd);
+#endif
+
+#if defined(__MINGW32__)
+#include <io.h>
+#define mkdir(filename,mode) mkdir((filename))
+#endif
+
+#ifdef _WIN32
+#include <stdlib.h>
+#define srandom srand
+#define random rand
+#endif
+
+#endif
diff --git a/tabix.c b/tabix.c
index 681f8a0..119f396 100644
--- a/tabix.c
+++ b/tabix.c
@@ -29,6 +29,7 @@ DEALINGS IN THE SOFTWARE. */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <strings.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -69,7 +70,6 @@ static void error(const char *format, ...)
int file_type(const char *fname)
{
int l = strlen(fname);
- int strcasecmp(const char *s1, const char *s2);
if (l>=7 && strcasecmp(fname+l-7, ".gff.gz") == 0) return IS_GFF;
else if (l>=7 && strcasecmp(fname+l-7, ".bed.gz") == 0) return IS_BED;
else if (l>=7 && strcasecmp(fname+l-7, ".sam.gz") == 0) return IS_SAM;
diff --git a/test/hfile.c b/test/hfile.c
index 358ac70..577b817 100644
--- a/test/hfile.c
+++ b/test/hfile.c
@@ -61,7 +61,7 @@ char *slurp(const char *filename)
{
char *text;
struct stat sbuf;
- size_t filesize, readsize;
+ size_t filesize;
FILE *f = fopen(filename, "rb");
if (f == NULL) fail("fopen(\"%s\", \"rb\")", filename);
if (fstat(fileno(f), &sbuf) != 0) fail("fstat(\"%s\")", filename);
diff --git a/test/sam.c b/test/sam.c
index 736281d..dd83336 100644
--- a/test/sam.c
+++ b/test/sam.c
@@ -43,7 +43,7 @@ DEALINGS IN THE SOFTWARE. */
int status;
-static void HTS_FORMAT(printf, 1, 2) fail(const char *fmt, ...)
+static void HTS_FORMAT(HTS_PRINTF_FMT, 1, 2) fail(const char *fmt, ...)
{
va_list args;
diff --git a/test/tabix/test-tabix.sh b/test/tabix/test-tabix.sh
index 358a3dd..4a4b045 100755
--- a/test/tabix/test-tabix.sh
+++ b/test/tabix/test-tabix.sh
@@ -57,11 +57,12 @@ run_test() {
y="exit_code"
elif [ "x$e" != "x" -a "$e" != "." ]
then
- if cmp -s _out.tmp "$e"
+ sed -n 's/.*/&/p' _out.tmp > _out.tmp2
+ if cmp -s _out.tmp2 "$e"
then
# Output was as expected
r="P"
- rm -f _out.tmp _err.tmp
+ rm -f _out.tmp _out.tmp2 _err.tmp
else
# Output differed
r="F"
@@ -70,7 +71,7 @@ run_test() {
else
# Expected zero exit code and got it.
r="P"
- rm -f _out.tmp _err.tmp
+ rm -f _out.tmp _out.tmp2 _err.tmp
fi
if [ "$r" = "F" ]
diff --git a/test/test-bcf-sr.pl b/test/test-bcf-sr.pl
index 8f78acb..3102cdd 100755
--- a/test/test-bcf-sr.pl
+++ b/test/test-bcf-sr.pl
@@ -156,6 +156,7 @@ sub check_outputs
{
my ($pos, at vals) = split(/\t/,$line);
chomp($vals[-1]);
+ $vals[-1] =~ s/\r$//;
push @{$out{$pos}},join("\t", at vals);
}
close($fh) or error("close failed: $fname_bin");
@@ -173,6 +174,7 @@ sub check_outputs
while (my $line=<$fh>)
{
chomp($line);
+ $line =~ s/\r$//;
push @plines,$line;
}
close($fh) or error("close failed: $fname_perl");
@@ -181,8 +183,8 @@ sub check_outputs
@plines = sort @plines;
for (my $i=0; $i<@plines; $i++)
{
- if ( $blines[$i] ne $plines[$i] )
- {
+ if ( $blines[$i] ne $plines[$i] )
+ {
#error("Different lines in $fname_bin vs $fname_perl:\n\t$blines[$i].\nvs\n\t$plines[$i].\n");
error("Different lines in $fname_bin vs $fname_perl:\n\t".join("\n\t", at blines)."\nvs\n\t".join("\n\t", at plines)."\n");
}
diff --git a/test/test.pl b/test/test.pl
index 261ca98..f168135 100755
--- a/test/test.pl
+++ b/test/test.pl
@@ -69,6 +69,23 @@ sub error
"\n";
exit 1;
}
+
+sub cygpath {
+ my ($path) = @_;
+ $path = `cygpath -m $path`;
+ $path =~ s/\r?\n//;
+ return $path
+}
+
+sub safe_tempdir
+{
+ my $dir = tempdir(CLEANUP=>1);
+ if ($^O =~ /^msys/) {
+ $dir = cygpath($dir);
+ }
+ return $dir;
+}
+
sub parse_params
{
my $opts = { keep_files=>0, nok=>0, nfailed=>0 };
@@ -81,11 +98,16 @@ sub parse_params
'h|?|help' => \$help
);
if ( !$ret or $help ) { error(); }
- $$opts{tmp} = $$opts{keep_files} ? $$opts{keep_files} : tempdir(CLEANUP=>1);
+ $$opts{tmp} = $$opts{keep_files} ? $$opts{keep_files} : safe_tempdir();
if ( $$opts{keep_files} ) { cmd("mkdir -p $$opts{keep_files}"); }
$$opts{path} = $FindBin::RealBin;
$$opts{bin} = $FindBin::RealBin;
$$opts{bin} =~ s{/test/?$}{};
+ if ($^O =~ /^msys/) {
+ $$opts{path} = cygpath($$opts{path});
+ $$opts{bin} = cygpath($$opts{bin});
+ }
+
return $opts;
}
sub _cmd
diff --git a/win/rand.c b/win/rand.c
new file mode 100644
index 0000000..c8d54ab
--- /dev/null
+++ b/win/rand.c
@@ -0,0 +1,98 @@
+/* rand.c -- drand48 implementation from the FreeBSD source tree. */
+
+// This file is an amalgamation of the many small files in FreeBSD to do with
+// drand48 and friends implementations.
+// It comprises _rand48.c, rand48.h, srand48.c, drand48.c, erand48.c, lrand48.c
+
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+//#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: src/lib/libc/gen/_rand48.c,v 1.2 2002/03/22 21:52:05 obrien Exp $");
+
+#include <math.h>
+#include "win/rand.h"
+
+#define RAND48_SEED_0 (0x330e)
+#define RAND48_SEED_1 (0xabcd)
+#define RAND48_SEED_2 (0x1234)
+#define RAND48_MULT_0 (0xe66d)
+#define RAND48_MULT_1 (0xdeec)
+#define RAND48_MULT_2 (0x0005)
+#define RAND48_ADD (0x000b)
+
+unsigned short _rand48_seed[3] = {
+ RAND48_SEED_0,
+ RAND48_SEED_1,
+ RAND48_SEED_2
+};
+unsigned short _rand48_mult[3] = {
+ RAND48_MULT_0,
+ RAND48_MULT_1,
+ RAND48_MULT_2
+};
+unsigned short _rand48_add = RAND48_ADD;
+
+static void
+_dorand48(unsigned short xseed[3])
+{
+ unsigned long accu;
+ unsigned short temp[2];
+
+ accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
+ (unsigned long) _rand48_add;
+ temp[0] = (unsigned short) accu; /* lower 16 bits */
+ accu >>= sizeof(unsigned short) * 8;
+ accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
+ (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
+ temp[1] = (unsigned short) accu; /* middle 16 bits */
+ accu >>= sizeof(unsigned short) * 8;
+ accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
+ xseed[0] = temp[0];
+ xseed[1] = temp[1];
+ xseed[2] = (unsigned short) accu;
+}
+
+void
+srand48(long seed)
+{
+ _rand48_seed[0] = RAND48_SEED_0;
+ _rand48_seed[1] = (unsigned short) seed;
+ _rand48_seed[2] = (unsigned short) (seed >> 16);
+ _rand48_mult[0] = RAND48_MULT_0;
+ _rand48_mult[1] = RAND48_MULT_1;
+ _rand48_mult[2] = RAND48_MULT_2;
+ _rand48_add = RAND48_ADD;
+}
+
+double
+erand48(unsigned short xseed[3])
+{
+ _dorand48(xseed);
+ return ldexp((double) xseed[0], -48) +
+ ldexp((double) xseed[1], -32) +
+ ldexp((double) xseed[2], -16);
+}
+
+double
+drand48(void)
+{
+ return erand48(_rand48_seed);
+}
+
+long
+lrand48(void)
+{
+ _dorand48(_rand48_seed);
+ return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
+}
diff --git a/win/rand.h b/win/rand.h
new file mode 100644
index 0000000..1a36daa
--- /dev/null
+++ b/win/rand.h
@@ -0,0 +1,23 @@
+/* rand.h -- drand48 implementation from the FreeBSD source tree. */
+
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#ifndef HTSLIB_HTS_RAND_H
+#define HTSLIB_HTS_RAND_H
+
+void srand48(long seed);
+double drand48(void);
+long lrand48(void);
+
+#endif /* HTSLIB_HTS_RAND_H */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/htslib.git
More information about the debian-med-commit
mailing list