p9y
authorMichael Wallner <mike@php.net>
Thu, 3 Dec 2020 13:24:40 +0000 (14:24 +0100)
committerMichael Wallner <mike@php.net>
Thu, 3 Dec 2020 18:09:40 +0000 (19:09 +0100)
53 files changed:
CMake/_Include.cmake
include/libmemcached-1.0/configure.h.in
include/libmemcached-1.0/memcached.h
include/libmemcached-1.0/platform.h
src/CMakeLists.txt
src/bin/CMakeLists.txt
src/bin/common/CMakeLists.txt
src/bin/common/options.hpp
src/bin/memcapable.cc
src/bin/memcp.cc
src/libmemcached/CMakeLists.txt
src/libmemcached/behavior.cc
src/libmemcached/common.h
src/libmemcached/connect.cc
src/libmemcached/flush_buffers.cc
src/libmemcached/get.cc
src/libmemcached/hash.cc
src/libmemcached/hosts.cc
src/libmemcached/instance.cc
src/libmemcached/io.cc
src/libmemcached/parse.cc
src/libmemcached/poll.cc [deleted file]
src/libmemcached/poll.h [deleted file]
src/libmemcached/purge.cc
src/libmemcached/response.cc
src/libmemcached/sasl.cc
src/libmemcached/server.cc
src/libmemcached/server.hpp
src/libmemcached/socket.hpp [deleted file]
src/libmemcached/windows.hpp [deleted file]
src/libmemcachedprotocol/CMakeLists.txt
src/libmemcachedprotocol/binary_handler.c
src/libmemcachedprotocol/common.h
src/libmemcachedprotocol/handler.c
src/p9y/CMakeLists.txt [new file with mode: 0644]
src/p9y/getopt.c [new file with mode: 0644]
src/p9y/getopt.hpp [new file with mode: 0644]
src/p9y/gettimeofday.cpp [new file with mode: 0644]
src/p9y/gettimeofday.hpp [new file with mode: 0644]
src/p9y/index.hpp [new file with mode: 0644]
src/p9y/libgen.c [new file with mode: 0644]
src/p9y/libgen.hpp [new file with mode: 0644]
src/p9y/p9y.cpp [new file with mode: 0644]
src/p9y/poll.c [new file with mode: 0644]
src/p9y/poll.hpp [new file with mode: 0644]
src/p9y/random.hpp [new file with mode: 0644]
src/p9y/realpath.c [new file with mode: 0644]
src/p9y/realpath.hpp [new file with mode: 0644]
src/p9y/socket.c [new file with mode: 0644]
src/p9y/socket.hpp [new file with mode: 0644]
src/win32/getopt.c [deleted file]
src/win32/getopt.h [deleted file]
test/lib/common.hpp

index 6f9a092bf641f40e67651db01c86f85e7abda741..a419d8dfdc0b023fff9106e7b3ef8635807764f9 100644 (file)
@@ -136,12 +136,17 @@ check_type("struct msghdr" sys/socket.h)
 
 check_cxx_symbol(abi::__cxa_demangle cxxabi.h)
 check_symbol(fcntl fcntl.h)
+check_symbol(gettimeofday sys/time.h)
 check_symbol(htonll arpa/inet.h)
+check_symbol(index strings.h)
 check_symbol(MSG_DONTWAIT sys/socket.h)
 check_symbol(MSG_MORE sys/socket.h)
 check_symbol(MSG_NOSIGNAL sys/socket.h)
 check_symbol(SO_RCVTIMEO sys/socket.h)
 check_symbol(SO_SNDTIMEO sys/socket.h)
+check_symbol(rand stdlib.h)
+check_symbol(random stdlib.h)
+check_symbol(realpath stdlib.h)
 check_symbol(sendmsg sys/socket.h)
 check_symbol(setenv stdlib.h)
 check_symbol(strerror_r string.h)
index fcda4200754e6a039f6a04f1e620cd5e9b5cc191..dfa55ebaa5dbae20d09c3e33748f9fcd994a33ad 100644 (file)
@@ -18,6 +18,8 @@
 #cmakedefine01 LIBMEMCACHED_ENABLE_DEPRECATED
 #cmakedefine01 LIBMEMCACHED_WITH_SASL_SUPPORT
 
+#cmakedefine HAVE_VISIBILITY 1
+
 #cmakedefine HAVE_NETDB_H 1
 
 #cmakedefine HAVE_IN_PORT_T 1
index 6f87e4380ebed70e982c9f1f46060e08c400062a..e3eac4e2f4724943e7ecaa5c3948967628bc5403 100644 (file)
 
 #pragma once
 
-/* This seems to be required for older compilers @note
- * http://stackoverflow.com/questions/8132399/how-to-printf-uint64-t  */
-#ifndef __STDC_FORMAT_MACROS
-#  define __STDC_FORMAT_MACROS
-#endif
-
-#ifdef __cplusplus
-#  include <cinttypes>
-#  include <cstddef>
-#  include <cstdlib>
-#else
-#  include <inttypes.h>
-#  include <stddef.h>
-#  include <stdlib.h>
-#  include <stdbool.h>
-#endif
-
-#include <sys/types.h>
-
-#ifndef HAVE_PID_T
-typedef int pid_t;
-#endif
-#ifndef HAVE_SSIZE_T
-typedef long int ssize_t;
-#endif
-
-#include "libmemcached-1.0/visibility.h"
 #include "libmemcached-1.0/configure.h"
+#include "libmemcached-1.0/visibility.h"
 #include "libmemcached-1.0/platform.h"
 
 #include "libmemcached-1.0/limits.h"
index a3ccd3d737ded861284109cacba695b969154b49..1ab1bc075180c094f59b5a061ed3a773d7ec6cd3 100644 (file)
 
 #include "libmemcached-1.0/configure.h"
 
-#if defined(_WIN32)
-#  include <winsock2.h>
-#  include <ws2tcpip.h>
+/* This seems to be required for older compilers @note
+ * http://stackoverflow.com/questions/8132399/how-to-printf-uint64-t  */
+#ifndef __STDC_FORMAT_MACROS
+#  define __STDC_FORMAT_MACROS
+#endif
+
+#ifdef __cplusplus
+#  include <cinttypes>
+#  include <cstddef>
+#  include <cstdlib>
+#else
+#  include <inttypes.h>
+#  include <stddef.h>
+#  include <stdlib.h>
+#  include <stdbool.h>
+#endif
+
+#include <sys/types.h>
 
-#  ifndef HAVE_IN_PORT_T
+#if defined HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#if !defined HAVE_IN_PORT_T
 typedef int in_port_t;
-#    define HAVE_IN_PORT_T 1
-#  endif
+#endif
 
-typedef SOCKET memcached_socket_t;
+#if !defined HAVE_PID_T
+typedef int pid_t;
+#endif
 
-#else
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <arpa/inet.h>
-#  include <netdb.h>
-#  include <sys/un.h>
-#  include <netinet/tcp.h>
+#ifndef HAVE_SSIZE_T
+typedef long int ssize_t;
+#endif
 
+#if defined _WIN32
+# include <winsock2.h>
+# include <ws2tcpip.h>
+typedef SOCKET memcached_socket_t;
+#else
 typedef int memcached_socket_t;
-
-#endif /* _WIN32 */
+#endif // _WIN32
index 3eaa021928e04577097e646711e4c474bd73cf29..87176a23c2f3e8d74bb97d74999ebc88a460c91a 100644 (file)
@@ -1,3 +1,4 @@
+add_subdirectory(p9y)
 
 add_subdirectory(bin)
 add_subdirectory(libhashkit)
index 187b9ceffe61d48fb9f20075634d1b0cfe738c44..7b4c34981f7a6f80f8f26473febd35b7ddbfd27d 100644 (file)
@@ -19,6 +19,5 @@ target_sources(memcapable PRIVATE ../libmemcached/byteorder.cc)
 
 # extra libs
 
-target_link_libraries(memcapable PRIVATE Threads::Threads)
 target_link_libraries(memping PRIVATE libmemcachedutil)
 target_link_libraries(memslap PRIVATE Threads::Threads)
index 84443e26ca1317c5e6b7a4ebae652cff26b407e1..0c77c3920f2bf44c3b105971d1474e2c7f94f094 100644 (file)
@@ -1,9 +1,7 @@
 add_library(libclient_common STATIC options.cpp checks.hpp random.hpp time.hpp)
-if(NOT HAVE_GETOPT_H)
-        target_sources(libclient_common PRIVATE ../../win32/getopt.c)
-endif()
 add_library(client_common ALIAS libclient_common)
 set_target_properties(libclient_common PROPERTIES CXX_STANDARD ${CXX_STANDARD})
