aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali@kernel.org>2021-12-26 18:19:25 +0100
committerMartin Mares <mj@ucw.cz>2021-12-28 16:26:39 +0100
commitdce0da6171f039d151f7a85db5a44ed57e20fcdf (patch)
treeae79edda4213d071bda0889df7561880e5b1bdc8
parent4658bfad1878c47e2cb6a42ec5dbd9b0ad6739dd (diff)
downloadpciutils-dce0da6171f039d151f7a85db5a44ed57e20fcdf.tar.gz
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 <string.h> 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 <string.h> header file cause compile errors for i586-mingw32msvc-gcc compiler. Instead of including <stringh> 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.
-rw-r--r--compat/getopt.c28
-rw-r--r--compat/getopt.h5
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 <stdio.h>
-#include <string.h>
/* 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 <string.h>
#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,