OSDN Git Service

Overhaul WinSock fd_set content management macros.
authorKeith Marshall <keith@users.osdn.me>
Wed, 8 Nov 2017 17:46:34 +0000 (17:46 +0000)
committerKeith Marshall <keith@users.osdn.me>
Wed, 8 Nov 2017 17:46:34 +0000 (17:46 +0000)
w32api/ChangeLog
w32api/include/winsock.h
w32api/tests/winsock.at

index d81c326..092ff33 100644 (file)
@@ -1,3 +1,20 @@
+2017-11-08  Keith Marshall  <keith@users.osdn.me>
+
+       Overhaul WinSock fd_set content management macros.
+
+       * include/winsock.h (FD_SET, FD_ISSET, FD_CLR, FD_ZERO): Replace the
+       original implementations of each of these macros, redirecting to...
+       (__FD_SET, __FD_ISSET, __FD_CLR, __FD_ZERO): ...these new, equivalent
+       inline functions, respectively; these are more robust, and correct a
+       defect in the original FD_SET macro implementation, whereby duplicate
+       descriptors could be added to an fd_set array, but would not then be
+       removed by the corresponding FD_CLR macro.
+
+       * tests/winsock.at (MINGW_AT_CHECK_WINSOCK): Ensure that all test
+       programs are linked with -lwsock32 or -lws2_32, as appropriate; the
+       __FD_SET and __FD_ISSET functions are dependent on the __WSAFDIsSet()
+       function, which is implemented in each of these libraries.
+
 2017-11-07  Keith Marshall  <keith@users.osdn.me>
 
        Identify features which have been deprecated in WinSock v2.
index 789ab04..7049230 100644 (file)
@@ -120,39 +120,51 @@ struct fd_set
   SOCKET       fd_array[FD_SETSIZE];
 } fd_set;
 
-int PASCAL __WSAFDIsSet (SOCKET, fd_set *);
+#ifndef FD_ISSET
+int FD_ISSET (SOCKET, fd_set *);
+#define FD_ISSET( __fd, __set )  __FD_ISSET ((__fd), (__set))
 
-#ifndef FD_CLR
-#define FD_CLR( fd, set )  do                                  \
-  { u_int __i;                                                 \
-    for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++)   \
-    { if (((fd_set *)(set))->fd_array[__i] == (fd))            \
-      { while (__i < ((fd_set *)(set))->fd_count-1)            \
-       { ((fd_set *)(set))->fd_array[__i]                      \
-           = ((fd_set *)(set))->fd_array[__i + 1]; __i++;      \
-       }                                                       \
-       ((fd_set *)(set))->fd_count--;                          \
-       break;                                                  \
-      }                                                        \
-    }                                                          \
-  } while (0)
-#endif /* ! defined FD_CLR */
+/* Microsoft provide this library function equivalent of the FD_ISSET
+ * macro, and erroneously claim that it is neccessary to implement the
+ * macro.  We could just as easily implement it entirely inline...
+ */
+int PASCAL __WSAFDIsSet (SOCKET, fd_set *);
+/* ...but, given the availability of the library function, we may just
+ * as well use it.
+ */
+__CRT_ALIAS int __FD_ISSET( SOCKET __fd, fd_set *__set )
+{ return __WSAFDIsSet (__fd, __set); }
+#endif /* ! defined FD_ISSET */
 
 #ifndef FD_SET
-#define FD_SET( fd, set )  do                                             \
-  { if (((fd_set *)(set))->fd_count < FD_SETSIZE)                         \
-       ((fd_set *)(set))->fd_array[((fd_set *)(set))->fd_count++] = (fd);  \
-  } while (0)
+void FD_SET (SOCKET, fd_set *);
+#define FD_SET( __fd, __set )  __FD_SET ((__fd), (__set))
+__CRT_ALIAS void __FD_SET (SOCKET __fd, fd_set *__set)
+{ if( (__set->fd_count < FD_SETSIZE) && ! FD_ISSET (__fd, __set) )
+    __set->fd_array[__set->fd_count++] = __fd;
+}
 #endif /* ! defined FD_SET */
 
+#ifndef FD_CLR
+void FD_CLR (SOCKET, fd_set *);
+#define FD_CLR( __fd, __set )  __FD_CLR ((__fd), (__set))
+__CRT_ALIAS void __FD_CLR (SOCKET __fd, fd_set *__set)
+{ u_int __m, __n; for (__m = __n = 0; __n < __set->fd_count; __n++)
+  { if (__fd != __set->fd_array[__n])
+    { if (__m < __n) __set->fd_array[__m] = __set->fd_array[__n];
+      ++__m;
+    }
+  } __set->fd_count = __m;
+}
+#endif /* ! defined FD_CLR */
+
 #ifndef FD_ZERO
-#define FD_ZERO( set )  (((fd_set *)(set))->fd_count = 0)
+void FD_ZERO (fd_set *);
+#define FD_ZERO( __set )  __FD_ZERO (__set)
+__CRT_ALIAS void __FD_ZERO (fd_set *__set)
+{ __set->fd_count = 0; }
 #endif /* ! defined FD_ZERO */
 
-#ifndef FD_ISSET
-#define FD_ISSET( fd, set )  __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set))
-#endif /* ! defined FD_ISSET */
-
 #elif ! defined _USE_SYS_TYPES_FD_SET
 /* Definitions from <sys/types.h> probably aren't what the user wants;
  * if they know what they are doing, and they are sure that this really
@@ -562,7 +574,7 @@ int PASCAL gethostname (char *, int );
 #define WSAGETSELECTEVENT(l)                   LOWORD(l)
 #define WSAGETSELECTERROR(l)                   HIWORD(l)
 
-typedef struct fd_set FD_SET, *PFD_SET, *LPFD_SET;
+typedef struct fd_set /* FD_SET, */ *PFD_SET, *LPFD_SET;
 typedef struct sockaddr SOCKADDR, *PSOCKADDR, *LPSOCKADDR;
 typedef struct sockaddr_in SOCKADDR_IN, *PSOCKADDR_IN, *LPSOCKADDR_IN;
 typedef struct linger LINGER, *PLINGER, *LPLINGER;
index e92c31b..9879f60 100644 (file)
@@ -97,6 +97,7 @@ AT_CLEANUP])
 #
 m4_define([MINGW_AT_CHECK_WINSOCK],[dnl
 AT_BANNER([Windows Sockets $1 fd_set macro checks.])
+MINGW_AT_LINK_LIBS([m4_case([$1],[v2],[-lws2_32],[-lwsock32])])
 
 # Verify that the FD_ZERO macro clears all descriptors from the
 # predefined, non-empty fd_set {1, 2, 3, 4}
@@ -157,7 +158,6 @@ MINGW_AT_CHECK_FD_MACRO([$2],[FD_CLR],dnl
 # function, we must ensure that the test code is linked with
 # the appropriate version of the WinSock library.
 #
-MINGW_AT_LINK_LIBS([m4_case([$1],[v2],[-lws2_32],[-lwsock32])])
 MINGW_AT_CHECK_FD_ISSET_MACRO([$2],[4])
 MINGW_AT_CHECK_FD_ISSET_MACRO([$2],[2])