+target_link_libraries(libclient_common PRIVATE p9y)
 target_link_libraries(libclient_common PUBLIC libmemcached)
 target_include_directories(libclient_common PUBLIC
         .
index 980ca38dc39ab8865a498002e98d6f334d4c2814..65018eff0d077fb3d3f41974120f8f28c0ec19f7 100644 (file)
 #include <vector>
 
 #include "libmemcached/common.h"
-
-#ifdef HAVE_GETOPT_H
-#  include <getopt.h>
-#elif defined _MSC_VER
-#  include "win32/getopt.h"
-#endif
+#include "p9y/getopt.hpp"
 
 class client_options {
 public:
index 1b9af02a5dc4bd596408351b8df6845255e55199..54e9c2242bea3c28061814a83fda375e75dba85f 100644 (file)
 #  include <unistd.h>
 #endif
 
-#ifndef HAVE_GETOPT_H
-#  include "../../win32/getopt.h"
-#endif
+#include "p9y/getopt.hpp"
+#include "p9y/socket.hpp"
+#include "p9y/poll.hpp"
 
 #include "libmemcached-1.0/memcached.h"
-#include "libmemcached/poll.h"
-#include "libmemcached/socket.hpp"
 #include "libmemcachedprotocol-0.0/binary.h"
 #include "libmemcached/byteorder.h"
 
@@ -132,14 +130,14 @@ static memcached_socket_t set_noblock(void) {
   int flags = fcntl(sock, F_GETFL, 0);
   if (flags == -1) {
     perror("Failed to get socket flags");
-    memcached_close_socket(sock);
+    closesocket(sock);
     return INVALID_SOCKET;
   }
 
   if ((flags & O_NONBLOCK) != O_NONBLOCK) {
     if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
       perror("Failed to set socket to nonblocking mode");
-      memcached_close_socket(sock);
+      closesocket(sock);
       return INVALID_SOCKET;
     }
   }
@@ -183,8 +181,8 @@ static ssize_t timeout_io_op(memcached_socket_t fd, short direction, const char
   } else {
     ret = recv(fd, const_cast<char *>(buf), len, 0);
   }
-
-  if (ret == SOCKET_ERROR && get_socket_errno() == EWOULDBLOCK) {
+  int local_errno = get_socket_errno();
+  if (ret == SOCKET_ERROR && local_errno == EWOULDBLOCK || (EAGAIN != EWOULDBLOCK && local_errno == EAGAIN)) {
     struct pollfd fds;
     memset(&fds, 0, sizeof(struct pollfd));
     fds.events = direction;
index 7ad8678717b315a52437dba9e9e7ae91685c0c33..7396057e930f8269a5812db9ce72aec7a4e8f439 100644 (file)
 
 #include "common/options.hpp"
 #include "common/checks.hpp"
+#include "p9y/libgen.hpp"
+#include "p9y/realpath.hpp"
 
 #include <cerrno>
 #include <climits>
 #include <cstdlib>
-#if HAVE_LIBGEN_H
-#  include <libgen.h>
-#endif
 #include <fstream>
 #include <sstream>
 
index 159472153e288d0c3c51140ecc5498ad88d6db61..0287fcc920b1a5443ad891c1fe25ee1b840811b3 100644 (file)
@@ -57,7 +57,6 @@ set(LIBMEMCACHED_SOURCES
         namespace.cc
         options.cc
         parse.cc
-        poll.cc
         purge.cc
         quit.cc
         response.cc
@@ -95,6 +94,7 @@ set_target_properties(libmemcached PROPERTIES
         SOVERSION ${LIBMEMCACHED_SO_VERSION})
 target_compile_definitions(libmemcached PRIVATE -DBUILDING_LIBMEMCACHED)
 target_link_libraries(libmemcached PUBLIC libhashkit Threads::Threads ${CMAKE_DL_LIBS})
+target_link_libraries(libmemcached PRIVATE p9y)
 if(MSVC)
     target_link_libraries(libmemcached PUBLIC wsock32 ws2_32)
 endif()
@@ -138,6 +138,7 @@ add_library(memcachedinternal ALIAS libmemcachedinternal)
 set_target_properties(libmemcachedinternal PROPERTIES CXX_STANDARD ${CXX_STANDARD} LIBRARY_OUTPUT_NAME memcachedinternal)
 target_compile_definitions(libmemcachedinternal PRIVATE -DBUILDING_LIBMEMCACHEDINTERNAL)
 target_link_libraries(libmemcachedinternal PUBLIC libhashkit Threads::Threads ${CMAKE_DL_LIBS})
+target_link_libraries(libmemcachedinternal PRIVATE p9y)
 if(MSVC)
     target_link_libraries(libmemcached PUBLIC wsock32 ws2_32)
 endif()
index 576ec8835ef34ee96a449c3082cef948931df08e..d0d6c6f2a9c0e416f6e732b0e5c405645fae5807 100644 (file)
@@ -16,6 +16,8 @@
 #include "libmemcached/common.h"
 #include "libmemcached/options.hpp"
 #include "libmemcached/virtual_bucket.h"
+#include "p9y/random.hpp"
+#include "p9y/socket.hpp"
 
 #include <ctime>
 #include <sys/types.h>
index eea5319b654c800dcecd20cbe867b67d65ae3db0..defb3b0da19b31ab7b79662e3d6e5c2bc9111dd3 100644 (file)
 #  include <dlfcn.h>
 #endif
 
-#if defined(_WIN32)
-#  include "libmemcached/windows.hpp"
-#endif
-
 #include "libmemcached-1.0/memcached.h"
 #include "libmemcached/watchpoint.h"
 #include "libmemcached/is.h"
 typedef struct memcached_st Memcached;
 
-#include "libmemcached/poll.h"
-
 #ifdef __cplusplus
 memcached_instance_st *memcached_instance_fetch(memcached_st *ptr, uint32_t server_key);
 #endif
@@ -90,7 +84,6 @@ memcached_instance_st *memcached_instance_fetch(memcached_st *ptr, uint32_t serv
 #  include "libmemcached/io.hpp"
 #  include "libmemcached/udp.hpp"
 #  include "libmemcached/do.hpp"
-#  include "libmemcached/socket.hpp"
 #  include "libmemcached/connect.hpp"
 #  include "libmemcached/allocators.hpp"
 #  include "libmemcached/hash.hpp"
@@ -151,6 +144,7 @@ extern "C" {
 memcached_return_t run_distribution(memcached_st *ptr);
 
 #ifdef __cplusplus
+#  include "p9y/poll.hpp"
 static inline void memcached_server_response_increment(memcached_instance_st *instance) {
   instance->events(POLLIN);
   instance->cursor_active_++;
index ff7772ca1c39bb97f14d5b6a396160fa59db1a67..913e48be21dc593c8b3da2aaa48ef3ba891ef611 100644 (file)
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
+#include "p9y/poll.hpp"
 
 #include <cassert>
 
-#ifndef SOCK_CLOEXEC
-#  define SOCK_CLOEXEC 0
-#endif
-
-#ifndef SOCK_NONBLOCK
-#  define SOCK_NONBLOCK 0
-#endif
-
-#ifndef FD_CLOEXEC
-#  define FD_CLOEXEC 0
-#endif
-
-#ifndef SO_NOSIGPIPE
-#  define SO_NOSIGPIPE 0
-#endif
-
-#ifndef TCP_NODELAY
-#  define TCP_NODELAY 0
-#endif
-
-#ifndef TCP_KEEPIDLE
-#  define TCP_KEEPIDLE 0
-#endif
 
 static memcached_return_t connect_poll(memcached_instance_st *server, const int connection_error) {
   struct pollfd fds[1];
index 512fa2b7a429681419a061d330cf938ca248b013..6c58e69cd902c56f2dde262213b19415350db281 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
 
 memcached_return_t memcached_flush_buffers(memcached_st *shell) {
   Memcached *memc = memcached2Memcached(shell);
index 4dd88061fc682a14a5092cc10ad801fb5cc567e9..d625adce3824feb3e733ec2d794faad06b1d3e8e 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/random.hpp"
 
 char *memcached_get(memcached_st *ptr, const char *key, size_t key_length, size_t *value_length,
                     uint32_t *flags, memcached_return_t *error) {
index cb1ca4641e1a85b93cd23ddfe39b31d8ecae8b34..3e147f8797e07106645e95134d0a0d0a302a467c 100644 (file)
 */
 
 #include "libmemcached/common.h"
-
-#if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-#endif
-#include <time.h>
-
 #include "libmemcached/virtual_bucket.h"
+#include "p9y/gettimeofday.hpp"
+#include "p9y/random.hpp"
 
 uint32_t memcached_generate_hash_value(const char *key, size_t key_length,
                                        memcached_hash_t hash_algorithm) {
index 39247287666d55fed37f5b5f72242057fa5f462d..8f1215020214ea9f372952406f19157bce3d2ebf 100644 (file)
 
 #include "libmemcached/common.h"
 #include "libmemcached/assert.hpp"
+#include "p9y/gettimeofday.hpp"
+#include "p9y/random.hpp"
 
 #include <cmath>
-#if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-#endif
-#include <time.h>
 
 /* Protoypes (static) */
 static memcached_return_t update_continuum(Memcached *ptr);
index 266eccc70f8d8b6f53b73b1513ab7879ff5447e6..972f6b6f6ae5e3f6e3cfacd4f2b4aa3f82a023a9 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
 
 static inline void _server_init(memcached_instance_st *self, Memcached *root,
                                 const memcached_string_t &hostname, in_port_t port, uint32_t weight,
index 27b5ecbd0f244064a743150e71bf4b925223cd72..94aca6177acc929f50811fa1276810de621c02fc 100644 (file)
@@ -15,9 +15,8 @@
 
 #include "libmemcached/common.h"
 
-#ifdef HAVE_SYS_SOCKET_H
-#  include <sys/socket.h>
-#endif
+#include "p9y/socket.hpp"
+#include "p9y/poll.hpp"
 
 void initialize_binary_request(memcached_instance_st *server,
                                protocol_binary_request_header &header) {
index 7130cf464ac224798b3ce7b91d087ef637e00343..12431222e3dfea0c72215484d1ebb28af13d7815 100644 (file)
@@ -26,8 +26,8 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) {
 
   end_ptr = server_strings + strlen(server_strings);
 
-  for (begin_ptr = server_strings, string = (char *) index(server_strings, ',');
-       begin_ptr != end_ptr; string = (char *) index(begin_ptr, ','))
+  for (begin_ptr = server_strings, string = (char *) strchr(server_strings, ',');
+       begin_ptr != end_ptr; string = (char *) strchr(begin_ptr, ','))
   {
     char buffer[HUGE_STRING_LEN];
     char *ptr, *ptr2;
@@ -44,7 +44,7 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) {
       begin_ptr = end_ptr;
     }
 
-    ptr = index(buffer, ':');
+    ptr = strchr(buffer, ':');
 
     in_port_t port = 0;
     if (ptr) {
@@ -59,9 +59,9 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) {
         return NULL;
       }
 
-      ptr2 = index(ptr, ' ');
+      ptr2 = strchr(ptr, ' ');
       if (!ptr2)
-        ptr2 = index(ptr, ':');
+        ptr2 = strchr(ptr, ':');
 
       if (ptr2) {
         ptr2++;
diff --git a/src/libmemcached/poll.cc b/src/libmemcached/poll.cc
deleted file mode 100644 (file)
index 5914aa4..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    +--------------------------------------------------------------------+
-    | libmemcached - C/C++ Client Library for memcached                  |
-    +--------------------------------------------------------------------+
-    | Redistribution and use in source and binary forms, with or without |
-    | modification, are permitted under the terms of the BSD license.    |
-    | You should have received a copy of the license in a bundled file   |
-    | named LICENSE; in case you did not receive a copy you can review   |
-    | the terms online at: https://opensource.org/licenses/BSD-3-Clause  |
-    +--------------------------------------------------------------------+
-    | Copyright (c) 2006-2014 Brian Aker   https://datadifferential.com/ |
-    | Copyright (c) 2020 Michael Wallner   <mike@php.net>                |
-    +--------------------------------------------------------------------+
-*/
-
-#include "libmemcached/common.h"
-
-#if defined(_WIN32)
-#  include "libmemcached/poll.h"
-#  if HAVE_SYS_TIME_H
-#    include <sys/time.h>
-#  endif
-#  include <time.h>
-#  if HAVE_STRINGS_H
-#    include <cstrings>
-#  endif
-
-int poll(struct pollfd fds[], nfds_t nfds, int tmo) {
-  fd_set readfds, writefds, errorfds;
-  FD_ZERO(&readfds);
-  FD_ZERO(&writefds);
-  FD_ZERO(&errorfds);
-
-  int maxfd = 0;
-
-  for (nfds_t x = 0; x < nfds; ++x) {
-    if (fds[x].events & (POLLIN | POLLOUT)) {
-#  ifndef _WIN32
-      if (fds[x].fd > maxfd) {
-        maxfd = fds[x].fd;
-      }
-#  endif
-      if (fds[x].events & POLLIN) {
-        FD_SET(fds[x].fd, &readfds);
-      }
-      if (fds[x].events & POLLOUT) {
-        FD_SET(fds[x].fd, &writefds);
-      }
-    }
-  }
-
-  struct timeval timeout = {tmo / 1000, (tmo % 1000) * 1000};
-  struct timeval *tp = &timeout;
-  if (tmo == -1) {
-    tp = NULL;
-  }
-  int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, tp);
-  if (ret <= 0) {
-    return ret;
-  }
-
-  /* Iterate through all of them because I need to clear the revent map */
-  for (nfds_t x = 0; x < nfds; ++x) {
-    fds[x].revents = 0;
-    if (FD_ISSET(fds[x].fd, &readfds)) {
-      fds[x].revents |= POLLIN;
-    }
-    if (FD_ISSET(fds[x].fd, &writefds)) {
-      fds[x].revents |= POLLOUT;
-    }
-    if (FD_ISSET(fds[x].fd, &errorfds)) {
-      fds[x].revents |= POLLERR;
-    }
-  }
-
-  return ret;
-}
-
-#endif // defined(_WIN32)
diff --git a/src/libmemcached/poll.h b/src/libmemcached/poll.h
deleted file mode 100644 (file)
index 8c0ad1f..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-    +--------------------------------------------------------------------+
-    | libmemcached - C/C++ Client Library for memcached                  |
-    +--------------------------------------------------------------------+
-    | Redistribution and use in source and binary forms, with or without |
-    | modification, are permitted under the terms of the BSD license.    |
-    | You should have received a copy of the license in a bundled file   |
-    | named LICENSE; in case you did not receive a copy you can review   |
-    | the terms online at: https://opensource.org/licenses/BSD-3-Clause  |
-    +--------------------------------------------------------------------+
-    | Copyright (c) 2006-2014 Brian Aker   https://datadifferential.com/ |
-    | Copyright (c) 2020 Michael Wallner   <mike@php.net>                |
-    +--------------------------------------------------------------------+
-*/
-
-#pragma once
-
-#if defined HAVE_SYS_POLL_H
-#  include <sys/poll.h>
-#elif defined HAVE_POLL_H
-#  include <poll.h>
-#elif defined _WIN32
-#  include "windows.hpp"
-#  define poll WSAPoll
-typedef int nfds_t;
-#elif !defined _MSC_VER
-
-#  ifdef __cplusplus
-extern "C" {
-#  endif
-
-typedef struct pollfd {
-#  if defined(_WIN32)
-  SOCKET fd;
-#  else
-  int fd;
-#  endif
-  short events;
-  short revents;
-} pollfd_t;
-
-typedef int nfds_t;
-
-#  define POLLIN   0x0001
-#  define POLLOUT  0x0004
-#  define POLLERR  0x0008
-#  define POLLHUP  0x010 /* Hung up.  */
-#  define POLLNVAL 0x020 /* Invalid polling request.  */
-
-int poll(struct pollfd fds[], nfds_t nfds, int tmo);
-
-#  ifdef __cplusplus
-}
-#  endif
-
-#endif // defined(_WIN32)
index 4437d76100b53354b9c660107c5014d2975eae9d..d4b3146da983790322440437337da27901b3f233 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
 
 #define memcached_set_purging(__object, __value) ((__object)->state.is_purging = (__value))
 
index 5f0f020442a295e8305976e7788093b057728548..13ffefeb04cd7b0ad765e30deb6195f675a1635b 100644 (file)
@@ -197,7 +197,7 @@ static memcached_return_t textual_read_one_response(memcached_instance_st *insta
              and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */
     {
       /* Find the space, and then move one past it to copy version */
-      char *response_ptr = index(buffer, ' ');
+      char *response_ptr = strchr(buffer, ' ');
 
       char *endptr;
       errno = 0;
index 9c8ad52f7211ebad0387c2ca86c3e8412460accf..4fa981d285cf6a03c047d1acd1ebbaa391e49932 100644 (file)
@@ -14,6 +14,8 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
+
 #include <cassert>
 #include <atomic>
 
index e038196abffd52fe8d3052e7365ec10c2d0c9f79..28d063ec05d494fd648419eda53c48e710dcd587 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcached/common.h"
+#include "p9y/socket.hpp"
 
 static inline void _server_init(memcached_server_st *self, Memcached *root,
                                 const memcached_string_t &hostname, in_port_t port, uint32_t weight,
index 017242bd9d8810d869866e88cfa484a08d347d50..86f6ffb9000950a3ad6d37941d2e26670851285b 100644 (file)
@@ -15,9 +15,7 @@
 
 #pragma once
 
-#ifdef HAVE_SYS_TIME_H
-#  include <sys/time.h>
-#endif
+#include "p9y/gettimeofday.hpp"
 
 #include <cassert>
 
diff --git a/src/libmemcached/socket.hpp b/src/libmemcached/socket.hpp
deleted file mode 100644 (file)
index ed7810f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-    +--------------------------------------------------------------------+
-    | libmemcached - C/C++ Client Library for memcached                  |
-    +--------------------------------------------------------------------+
-    | Redistribution and use in source and binary forms, with or without |
-    | modification, are permitted under the terms of the BSD license.    |
-    | You should have received a copy of the license in a bundled file   |
-    | named LICENSE; in case you did not receive a copy you can review   |
-    | the terms online at: https://opensource.org/licenses/BSD-3-Clause  |
-    +--------------------------------------------------------------------+
-    | Copyright (c) 2006-2014 Brian Aker   https://datadifferential.com/ |
-    | Copyright (c) 2020 Michael Wallner   <mike@php.net>                |
-    +--------------------------------------------------------------------+
-*/
-
-#pragma once
-
-/* To hide the platform differences between MS Windows and Unix, I am
- * going to use the Microsoft way and #define the Microsoft-specific
- * functions to the unix way. Microsoft use a separate subsystem for sockets,
- * but Unix normally just use a filedescriptor on the same functions. It is
- * a lot easier to map back to the unix way with macros than going the other
- * way without side effect ;-)
- */
-#if defined(WIN32) || defined(__MINGW32__)
-#  include "win32/wrappers.h"
-#  include "windows.hpp"
-#  define get_socket_errno() translate_windows_error()
-#else
-#  include <unistd.h>
-#  define INVALID_SOCKET     -1
-#  define SOCKET_ERROR       -1
-#  define closesocket(a)     close(a)
-#  define get_socket_errno() errno
-#endif
-
-#ifdef __cplusplus
-static inline void memcached_close_socket(memcached_socket_t &socket_fd) {
-  closesocket(socket_fd);
-  socket_fd = INVALID_SOCKET;
-}
-#endif
-
-#ifndef HAVE_MSG_NOSIGNAL
-#  define MSG_NOSIGNAL 0
-#endif
-
-#ifndef HAVE_MSG_DONTWAIT
-#  define MSG_DONTWAIT 0
-#endif
-
-#ifndef HAVE_MSG_MORE
-#  define MSG_MORE 0
-#endif
diff --git a/src/libmemcached/windows.hpp b/src/libmemcached/windows.hpp
deleted file mode 100644 (file)
index b867a6d..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-    +--------------------------------------------------------------------+
-    | libmemcached - C/C++ Client Library for memcached                  |
-    +--------------------------------------------------------------------+
-    | Redistribution and use in source and binary forms, with or without |
-    | modification, are permitted under the terms of the BSD license.    |
-    | You should have received a copy of the license in a bundled file   |
-    | named LICENSE; in case you did not receive a copy you can review   |
-    | the terms online at: https://opensource.org/licenses/BSD-3-Clause  |
-    +--------------------------------------------------------------------+
-    | Copyright (c) 2006-2014 Brian Aker   https://datadifferential.com/ |
-    | Copyright (c) 2020 Michael Wallner   <mike@php.net>                |
-    +--------------------------------------------------------------------+
-*/
-
-#pragma once
-
-#ifdef __cplusplus
-#  include <cerrno>
-#else
-#  include <errno.h>
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#  define WIN32_LEAN_AND_MEAN
-#endif
-
-#if defined(HAVE_WINSOCK2_H) && HAVE_WINSOCK2_H
-#  include <winsock2.h>
-#endif
-
-#if defined(HAVE_WS2TCPIP_H) && HAVE_WS2TCPIP_H
-#  include <ws2tcpip.h>
-#endif
-
-#if defined(HAVE_IO_H) && HAVE_IO_H
-#  include <io.h>
-#endif
-
-struct sockaddr_un {
-  short int sun_family;
-  char sun_path[108];
-};
-
-static inline int translate_windows_error() {
-  int local_errno = WSAGetLastError();
-
-  switch (local_errno) {
-  case WSAEINVAL:
-    local_errno = EINPROGRESS;
-    break;
-  case WSAEALREADY:
-  case WSAEWOULDBLOCK:
-    local_errno = EAGAIN;
-    break;
-
-  case WSAECONNREFUSED:
-    local_errno = ECONNREFUSED;
-    break;
-
-  case WSAENETUNREACH:
-    local_errno = ENETUNREACH;
-    break;
-
-  case WSAETIMEDOUT:
-    local_errno = ETIMEDOUT;
-    break;
-
-  case WSAECONNRESET:
-    local_errno = ECONNRESET;
-    break;
-
-  case WSAEADDRINUSE:
-    local_errno = EADDRINUSE;
-    break;
-
-  case WSAEOPNOTSUPP:
-    local_errno = EOPNOTSUPP;
-    break;
-
-  case WSAENOPROTOOPT:
-    local_errno = ENOPROTOOPT;
-    break;
-
-  default:
-    break;
-  }
-
-  return local_errno;
-}
-
-static inline char *basename(const char *filename) {
-  static char base[MAX_PATH * 2], ext[MAX_PATH], *ptr;
-  (void) _splitpath_s(filename, NULL, 0, NULL, 0, base, MAX_PATH, ext, MAX_PATH);
-  strcat_s(base, MAX_PATH * 2 - 1, ext);
-  return base;
-}
-
-static inline char *realpath(const char *path, char real[MAX_PATH]) {
-  return _fullpath(real, path, MAX_PATH);
-}
\ No newline at end of file
index 61fbed1560b0e6de26aba1ad222962c629e99ff4..43d59de1310ca064b509a03c0b4b0dfa318ab020 100644 (file)
@@ -21,6 +21,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL AppleClang)
                LINK_FLAGS "-Wl,-undefined,dynamic_lookup"
                )
 endif()
+target_link_libraries(libmemcachedprotocol PRIVATE p9y)
 target_link_libraries(libmemcachedprotocol PUBLIC Threads::Threads)
 if(MSVC)
     target_link_libraries(libmemcachedprotocol PUBLIC wsock32 ws2_32)
index ada4c42599cc999fe62c50d796fbe175b2cebdae..a1b072d04e14cef2aa497e5383b379bbd374d2d4 100644 (file)
@@ -14,6 +14,7 @@
 */
 
 #include "libmemcachedprotocol/common.h"
+#include "p9y/socket.hpp"
 
 #include <stdlib.h>
 #include <sys/types.h>
index ee27ab4a721074064bc1df8b0a32bfbb645b78e6..39f0464ef277600203bee43ff1804a9dd514ebb5 100644 (file)
@@ -21,7 +21,6 @@
 #include "libmemcachedprotocol-0.0/handler.h"
 #include "libmemcachedprotocol/cache.h"
 #include "libmemcached/byteorder.h"
-#include "libmemcached/socket.hpp"
 
 /*
  * I don't really need the following two functions as function pointers
index b848407245ba07a22a475548cbe962a54a620bf0..535795cab49bb40bb16b20ec16211c7edad934aa 100644 (file)
 #include <ctype.h>
 #include <stdio.h>
 
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-#  include <sys/socket.h>
-#endif
+#include "p9y/socket.hpp"
 
 /*
 ** **********************************************************************
diff --git a/src/p9y/CMakeLists.txt b/src/p9y/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1734f0b
--- /dev/null
@@ -0,0 +1,36 @@
+add_library(p9y STATIC
+    getopt.hpp
+    libgen.hpp
+    realpath.hpp
+    socket.hpp
+    poll.hpp
+    random.hpp
+    index.hpp
+    p9y.cpp
+    )
+
+target_include_directories(p9y PRIVATE
+    .
+    ${CMAKE_SOURCE_DIR}/include
+    ${CMAKE_BINARY_DIR}
+    ${CMAKE_BINARY_DIR}/include
+    )
+
+if(NOT HAVE_GETOPT_H)
+    target_sources(p9y PRIVATE getopt.c)
+endif()
+if(NOT HAVE_LIBGEN_H)
+    target_sources(p9y PRIVATE libgen.c)
+endif()
+if(NOT HAVE_REALPATH)
+    target_sources(p9y PRIVATE realpath.c)
+endif()
+if(WIN32)
+    target_sources(p9y PRIVATE socket.c)
+endif()
+if(NOT HAVE_POLL_H AND NOT HAVE_SYS_POLL_H AND NOT WIN32)
+    target_sources(p9y PRIVATE poll.c)
+endif()
+if(NOT HAVE_GETTIMEOFDAY)
+    target_sources(p9y PRIVATE gettimeofday.cpp)
+endif()
diff --git a/src/p9y/getopt.c b/src/p9y/getopt.c
new file mode 100644 (file)
index 0000000..4043494
--- /dev/null
@@ -0,0 +1,659 @@
+#ifndef __GETOPT_H__
+/**
+ * DISCLAIMER
+ * This file is part of the mingw-w64 runtime package.
+ *
+ * The mingw-w64 runtime package and its code is distributed in the hope that it
+ * will be useful but WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESSED OR
+ * IMPLIED ARE HEREBY DISCLAIMED.  This includes but is not limited to
+ * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+ /*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define __GETOPT_H__
+
+#ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef _WIN32
+#  include <crtdefs.h>
+#  include <windows.h>
+#endif
+
+#include <stddef.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        REPLACE_GETOPT          /* use this getopt as the system getopt(3) */
+
+#ifdef REPLACE_GETOPT
+int    opterr = 1;             /* if error message should be printed */
+int    optind = 1;             /* index into parent argv vector */
+int    optopt = '?';           /* character checked for validity */
+#undef optreset                /* see getopt.h */
+#define        optreset                __mingw_optreset
+int    optreset;               /* reset getopt */
+char    *optarg;               /* argument associated with option */
+#endif
+
+//extern int optind;           /* index of first non-option in argv      */
+//extern int optopt;           /* single option character, as parsed     */
+//extern int opterr;           /* flag to enable built-in diagnostics... */
+//                             /* (user may set to zero, to suppress)    */
+//
+//extern char *optarg;         /* pointer to argument of current option  */
+
+#define PRINT_ERROR    ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE   0x01    /* permute non-options to the end of argv */
+#define FLAG_ALLARGS   0x02    /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY  0x04    /* operate as getopt_long_only */
+
+/* return values */
+#define        BADCH           (int)'?'
+#define        BADARG          ((*options == ':') ? (int)':' : (int)'?')
+#define        INORDER         (int)1
+
+#ifndef __CYGWIN__
+#define __progname __argv[0]
+#else
+extern char __declspec(dllimport) *__progname;
+#endif
+
+#ifdef __CYGWIN__
+static char EMSG[] = "";
+#else
+#define        EMSG            ""
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+                          const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+                             const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+static void
+_vwarnx(const char *fmt,va_list ap)
+{
+  (void)fprintf(stderr,"%s: ",__progname);
+  if (fmt != NULL)
+    (void)vfprintf(stderr,fmt,ap);
+  (void)fprintf(stderr,"\n");
+}
+
+static void
+warnx(const char *fmt,...)
+{
+  va_list ap;
+  va_start(ap,fmt);
+  _vwarnx(fmt,ap);
+  va_end(ap);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+       int c;
+
+       c = a % b;
+       while (c != 0) {
+               a = b;
+               b = c;
+               c = a % b;
+       }
+
+       return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+       char * const *nargv)
+{
+       int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+       char *swap;
+
+       /*
+        * compute lengths of blocks and number and size of cycles
+        */
+       nnonopts = panonopt_end - panonopt_start;
+       nopts = opt_end - panonopt_end;
+       ncycle = gcd(nnonopts, nopts);
+       cyclelen = (opt_end - panonopt_start) / ncycle;
+
+       for (i = 0; i < ncycle; i++) {
+               cstart = panonopt_end+i;
+               pos = cstart;
+               for (j = 0; j < cyclelen; j++) {
+                       if (pos >= panonopt_end)
+                               pos -= nnonopts;
+                       else
+                               pos += nopts;
+                       swap = nargv[pos];
+                       /* LINTED const cast */
+                       ((char **) nargv)[pos] = nargv[cstart];
+                       /* LINTED const cast */
+                       ((char **)nargv)[cstart] = swap;
+               }
+       }
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ *     Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+       /*
+        * We don't pass FLAG_PERMUTE to getopt_internal() since
+        * the BSD getopt(3) (unlike GNU) has never done this.
+        *
+        * Furthermore, since many privileged programs call getopt()
+        * before dropping privileges it makes sense to keep things
+        * as simple (and bug-free) as possible.
+        */
+       return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+//extern int getopt(int nargc, char * const *nargv, const char *options);
+
+#ifdef _BSD_SOURCE
+/*
+ * BSD adds the non-standard `optreset' feature, for reinitialisation
+ * of `getopt' parsing.  We support this feature, for applications which
+ * proclaim their BSD heritage, before including this header; however,
+ * to maintain portability, developers are advised to avoid it.
+ */
+# define optreset  __mingw_optreset
+extern int optreset;
+#endif
+#ifdef __cplusplus
+}
+#endif
+/*
+ * POSIX requires the `getopt' API to be specified in `unistd.h';
+ * thus, `unistd.h' includes this header.  However, we do not want
+ * to expose the `getopt_long' or `getopt_long_only' APIs, when
+ * included in this manner.  Thus, close the standard __GETOPT_H__
+ * declarations block, and open an additional __GETOPT_LONG_H__
+ * specific block, only when *not* __UNISTD_H_SOURCED__, in which
+ * to declare the extended API.
+ */
+#endif /* !defined(__GETOPT_H__) */
+
+#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
+#define __GETOPT_LONG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct option          /* specification for a long form option...      */
+{
+  const char *name;            /* option name, without leading hyphens */
+  int         has_arg;         /* does it take an argument?            */
+  int        *flag;            /* where to save its status, or NULL    */
+  int         val;             /* its associated status value          */
+};
+
+enum                   /* permitted values for its `has_arg' field...  */
+{
+  no_argument = 0,             /* option never takes an argument       */
+  required_argument,           /* option always requires an argument   */
+  optional_argument            /* option may take an argument          */
+};
+
+/*
+ * parse_long_options --
+ *     Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+       const struct option *long_options, int *idx, int short_too)
+{
+       char *current_argv, *has_equal;
+       size_t current_argv_len;
+       int i, ambiguous, match;
+
+#define IDENTICAL_INTERPRETATION(_x, _y)                                \
+       (long_options[(_x)].has_arg == long_options[(_y)].has_arg &&    \
+        long_options[(_x)].flag == long_options[(_y)].flag &&          \
+        long_options[(_x)].val == long_options[(_y)].val)
+
+       current_argv = place;
+       match = -1;
+       ambiguous = 0;
+
+       optind++;
+
+       if ((has_equal = strchr(current_argv, '=')) != NULL) {
+               /* argument found (--option=arg) */
+               current_argv_len = has_equal - current_argv;
+               has_equal++;
+       } else
+               current_argv_len = strlen(current_argv);
+
+       for (i = 0; long_options[i].name; i++) {
+               /* find matching long option */
+               if (strncmp(current_argv, long_options[i].name,
+                   current_argv_len))
+                       continue;
+
+               if (strlen(long_options[i].name) == current_argv_len) {
+                       /* exact match */
+                       match = i;
+                       ambiguous = 0;
+                       break;
+               }
+               /*
+                * If this is a known short option, don't allow
+                * a partial match of a single character.
+                */
+               if (short_too && current_argv_len == 1)
+                       continue;
+
+               if (match == -1)        /* partial match */
+                       match = i;
+               else if (!IDENTICAL_INTERPRETATION(i, match))
+                       ambiguous = 1;
+       }
+       if (ambiguous) {
+               /* ambiguous abbreviation */
+               if (PRINT_ERROR)
+                       warnx(ambig, (int)current_argv_len,
+                            current_argv);
+               optopt = 0;
+               return (BADCH);
+       }
+       if (match != -1) {              /* option found */
+               if (long_options[match].has_arg == no_argument
+                   && has_equal) {
+                       if (PRINT_ERROR)
+                               warnx(noarg, (int)current_argv_len,
+                                    current_argv);
+                       /*
+                        * XXX: GNU sets optopt to val regardless of flag
+                        */
+                       if (long_options[match].flag == NULL)
+                               optopt = long_options[match].val;
+                       else
+                               optopt = 0;
+                       return (BADARG);
+               }
+               if (long_options[match].has_arg == required_argument ||
+                   long_options[match].has_arg == optional_argument) {
+                       if (has_equal)
+                               optarg = has_equal;
+                       else if (long_options[match].has_arg ==
+                           required_argument) {
+                               /*
+                                * optional argument doesn't use next nargv
+                                */
+                               optarg = nargv[optind++];
+                       }
+               }
+               if ((long_options[match].has_arg == required_argument)
+                   && (optarg == NULL)) {
+                       /*
+                        * Missing argument; leading ':' indicates no error
+                        * should be generated.
+                        */
+                       if (PRINT_ERROR)
+                               warnx(recargstring,
+                                   current_argv);
+                       /*
+                        * XXX: GNU sets optopt to val regardless of flag
+                        */
+                       if (long_options[match].flag == NULL)
+                               optopt = long_options[match].val;
+                       else
+                               optopt = 0;
+                       --optind;
+                       return (BADARG);
+               }
+       } else {                        /* unknown option */
+               if (short_too) {
+                       --optind;
+                       return (-1);
+               }
+               if (PRINT_ERROR)
+                       warnx(illoptstring, current_argv);
+               optopt = 0;
+               return (BADCH);
+       }
+       if (idx)
+               *idx = match;
+       if (long_options[match].flag) {
+               *long_options[match].flag = long_options[match].val;
+               return (0);
+       } else
+               return (long_options[match].val);
+#undef IDENTICAL_INTERPRETATION
+}
+
+/*
+ * getopt_internal --
+ *     Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+       const struct option *long_options, int *idx, int flags)
+{
+       char *oli;                              /* option letter list index */
+       int optchar, short_too;
+       static int posixly_correct = -1;
+
+       if (options == NULL)
+               return (-1);
+
+       /*
+        * XXX Some GNU programs (like cvs) set optind to 0 instead of
+        * XXX using optreset.  Work around this braindamage.
+        */
+       if (optind == 0)
+               optind = optreset = 1;
+
+       /*
+        * Disable GNU extensions if POSIXLY_CORRECT is set or options
+        * string begins with a '+'.
+        *
+        * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
+        *                 optreset != 0 for GNU compatibility.
+        */
+       if (posixly_correct == -1 || optreset != 0)
+               posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+       if (*options == '-')
+               flags |= FLAG_ALLARGS;
+       else if (posixly_correct || *options == '+')
+               flags &= ~FLAG_PERMUTE;
+       if (*options == '+' || *options == '-')
+               options++;
+
+       optarg = NULL;
+       if (optreset)
+               nonopt_start = nonopt_end = -1;
+start:
+       if (optreset || !*place) {              /* update scanning pointer */
+               optreset = 0;
+               if (optind >= nargc) {          /* end of argument vector */
+                       place = EMSG;
+                       if (nonopt_end != -1) {
+                               /* do permutation, if we have to */
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               optind -= nonopt_end - nonopt_start;
+                       }
+                       else if (nonopt_start != -1) {
+                               /*
+                                * If we skipped non-options, set optind
+                                * to the first of them.
+                                */
+                               optind = nonopt_start;
+                       }
+                       nonopt_start = nonopt_end = -1;
+                       return (-1);
+               }
+               if (*(place = nargv[optind]) != '-' ||
+                   (place[1] == '\0' && strchr(options, '-') == NULL)) {
+                       place = EMSG;           /* found non-option */
+                       if (flags & FLAG_ALLARGS) {
+                               /*
+                                * GNU extension:
+                                * return non-option as argument to option 1
+                                */
+                               optarg = nargv[optind++];
+                               return (INORDER);
+                       }
+                       if (!(flags & FLAG_PERMUTE)) {
+                               /*
+                                * If no permutation wanted, stop parsing
+                                * at first non-option.
+                                */
+                               return (-1);
+                       }
+                       /* do permutation */
+                       if (nonopt_start == -1)
+                               nonopt_start = optind;
+                       else if (nonopt_end != -1) {
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               nonopt_start = optind -
+                                   (nonopt_end - nonopt_start);
+                               nonopt_end = -1;
+                       }
+                       optind++;
+                       /* process next argument */
+                       goto start;
+               }
+               if (nonopt_start != -1 && nonopt_end == -1)
+                       nonopt_end = optind;
+
+               /*
+                * If we have "-" do nothing, if "--" we are done.
+                */
+               if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+                       optind++;
+                       place = EMSG;
+                       /*
+                        * We found an option (--), so if we skipped
+                        * non-options, we have to permute.
+                        */
+                       if (nonopt_end != -1) {
+                               permute_args(nonopt_start, nonopt_end,
+                                   optind, nargv);
+                               optind -= nonopt_end - nonopt_start;
+                       }
+                       nonopt_start = nonopt_end = -1;
+                       return (-1);
+               }
+       }
+
+       /*
+        * Check long options if:
+        *  1) we were passed some
+        *  2) the arg is not just "-"
+        *  3) either the arg starts with -- we are getopt_long_only()
+        */
+       if (long_options != NULL && place != nargv[optind] &&
+           (*place == '-' || (flags & FLAG_LONGONLY))) {
+               short_too = 0;
+               if (*place == '-')
+                       place++;                /* --foo long option */
+               else if (*place != ':' && strchr(options, *place) != NULL)
+                       short_too = 1;          /* could be short option too */
+
+               optchar = parse_long_options(nargv, options, long_options,
+                   idx, short_too);
+               if (optchar != -1) {
+                       place = EMSG;
+                       return (optchar);
+               }
+       }
+
+       if ((optchar = (int)*place++) == (int)':' ||
+           (optchar == (int)'-' && *place != '\0') ||
+           (oli = (char*)strchr(options, optchar)) == NULL) {
+               /*
+                * If the user specified "-" and  '-' isn't listed in
+                * options, return -1 (non-option) as per POSIX.
+                * Otherwise, it is an unknown option character (or ':').
+                */
+               if (optchar == (int)'-' && *place == '\0')
+                       return (-1);
+               if (!*place)
+                       ++optind;
+               if (PRINT_ERROR)
+                       warnx(illoptchar, optchar);
+               optopt = optchar;
+               return (BADCH);
+       }
+       if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+               /* -W long-option */
+               if (*place)                     /* no space */
+                       /* NOTHING */;
+               else if (++optind >= nargc) {   /* no arg */
+                       place = EMSG;
+                       if (PRINT_ERROR)
+                               warnx(recargchar, optchar);
+                       optopt = optchar;
+                       return (BADARG);
+               } else                          /* white space */
+                       place = nargv[optind];
+               optchar = parse_long_options(nargv, options, long_options,
+                   idx, 0);
+               place = EMSG;
+               return (optchar);
+       }
+       if (*++oli != ':') {                    /* doesn't take argument */
+               if (!*place)
+                       ++optind;
+       } else {                                /* takes (optional) argument */
+               optarg = NULL;
+               if (*place)                     /* no white space */
+                       optarg = place;
+               else if (oli[1] != ':') {       /* arg not optional */
+                       if (++optind >= nargc) {        /* no arg */
+                               place = EMSG;
+                               if (PRINT_ERROR)
+                                       warnx(recargchar, optchar);
+                               optopt = optchar;
+                               return (BADARG);
+                       } else
+                               optarg = nargv[optind];
+               }
+               place = EMSG;
+               ++optind;
+       }
+       /* dump back option letter */
+       return (optchar);
+}
+
+/*
+ * getopt_long --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+       return (getopt_internal(nargc, nargv, options, long_options, idx,
+           FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *     Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+       return (getopt_internal(nargc, nargv, options, long_options, idx,
+           FLAG_PERMUTE|FLAG_LONGONLY));
+}
+
+//extern int getopt_long(int nargc, char * const *nargv, const char *options,
+//    const struct option *long_options, int *idx);
+//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
+//    const struct option *long_options, int *idx);
+/*
+ * Previous MinGW implementation had...
+ */
+#ifndef HAVE_DECL_GETOPT
+/*
+ * ...for the long form API only; keep this for compatibility.
+ */
+# define HAVE_DECL_GETOPT      1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
diff --git a/src/p9y/getopt.hpp b/src/p9y/getopt.hpp
new file mode 100644 (file)
index 0000000..f449d60
--- /dev/null
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "mem_config.h"
+
+#ifdef HAVE_GETOPT_H
+#  include <getopt.h>
+#else
+
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+
+extern int opterr;    /* if error message should be printed */
+extern int optind;    /* index into parent argv vector */
+extern char *optarg;  /* argument associated with option */
+
+struct option    /* specification for a long form option...  */
+{
+  const char *name;       /* option name, without leading hyphens */
+  int         has_arg;    /* does it take an argument?    */
+  int        *flag;       /* where to save its status, or NULL  */
+  int         val;        /* its associated status value    */
+};
+
+enum            /* permitted values for its `has_arg' field...  */
+{
+  no_argument = 0,        /* option never takes an argument  */
+  required_argument,      /* option always requires an argument  */
+  optional_argument       /* option may take an argument    */
+};
+
+int getopt(int nargc, char * const *nargv, const char *options);
+int getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx);
+int getopt_long_only(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx);
+
+#  ifdef __cplusplus
+}
+#  endif
+
+#endif // HAVE_GETOPT_H
diff --git a/src/p9y/gettimeofday.cpp b/src/p9y/gettimeofday.cpp
new file mode 100644 (file)
index 0000000..7d002ca
--- /dev/null
@@ -0,0 +1,23 @@
+#include "gettimeofday.hpp"
+
+#include <chrono>
+
+#if !defined HAVE_GETTIMEOFDAY
+int gettimeofday(struct timeval* tp, struct timezone*) {
+  using clock = std::chrono::system_clock;
+  auto as_sec = [] (auto d) {
+      return std::chrono::duration_cast<std::chrono::seconds>(d);
+  };
+  auto as_usec = [] (auto d) {
+      return std::chrono::duration_cast<std::chrono::microseconds>(d);
+  };
+
+  auto now = clock::now().time_since_epoch();
+  auto sec = as_sec(now);
+  auto usec = as_usec(now - sec);
+
+  tp->tv_sec = sec.count();
+  tp->tv_usec = usec.count();
+  return 0;
+}
+#endif
diff --git a/src/p9y/gettimeofday.hpp b/src/p9y/gettimeofday.hpp
new file mode 100644 (file)
index 0000000..02b8d6d
--- /dev/null
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "libmemcached-1.0/platform.h"
+
+#include <time.h>
+#if defined HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#if !defined HAVE_GETTIMEOFDAY
+int gettimeofday(struct timeval* tp, struct timezone* tzp);
+#endif
diff --git a/src/p9y/index.hpp b/src/p9y/index.hpp
new file mode 100644 (file)
index 0000000..d193bf6
--- /dev/null
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "mem_config.h"
+
+#if defined HAVE_STRINGS_H
+# include <strings.h>
+#elif defined __cplusplus
+# include <cstring>
+#else
+# include <string.h>
+#endif
+
+#if !defined HAVE_INDEX
+# define index strchr
+#endif
diff --git a/src/p9y/libgen.c b/src/p9y/libgen.c
new file mode 100644 (file)
index 0000000..70696eb
--- /dev/null
@@ -0,0 +1,10 @@
+#include "libgen.hpp"
+
+#if defined _WIN32
+char *basename(const char *filename) {
+  static char base[_MAX_PATH * 2], ext[_MAX_PATH], *ptr;
+  (void) _splitpath_s(filename, NULL, 0, NULL, 0, base, _MAX_PATH, ext, _MAX_PATH);
+  strcat_s(base, _MAX_PATH * 2 - 1, ext);
+  return base;
+}
+#endif
diff --git a/src/p9y/libgen.hpp b/src/p9y/libgen.hpp
new file mode 100644 (file)
index 0000000..82976d7
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "mem_config.h"
+
+#if defined __cplusplus
+#   include <cstdlib>
+#else
+#   include <stdlib.h>
+#endif
+
+#if defined HAVE_LIBGEN_H
+# include <libgen.h>
+#elif defined _WIN32
+#  if defined __cplusplus
+extern "C" {
+#  endif
+char *basename(const char *filename);
+#  if  defined __cplusplus
+}
+#  endif
+#endif // HAVE_LIBGEN_H
diff --git a/src/p9y/p9y.cpp b/src/p9y/p9y.cpp
new file mode 100644 (file)
index 0000000..35ee8f0
--- /dev/null
@@ -0,0 +1 @@
+// empty stub
diff --git a/src/p9y/poll.c b/src/p9y/poll.c
new file mode 100644 (file)
index 0000000..b745c8b
--- /dev/null
@@ -0,0 +1,56 @@
+#include "poll.hpp"
+
+#if defined P9Y_NEED_POLL
+
+int poll(struct pollfd fds[], nfds_t nfds, int tmo) {
+  fd_set readfds, writefds, errorfds;
+  FD_ZERO(&readfds);
+  FD_ZERO(&writefds);
+  FD_ZERO(&errorfds);
+
+  int maxfd = 0;
+
+  for (nfds_t x = 0; x < nfds; ++x) {
+    if (fds[x].events & (POLLIN | POLLOUT)) {
+#  ifndef _WIN32
+      if (fds[x].fd > maxfd) {
+        maxfd = fds[x].fd;
+      }
+#  endif
+      if (fds[x].events & POLLIN) {
+        FD_SET(fds[x].fd, &readfds);
+      }
+      if (fds[x].events & POLLOUT) {
+        FD_SET(fds[x].fd, &writefds);
+      }
+    }
+  }
+
+  struct timeval timeout = {tmo / 1000, (tmo % 1000) * 1000};
+  struct timeval *tp = &timeout;
+  if (tmo == -1) {
+    tp = NULL;
+  }
+  int ret = select(maxfd + 1, &readfds, &writefds, &errorfds, tp);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  /* Iterate through all of them because I need to clear the revent map */
+  for (nfds_t x = 0; x < nfds; ++x) {
+    fds[x].revents = 0;
+    if (FD_ISSET(fds[x].fd, &readfds)) {
+      fds[x].revents |= POLLIN;
+    }
+    if (FD_ISSET(fds[x].fd, &writefds)) {
+      fds[x].revents |= POLLOUT;
+    }
+    if (FD_ISSET(fds[x].fd, &errorfds)) {
+      fds[x].revents |= POLLERR;
+    }
+  }
+
+  return ret;
+}
+
+#endif // P9Y_NEED_POLL
diff --git a/src/p9y/poll.hpp b/src/p9y/poll.hpp
new file mode 100644 (file)
index 0000000..6a24261
--- /dev/null
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "libmemcached-1.0/platform.h"
+
+#if defined HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+#elif defined HAVE_POLL_H
+#  include <poll.h>
+#elif defined _WIN32
+#  define poll WSAPoll
+typedef int nfds_t;
+#else
+
+#  define P9Y_NEED_POLL
+
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+
+typedef struct pollfd {
+#  if defined(_WIN32)
+  SOCKET fd;
+#  else
+  int fd;
+#  endif
+  short events;
+  short revents;
+} pollfd_t;
+
+typedef int nfds_t;
+
+#  define POLLIN   0x0001
+#  define POLLOUT  0x0004
+#  define POLLERR  0x0008
+#  define POLLHUP  0x010 /* Hung up.  */
+#  define POLLNVAL 0x020 /* Invalid polling request.  */
+
+int poll(struct pollfd fds[], nfds_t nfds, int tmo);
+
+#  ifdef __cplusplus
+}
+#  endif
+
+#endif
diff --git a/src/p9y/random.hpp b/src/p9y/random.hpp
new file mode 100644 (file)
index 0000000..213d2ad
--- /dev/null
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "mem_config.h"
+
+#if defined __cplusplus
+# include <cstdlib>
+#else
+# include <stdlib.h>
+#endif
+
+#if !defined HAVE_RANDOM
+# if defined HAVE_RAND
+#   define random rand
+#   define srandom srand
+# endif
+#endif
diff --git a/src/p9y/realpath.c b/src/p9y/realpath.c
new file mode 100644 (file)
index 0000000..cf6430a
--- /dev/null
@@ -0,0 +1,7 @@
+#include "realpath.hpp"
+
+#if defined _WIN32
+char *realpath(const char *path, char real[_MAX_PATH]) {
+  return _fullpath(real, path, _MAX_PATH);
+}
+#endif
diff --git a/src/p9y/realpath.hpp b/src/p9y/realpath.hpp
new file mode 100644 (file)
index 0000000..ed63cfa
--- /dev/null
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "mem_config.h"
+
+#if defined __cplusplus
+# include <cstdlib>
+#else
+# include <stdlib.h>
+#endif
+
+#if !defined HAVE_REALPATH
+# if defined _WIN32
+#  if defined __cplusplus
+extern "C" {
+#  endif
+char *realpath(const char *path, char real[_MAX_PATH]);
+#  if defined __cplusplus
+}
+#  endif
+# endif // _WIN32
+#endif // HAVE_REALPATH
diff --git a/src/p9y/socket.c b/src/p9y/socket.c
new file mode 100644 (file)
index 0000000..1398e1d
--- /dev/null
@@ -0,0 +1,50 @@
+#include "socket.hpp"
+
+#if defined _WIN32
+int get_socket_errno() {
+    int local_errno = WSAGetLastError();
+
+  switch (local_errno) {
+  case WSAEINVAL:
+    local_errno = EINPROGRESS;
+    break;
+  case WSAEALREADY:
+  case WSAEWOULDBLOCK:
+    local_errno = EAGAIN;
+    break;
+
+  case WSAECONNREFUSED:
+    local_errno = ECONNREFUSED;
+    break;
+
+  case WSAENETUNREACH:
+    local_errno = ENETUNREACH;
+    break;
+
+  case WSAETIMEDOUT:
+    local_errno = ETIMEDOUT;
+    break;
+
+  case WSAECONNRESET:
+    local_errno = ECONNRESET;
+    break;
+
+  case WSAEADDRINUSE:
+    local_errno = EADDRINUSE;
+    break;
+
+  case WSAEOPNOTSUPP:
+    local_errno = EOPNOTSUPP;
+    break;
+
+  case WSAENOPROTOOPT:
+    local_errno = ENOPROTOOPT;
+    break;
+
+  default:
+    break;
+  }
+
+  return local_errno;
+}
+#endif // _WIN32
diff --git a/src/p9y/socket.hpp b/src/p9y/socket.hpp
new file mode 100644 (file)
index 0000000..339b599
--- /dev/null
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "libmemcached-1.0/platform.h"
+
+#if defined __cplusplus
+# include <cerrno>
+#else
+# include <errno.h>
+#endif
+
+#if defined HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#if defined HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#if defined HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#if defined HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+# if defined _WIN32
+int get_socket_errno();
+#  define SHUT_WR SD_SEND
+#  define SHUT_RD SD_RECEIVE
+#  define SHUT_RDWR SD_BOTH
+# else
+#   define closesocket close
+#   define get_socket_errno() errno
+#   define INVALID_SOCKET (-1)
+#   define SOCKET_ERROR (-1)
+# endif
+
+#if defined __cplusplus
+}
+#endif
+
+#if !defined SOCK_CLOEXEC
+#  define SOCK_CLOEXEC 0
+#endif
+
+#if !defined SOCK_NONBLOCK
+#  define SOCK_NONBLOCK 0
+#endif
+
+#if !defined FD_CLOEXEC
+#  define FD_CLOEXEC 0
+#endif
+
+#if !defined SO_NOSIGPIPE
+#  define SO_NOSIGPIPE 0
+#endif
+
+#if !defined TCP_NODELAY
+#  define TCP_NODELAY 0
+#endif
+
+#if !defined TCP_KEEPIDLE
+#  define TCP_KEEPIDLE 0
+#endif
+
+#if !defined EAI_SYSTEM
+#  define EAI_SYSTEM (-1)
+#endif
+
+#if !defined HAVE_MSG_NOSIGNAL
+#  define MSG_NOSIGNAL 0
+#endif
+
+#if !defined HAVE_MSG_MORE
+#  define MSG_MORE 0
+#endif
diff --git a/src/win32/getopt.c b/src/win32/getopt.c
deleted file mode 100644 (file)
index dd8cd70..0000000
+++ /dev/null
@@ -1,652 +0,0 @@
-#ifndef __GETOPT_H__
-/**
- * DISCLAIMER
- * This file is part of the mingw-w64 runtime package.
- *
- * The mingw-w64 runtime package and its code is distributed in the hope that it 
- * will be useful but WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESSED OR 
- * IMPLIED ARE HEREBY DISCLAIMED.  This includes but is not limited to 
- * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
- /*
- * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-/*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Dieter Baron and Thomas Klausner.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define __GETOPT_H__
-
-/* All the headers include this file. */
-#include <crtdefs.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <windows.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define        REPLACE_GETOPT          /* use this getopt as the system getopt(3) */
-
-#ifdef REPLACE_GETOPT
-int    opterr = 1;             /* if error message should be printed */
-int    optind = 1;             /* index into parent argv vector */
-int    optopt = '?';           /* character checked for validity */
-#undef optreset                /* see getopt.h */
-#define        optreset                __mingw_optreset
-int    optreset;               /* reset getopt */
-char    *optarg;               /* argument associated with option */
-#endif
-
-//extern int optind;           /* index of first non-option in argv      */
-//extern int optopt;           /* single option character, as parsed     */
-//extern int opterr;           /* flag to enable built-in diagnostics... */
-//                             /* (user may set to zero, to suppress)    */
-//
-//extern char *optarg;         /* pointer to argument of current option  */
-
-#define PRINT_ERROR    ((opterr) && (*options != ':'))
-
-#define FLAG_PERMUTE   0x01    /* permute non-options to the end of argv */
-#define FLAG_ALLARGS   0x02    /* treat non-options as args to option "-1" */
-#define FLAG_LONGONLY  0x04    /* operate as getopt_long_only */
-
-/* return values */
-#define        BADCH           (int)'?'
-#define        BADARG          ((*options == ':') ? (int)':' : (int)'?')
-#define        INORDER         (int)1
-
-#ifndef __CYGWIN__
-#define __progname __argv[0]
-#else
-extern char __declspec(dllimport) *__progname;
-#endif
-
-#ifdef __CYGWIN__
-static char EMSG[] = "";
-#else
-#define        EMSG            ""
-#endif
-
-static int getopt_internal(int, char * const *, const char *,
-                          const struct option *, int *, int);
-static int parse_long_options(char * const *, const char *,
-                             const struct option *, int *, int);
-static int gcd(int, int);
-static void permute_args(int, int, int, char * const *);
-
-static char *place = EMSG; /* option letter processing */
-
-/* XXX: set optreset to 1 rather than these two */
-static int nonopt_start = -1; /* first non option argument (for permute) */
-static int nonopt_end = -1;   /* first option after non options (for permute) */
-
-/* Error messages */
-static const char recargchar[] = "option requires an argument -- %c";
-static const char recargstring[] = "option requires an argument -- %s";
-static const char ambig[] = "ambiguous option -- %.*s";
-static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "unknown option -- %c";
-static const char illoptstring[] = "unknown option -- %s";
-
-static void
-_vwarnx(const char *fmt,va_list ap)
-{
-  (void)fprintf(stderr,"%s: ",__progname);
-  if (fmt != NULL)
-    (void)vfprintf(stderr,fmt,ap);
-  (void)fprintf(stderr,"\n");
-}
-
-static void
-warnx(const char *fmt,...)
-{
-  va_list ap;
-  va_start(ap,fmt);
-  _vwarnx(fmt,ap);
-  va_end(ap);
-}
-
-/*
- * Compute the greatest common divisor of a and b.
- */
-static int
-gcd(int a, int b)
-{
-       int c;
-
-       c = a % b;
-       while (c != 0) {
-               a = b;
-               b = c;
-               c = a % b;
-       }
-
-       return (b);
-}
-
-/*
- * Exchange the block from nonopt_start to nonopt_end with the block
- * from nonopt_end to opt_end (keeping the same order of arguments
- * in each block).
- */
-static void
-permute_args(int panonopt_start, int panonopt_end, int opt_end,
-       char * const *nargv)
-{
-       int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
-       char *swap;
-
-       /*
-        * compute lengths of blocks and number and size of cycles
-        */
-       nnonopts = panonopt_end - panonopt_start;
-       nopts = opt_end - panonopt_end;
-       ncycle = gcd(nnonopts, nopts);
-       cyclelen = (opt_end - panonopt_start) / ncycle;
-
-       for (i = 0; i < ncycle; i++) {
-               cstart = panonopt_end+i;
-               pos = cstart;
-               for (j = 0; j < cyclelen; j++) {
-                       if (pos >= panonopt_end)
-                               pos -= nnonopts;
-                       else
-                               pos += nopts;
-                       swap = nargv[pos];
-                       /* LINTED const cast */
-                       ((char **) nargv)[pos] = nargv[cstart];
-                       /* LINTED const cast */
-                       ((char **)nargv)[cstart] = swap;
-               }
-       }
-}
-
-#ifdef REPLACE_GETOPT
-/*
- * getopt --
- *     Parse argc/argv argument vector.
- *
- * [eventually this will replace the BSD getopt]
- */
-int
-getopt(int nargc, char * const *nargv, const char *options)
-{
-
-       /*
-        * We don't pass FLAG_PERMUTE to getopt_internal() since
-        * the BSD getopt(3) (unlike GNU) has never done this.
-        *
-        * Furthermore, since many privileged programs call getopt()
-        * before dropping privileges it makes sense to keep things
-        * as simple (and bug-free) as possible.
-        */
-       return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
-}
-#endif /* REPLACE_GETOPT */
-
-//extern int getopt(int nargc, char * const *nargv, const char *options);
-
-#ifdef _BSD_SOURCE
-/*
- * BSD adds the non-standard `optreset' feature, for reinitialisation
- * of `getopt' parsing.  We support this feature, for applications which
- * proclaim their BSD heritage, before including this header; however,
- * to maintain portability, developers are advised to avoid it.
- */
-# define optreset  __mingw_optreset
-extern int optreset;
-#endif
-#ifdef __cplusplus
-}
-#endif
-/*
- * POSIX requires the `getopt' API to be specified in `unistd.h';
- * thus, `unistd.h' includes this header.  However, we do not want
- * to expose the `getopt_long' or `getopt_long_only' APIs, when
- * included in this manner.  Thus, close the standard __GETOPT_H__
- * declarations block, and open an additional __GETOPT_LONG_H__
- * specific block, only when *not* __UNISTD_H_SOURCED__, in which
- * to declare the extended API.
- */
-#endif /* !defined(__GETOPT_H__) */
-
-#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
-#define __GETOPT_LONG_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct option          /* specification for a long form option...      */
-{
-  const char *name;            /* option name, without leading hyphens */
-  int         has_arg;         /* does it take an argument?            */
-  int        *flag;            /* where to save its status, or NULL    */
-  int         val;             /* its associated status value          */
-};
-
-enum                   /* permitted values for its `has_arg' field...  */
-{
-  no_argument = 0,             /* option never takes an argument       */
-  required_argument,           /* option always requires an argument   */
-  optional_argument            /* option may take an argument          */
-};
-
-/*
- * parse_long_options --
- *     Parse long options in argc/argv argument vector.
- * Returns -1 if short_too is set and the option does not match long_options.
- */
-static int
-parse_long_options(char * const *nargv, const char *options,
-       const struct option *long_options, int *idx, int short_too)
-{
-       char *current_argv, *has_equal;
-       size_t current_argv_len;
-       int i, ambiguous, match;
-
-#define IDENTICAL_INTERPRETATION(_x, _y)                                \
-       (long_options[(_x)].has_arg == long_options[(_y)].has_arg &&    \
-        long_options[(_x)].flag == long_options[(_y)].flag &&          \
-        long_options[(_x)].val == long_options[(_y)].val)
-
-       current_argv = place;
-       match = -1;
-       ambiguous = 0;
-
-       optind++;
-
-       if ((has_equal = strchr(current_argv, '=')) != NULL) {
-               /* argument found (--option=arg) */
-               current_argv_len = has_equal - current_argv;
-               has_equal++;
-       } else
-               current_argv_len = strlen(current_argv);
-
-       for (i = 0; long_options[i].name; i++) {
-               /* find matching long option */
-               if (strncmp(current_argv, long_options[i].name,
-                   current_argv_len))
-                       continue;
-
-               if (strlen(long_options[i].name) == current_argv_len) {
-                       /* exact match */
-                       match = i;
-                       ambiguous = 0;
-                       break;
-               }
-               /*
-                * If this is a known short option, don't allow
-                * a partial match of a single character.
-                */
-               if (short_too && current_argv_len == 1)
-                       continue;
-
-               if (match == -1)        /* partial match */
-                       match = i;
-               else if (!IDENTICAL_INTERPRETATION(i, match))
-                       ambiguous = 1;
-       }
-       if (ambiguous) {
-               /* ambiguous abbreviation */
-               if (PRINT_ERROR)
-                       warnx(ambig, (int)current_argv_len,
-                            current_argv);
-               optopt = 0;
-               return (BADCH);
-       }
-       if (match != -1) {              /* option found */
-               if (long_options[match].has_arg == no_argument
-                   && has_equal) {
-                       if (PRINT_ERROR)
-                               warnx(noarg, (int)current_argv_len,
-                                    current_argv);
-                       /*
-                        * XXX: GNU sets optopt to val regardless of flag
-                        */
-                       if (long_options[match].flag == NULL)
-                               optopt = long_options[match].val;
-                       else
-                               optopt = 0;
-                       return (BADARG);
-               }
-               if (long_options[match].has_arg == required_argument ||
-                   long_options[match].has_arg == optional_argument) {
-                       if (has_equal)
-                               optarg = has_equal;
-                       else if (long_options[match].has_arg ==
-                           required_argument) {
-                               /*
-                                * optional argument doesn't use next nargv
-                                */
-                               optarg = nargv[optind++];
-                       }
-               }
-               if ((long_options[match].has_arg == required_argument)
-                   && (optarg == NULL)) {
-                       /*
-                        * Missing argument; leading ':' indicates no error
-                        * should be generated.
-                        */
-                       if (PRINT_ERROR)
-                               warnx(recargstring,
-                                   current_argv);
-                       /*
-                        * XXX: GNU sets optopt to val regardless of flag
-                        */
-                       if (long_options[match].flag == NULL)
-                               optopt = long_options[match].val;
-                       else
-                               optopt = 0;
-                       --optind;
-                       return (BADARG);
-               }
-       } else {                        /* unknown option */
-               if (short_too) {
-                       --optind;
-                       return (-1);
-               }
-               if (PRINT_ERROR)
-                       warnx(illoptstring, current_argv);
-               optopt = 0;
-               return (BADCH);
-       }
-       if (idx)
-               *idx = match;
-       if (long_options[match].flag) {
-               *long_options[match].flag = long_options[match].val;
-               return (0);
-       } else
-               return (long_options[match].val);
-#undef IDENTICAL_INTERPRETATION
-}
-
-/*
- * getopt_internal --
- *     Parse argc/argv argument vector.  Called by user level routines.
- */
-static int
-getopt_internal(int nargc, char * const *nargv, const char *options,
-       const struct option *long_options, int *idx, int flags)
-{
-       char *oli;                              /* option letter list index */
-       int optchar, short_too;
-       static int posixly_correct = -1;
-
-       if (options == NULL)
-               return (-1);
-
-       /*
-        * XXX Some GNU programs (like cvs) set optind to 0 instead of
-        * XXX using optreset.  Work around this braindamage.
-        */
-       if (optind == 0)
-               optind = optreset = 1;
-
-       /*
-        * Disable GNU extensions if POSIXLY_CORRECT is set or options
-        * string begins with a '+'.
-        *
-        * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
-        *                 optreset != 0 for GNU compatibility.
-        */
-       if (posixly_correct == -1 || optreset != 0)
-               posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
-       if (*options == '-')
-               flags |= FLAG_ALLARGS;
-       else if (posixly_correct || *options == '+')
-               flags &= ~FLAG_PERMUTE;
-       if (*options == '+' || *options == '-')
-               options++;
-
-       optarg = NULL;
-       if (optreset)
-               nonopt_start = nonopt_end = -1;
-start:
-       if (optreset || !*place) {              /* update scanning pointer */
-               optreset = 0;
-               if (optind >= nargc) {          /* end of argument vector */
-                       place = EMSG;
-                       if (nonopt_end != -1) {
-                               /* do permutation, if we have to */
-                               permute_args(nonopt_start, nonopt_end,
-                                   optind, nargv);
-                               optind -= nonopt_end - nonopt_start;
-                       }
-                       else if (nonopt_start != -1) {
-                               /*
-                                * If we skipped non-options, set optind
-                                * to the first of them.
-                                */
-                               optind = nonopt_start;
-                       }
-                       nonopt_start = nonopt_end = -1;
-                       return (-1);
-               }
-               if (*(place = nargv[optind]) != '-' ||
-                   (place[1] == '\0' && strchr(options, '-') == NULL)) {
-                       place = EMSG;           /* found non-option */
-                       if (flags & FLAG_ALLARGS) {
-                               /*
-                                * GNU extension:
-                                * return non-option as argument to option 1
-                                */
-                               optarg = nargv[optind++];
-                               return (INORDER);
-                       }
-                       if (!(flags & FLAG_PERMUTE)) {
-                               /*
-                                * If no permutation wanted, stop parsing
-                                * at first non-option.
-                                */
-                               return (-1);
-                       }
-                       /* do permutation */
-                       if (nonopt_start == -1)
-                               nonopt_start = optind;
-                       else if (nonopt_end != -1) {
-                               permute_args(nonopt_start, nonopt_end,
-                                   optind, nargv);
-                               nonopt_start = optind -
-                                   (nonopt_end - nonopt_start);
-                               nonopt_end = -1;
-                       }
-                       optind++;
-                       /* process next argument */
-                       goto start;
-               }
-               if (nonopt_start != -1 && nonopt_end == -1)
-                       nonopt_end = optind;
-
-               /*
-                * If we have "-" do nothing, if "--" we are done.
-                */
-               if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
-                       optind++;
-                       place = EMSG;
-                       /*
-                        * We found an option (--), so if we skipped
-                        * non-options, we have to permute.
-                        */
-                       if (nonopt_end != -1) {
-                               permute_args(nonopt_start, nonopt_end,
-                                   optind, nargv);
-                               optind -= nonopt_end - nonopt_start;
-                       }
-                       nonopt_start = nonopt_end = -1;
-                       return (-1);
-               }
-       }
-
-       /*
-        * Check long options if:
-        *  1) we were passed some
-        *  2) the arg is not just "-"
-        *  3) either the arg starts with -- we are getopt_long_only()
-        */
-       if (long_options != NULL && place != nargv[optind] &&
-           (*place == '-' || (flags & FLAG_LONGONLY))) {
-               short_too = 0;
-               if (*place == '-')
-                       place++;                /* --foo long option */
-               else if (*place != ':' && strchr(options, *place) != NULL)
-                       short_too = 1;          /* could be short option too */
-
-               optchar = parse_long_options(nargv, options, long_options,
-                   idx, short_too);
-               if (optchar != -1) {
-                       place = EMSG;
-                       return (optchar);
-               }
-       }
-
-       if ((optchar = (int)*place++) == (int)':' ||
-           (optchar == (int)'-' && *place != '\0') ||
-           (oli = (char*)strchr(options, optchar)) == NULL) {
-               /*
-                * If the user specified "-" and  '-' isn't listed in
-                * options, return -1 (non-option) as per POSIX.
-                * Otherwise, it is an unknown option character (or ':').
-                */
-               if (optchar == (int)'-' && *place == '\0')
-                       return (-1);
-               if (!*place)
-                       ++optind;
-               if (PRINT_ERROR)
-                       warnx(illoptchar, optchar);
-               optopt = optchar;
-               return (BADCH);
-       }
-       if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
-               /* -W long-option */
-               if (*place)                     /* no space */
-                       /* NOTHING */;
-               else if (++optind >= nargc) {   /* no arg */
-                       place = EMSG;
-                       if (PRINT_ERROR)
-                               warnx(recargchar, optchar);
-                       optopt = optchar;
-                       return (BADARG);
-               } else                          /* white space */
-                       place = nargv[optind];
-               optchar = parse_long_options(nargv, options, long_options,
-                   idx, 0);
-               place = EMSG;
-               return (optchar);
-       }
-       if (*++oli != ':') {                    /* doesn't take argument */
-               if (!*place)
-                       ++optind;
-       } else {                                /* takes (optional) argument */
-               optarg = NULL;
-               if (*place)                     /* no white space */
-                       optarg = place;
-               else if (oli[1] != ':') {       /* arg not optional */
-                       if (++optind >= nargc) {        /* no arg */
-                               place = EMSG;
-                               if (PRINT_ERROR)
-                                       warnx(recargchar, optchar);
-                               optopt = optchar;
-                               return (BADARG);
-                       } else
-                               optarg = nargv[optind];
-               }
-               place = EMSG;
-               ++optind;
-       }
-       /* dump back option letter */
-       return (optchar);
-}
-
-/*
- * getopt_long --
- *     Parse argc/argv argument vector.
- */
-int
-getopt_long(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
-{
-
-       return (getopt_internal(nargc, nargv, options, long_options, idx,
-           FLAG_PERMUTE));
-}
-
-/*
- * getopt_long_only --
- *     Parse argc/argv argument vector.
- */
-int
-getopt_long_only(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
-{
-
-       return (getopt_internal(nargc, nargv, options, long_options, idx,
-           FLAG_PERMUTE|FLAG_LONGONLY));
-}
-
-//extern int getopt_long(int nargc, char * const *nargv, const char *options,
-//    const struct option *long_options, int *idx);
-//extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
-//    const struct option *long_options, int *idx);
-/*
- * Previous MinGW implementation had...
- */
-#ifndef HAVE_DECL_GETOPT
-/*
- * ...for the long form API only; keep this for compatibility.
- */
-# define HAVE_DECL_GETOPT      1
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
diff --git a/src/win32/getopt.h b/src/win32/getopt.h
deleted file mode 100644 (file)
index 8f0835b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-extern "C" {
-
-extern int opterr;    /* if error message should be printed */
-extern int optind;    /* index into parent argv vector */
-extern char *optarg;  /* argument associated with option */
-
-struct option    /* specification for a long form option...  */
-{
-  const char *name;       /* option name, without leading hyphens */
-  int         has_arg;    /* does it take an argument?    */
-  int        *flag;       /* where to save its status, or NULL  */
-  int         val;        /* its associated status value    */
-};
-
-enum            /* permitted values for its `has_arg' field...  */
-{
-  no_argument = 0,        /* option never takes an argument  */
-  required_argument,      /* option always requires an argument  */
-  optional_argument       /* option may take an argument    */
-};
-
-int getopt(int nargc, char * const *nargv, const char *options);
-int getopt_long(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx);
-int getopt_long_only(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx);
-
-}
\ No newline at end of file
index e522f9cc194b19412460a136c491f1f318c810b4..083efe0d66f060eaa2f4dd2baa2e7de7efc6659a 100644 (file)
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <chrono>
+#include <cstring>
 #include <iostream>
 #include <map>
 #include <optional>