From dce0da6171f039d151f7a85db5a44ed57e20fcdf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Sun, 26 Dec 2021 18:19:25 +0100 Subject: [PATCH] compat/getopt: Fix compatibility with non-GNU C library Remove "#if defined(__GNU_LIBRARY__)" guard for getopt() function prototype in compat/getopt.h header file. The only purpose of compat/getopt.h header is to provide getopt() function prototype for compatibility purpose on every platform, specially those which do not use GNU C library (e.g. Windows). Without this change i586-mingw32msvc-gcc compiler complains that function getopt() is used without defined prototype. Also remove inclusion of #include header file in compat/getopt.c source file. Probably due to compatibility purposes compat/getopt.c file has defined custom prototype for function strncmp() incompatible with C99 (length argument in C99 should be of type size_t). Including C99 prototype of strncmp() function from MinGW32 header file cause compile errors for i586-mingw32msvc-gcc compiler. Instead of including provides custom and simple my_strncmp() implementation. Thsi change fixes compilation of compat/getopt.c with i586-mingw32msvc-gcc, i686-w64-mingw32-gcc, x86_64-w64-mingw32-gcc and also MSVC cl compilers. --- compat/getopt.c | 28 +++++++++++++++++++++++----- compat/getopt.h | 5 ----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/compat/getopt.c b/compat/getopt.c index 1d0beb7..f3ccb4b 100644 --- a/compat/getopt.c +++ b/compat/getopt.c @@ -36,7 +36,6 @@ #endif #include -#include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C @@ -163,6 +162,8 @@ static enum { #include #define my_index strchr #define my_strlen strlen +#define my_strcmp strcmp +#define my_strncmp strncmp #else /* Avoid depending on library functions or files @@ -170,11 +171,11 @@ static enum { #if __STDC__ || defined(PROTO) extern char *getenv(const char *name); -extern int strcmp(const char *s1, const char *s2); -extern int strncmp(const char *s1, const char *s2, int n); static int my_strlen(const char *s); static char *my_index(const char *str, int chr); +static int my_strncmp(const char *s1, const char *s2, int n); +static int my_strcmp(const char *s1, const char *s2); #else extern char *getenv(); #endif @@ -197,6 +198,23 @@ static char *my_index(const char *str, int chr) return 0; } +static int my_strncmp(const char *s1, const char *s2, int n) +{ + while (n && *s1 && (*s1 == *s2)) { + ++s1; + ++s2; + --n; + } + if (n == 0) + return 0; + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} + +static int my_strcmp(const char *s1, const char *s2) +{ + return my_strncmp(s1, s2, -1); +} + #endif /* GNU C library. */ /* Handle permutation of arguments. */ @@ -385,7 +403,7 @@ int _getopt_internal(int argc, char *const *argv, const char *optstring, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ - if (optind != argc && !strcmp(argv[optind], "--")) { + if (optind != argc && !my_strcmp(argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) @@ -445,7 +463,7 @@ int _getopt_internal(int argc, char *const *argv, const char *optstring, /* Test all options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, nextchar, s - nextchar)) { + if (!my_strncmp(p->name, nextchar, s - nextchar)) { if (s - nextchar == my_strlen(p->name)) { /* Exact match found. */ pfound = p; diff --git a/compat/getopt.h b/compat/getopt.h index 0abce6e..e7b4bfe 100644 --- a/compat/getopt.h +++ b/compat/getopt.h @@ -95,12 +95,7 @@ struct option #define optional_argument 2 #if __STDC__ || defined(PROTO) -#if defined(__GNU_LIBRARY__) -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); -#endif /* not __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, -- 2.39.5