eal/windows: add fnmatch implementation
authorPallavi Kadam <pallavi.kadam@intel.com>
Wed, 6 May 2020 01:30:31 +0000 (18:30 -0700)
committerThomas Monjalon <thomas@monjalon.net>
Thu, 7 May 2020 10:18:17 +0000 (12:18 +0200)
Fnmatch implementation is required on Windows to support
log level arguments specified with a globbing pattern.
The source file is with BSD-3-Clause license.
https://github.com/lattera/freebsd/blob/master/usr.bin/csup/fnmatch.c

Signed-off-by: Pallavi Kadam <pallavi.kadam@intel.com>
Reviewed-by: Ranjit Menon <ranjit.menon@intel.com>
Reviewed-by: Tasnim Bashar <tbashar@mellanox.com>
Tested-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Acked-by: Narcisa Vasile <navasile@linux.microsoft.com>
lib/librte_eal/windows/fnmatch.c [new file with mode: 0644]
lib/librte_eal/windows/include/fnmatch.h
lib/librte_eal/windows/meson.build

diff --git a/lib/librte_eal/windows/fnmatch.c b/lib/librte_eal/windows/fnmatch.c
new file mode 100644 (file)
index 0000000..f622bf5
--- /dev/null
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)fnmatch.c    8.2 (Berkeley) 4/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "fnmatch.h"
+
+#define EOS    '\0'
+
+static const char *rangematch(const char *, char, int);
+
+int
+fnmatch(const char *pattern, const char *string, int flags)
+{
+       const char *stringstart;
+       char c, test;
+
+       for (stringstart = string;;)
+               switch (c = *pattern++) {
+               case EOS:
+                       if ((flags & FNM_LEADING_DIR) && *string == '/')
+                               return (0);
+                       return (*string == EOS ? 0 : FNM_NOMATCH);
+               case '?':
+                       if (*string == EOS)
+                               return (FNM_NOMATCH);
+                       if (*string == '/' && (flags & FNM_PATHNAME))
+                               return (FNM_NOMATCH);
+                       if (*string == '.' && (flags & FNM_PERIOD) &&
+                           (string == stringstart ||
+                           ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+                               return (FNM_NOMATCH);
+                       ++string;
+                       break;
+               case '*':
+                       c = *pattern;
+                       /* Collapse multiple stars. */
+                       while (c == '*')
+                               c = *++pattern;
+
+                       if (*string == '.' && (flags & FNM_PERIOD) &&
+                           (string == stringstart ||
+                           ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+                               return (FNM_NOMATCH);
+
+                       /* Optimize for pattern with * at end or before /. */
+                       if (c == EOS)
+                               if (flags & FNM_PATHNAME)
+                                       return ((flags & FNM_LEADING_DIR) ||
+                                           strchr(string, '/') == NULL ?
+                                           0 : FNM_NOMATCH);
+                               else
+                                       return (0);
+                       else if (c == '/' && flags & FNM_PATHNAME) {
+                               string = strchr(string, '/');
+                               if (string == NULL)
+                                       return (FNM_NOMATCH);
+                               break;
+                       }
+
+                       /* General case, use recursion. */
+                       while ((test = *string) != EOS) {
+                               if (!fnmatch(pattern, string,
+                                       flags & ~FNM_PERIOD))
+                                       return (0);
+                               if (test == '/' && flags & FNM_PATHNAME)
+                                       break;
+                               ++string;
+                       }
+                       return (FNM_NOMATCH);
+               case '[':
+                       if (*string == EOS)
+                               return (FNM_NOMATCH);
+                       if (*string == '/' && flags & FNM_PATHNAME)
+                               return (FNM_NOMATCH);
+                       pattern = rangematch(pattern, *string, flags);
+                       if (pattern == NULL)
+                               return (FNM_NOMATCH);
+                       ++string;
+                       break;
+               case '\\':
+                       if (!(flags & FNM_NOESCAPE)) {
+                               c = *pattern++;
+                               if (c == EOS) {
+                                       c = '\\';
+                                       --pattern;
+                               }
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       if (c == *string)
+                               ;
+                       else if ((flags & FNM_CASEFOLD) &&
+                                (tolower((unsigned char)c) ==
+                                 tolower((unsigned char)*string)))
+                               ;
+                       else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
+                            ((c == '/' && string != stringstart) ||
+                            (string == stringstart+1 && *stringstart == '/')))
+                               return (0);
+                       else
+                               return (FNM_NOMATCH);
+                       string++;
+                       break;
+               }
+       /* NOTREACHED */
+}
+
+static const char *
+rangematch(const char *pattern, char test, int flags)
+{
+       int negate, ok;
+       char c, c2;
+
+       /*
+        * A bracket expression starting with an unquoted circumflex
+        * character produces unspecified results (IEEE 1003.2-1992,
+        * 3.13.2).  This implementation treats it like '!', for
+        * consistency with the regular expression syntax.
+        * J.T. Conklin (conklin@ngai.kaleida.com)
+        */
+       negate = (*pattern == '!' || *pattern == '^');
+       if (negate)
+               ++pattern;
+
+       if (flags & FNM_CASEFOLD)
+               test = tolower((unsigned char)test);
+
+       for (ok = 0; (c = *pattern++) != ']';) {
+               if (c == '\\' && !(flags & FNM_NOESCAPE))
+                       c = *pattern++;
+               if (c == EOS)
+                       return (NULL);
+
+               if (flags & FNM_CASEFOLD)
+                       c = tolower((unsigned char)c);
+
+               c2 = *(pattern + 1);
+               if (*pattern == '-' && c2 != EOS && c2 != ']') {
+                       pattern += 2;
+                       if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+                               c2 = *pattern++;
+                       if (c2 == EOS)
+                               return (NULL);
+
+                       if (flags & FNM_CASEFOLD)
+                               c2 = tolower((unsigned char)c2);
+
+                       if ((unsigned char)c <= (unsigned char)test &&
+                           (unsigned char)test <= (unsigned char)c2)
+                               ok = 1;
+               } else if (c == test)
+                       ok = 1;
+       }
+       return (ok == negate ? NULL : pattern);
+}
index d0159f0..142753c 100644 (file)
@@ -18,6 +18,13 @@ extern "C" {
 
 #define FNM_NOMATCH 1
 
+#define FNM_NOESCAPE 0x01
+#define FNM_PATHNAME 0x02
+#define FNM_PERIOD 0x04
+#define FNM_LEADING_DIR 0x08
+#define FNM_CASEFOLD 0x10
+#define FNM_PREFIX_DIRS 0x20
+
 /**
  * This function is used for searhing a given string source
  * with the given regular expression pattern.
@@ -34,14 +41,7 @@ extern "C" {
  * @return
  *     if the pattern is found then return 0 or else FNM_NOMATCH
  */
-static inline int fnmatch(__rte_unused const char *pattern,
-               __rte_unused const char *string,
-               __rte_unused int flags)
-{
-       /* TODO */
-       /* This is a stub, not the expected result */
-       return FNM_NOMATCH;
-}
+int fnmatch(const char *pattern, const char *string, int flags);
 
 #ifdef __cplusplus
 }
index 09dd4ab..8829407 100644 (file)
@@ -8,5 +8,6 @@ sources += files(
        'eal_debug.c',
        'eal_lcore.c',
        'eal_thread.c',
+       'fnmatch.c',
        'getopt.c',
 )