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 <[email protected]> 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 <[email protected]> + +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 <[email protected]> + +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,@vals) = split(/\t/,$line); chomp($vals[-1]); + $vals[-1] =~ s/\r$//; push @{$out{$pos}},join("\t",@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",@blines)."\nvs\n\t".join("\n\t",@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 _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
