From 3d374692f7dcdea4e7fb18b77ecf32d39fb367db Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Mon, 3 May 2021 16:26:38 +0100 Subject: [PATCH] Eina: API addition: interface musl's fnmatch() implementation Summary: addd musl's fnmatch() implementation to Eina Test Plan: compilation and simple test case Reviewers: raster Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12261 --- src/lib/eina/Eina.h | 1 + src/lib/eina/eina_fnmatch.c | 47 +++++ src/lib/eina/eina_fnmatch.h | 34 ++++ src/lib/eina/meson.build | 2 + src/static_libs/fnmatch/COPYRIGHT | 193 ++++++++++++++++++ src/static_libs/fnmatch/fnmatch.c | 325 ++++++++++++++++++++++++++++++ src/static_libs/fnmatch/fnmatch.h | 28 +++ 7 files changed, 630 insertions(+) create mode 100644 src/lib/eina/eina_fnmatch.c create mode 100644 src/lib/eina/eina_fnmatch.h create mode 100644 src/static_libs/fnmatch/COPYRIGHT create mode 100644 src/static_libs/fnmatch/fnmatch.c create mode 100644 src/static_libs/fnmatch/fnmatch.h diff --git a/src/lib/eina/Eina.h b/src/lib/eina/Eina.h index d2ce89e805..da73953362 100644 --- a/src/lib/eina/Eina.h +++ b/src/lib/eina/Eina.h @@ -214,6 +214,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/src/lib/eina/eina_fnmatch.c b/src/lib/eina/eina_fnmatch.c new file mode 100644 index 0000000000..697a06edb0 --- /dev/null +++ b/src/lib/eina/eina_fnmatch.c @@ -0,0 +1,47 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 Rich Felker + * Copyright (C) 2021 Vincent Torri + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#include +#include +#include +#include + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_fnmatch.h" +#include "../../static_libs/fnmatch/fnmatch.h" +#include "../../static_libs/fnmatch/fnmatch.c" + +/*============================================================================* + * Local * + *============================================================================*/ + +/*============================================================================* + * Global * + *============================================================================*/ + +/*============================================================================* + * API * + *============================================================================*/ + +EINA_API Eina_Bool +eina_fnmatch(const char *glob, const char *string, Eina_Fnmatch_Flags flags) +{ + return (__fnmatch(glob, string, flags) == 0); +} diff --git a/src/lib/eina/eina_fnmatch.h b/src/lib/eina/eina_fnmatch.h new file mode 100644 index 0000000000..2cb16ff7f1 --- /dev/null +++ b/src/lib/eina/eina_fnmatch.h @@ -0,0 +1,34 @@ +/* EINA - EFL data type library + * Copyright (C) 2021 Vincent Torri + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifndef EINA_FNMATCH_H +#define EINA_FNMATCH_H + +typedef enum +{ + EINA_FNMATCH_PATHNAME = (1 << 0), + EINA_FNMATCH_NOESCAPE = (1 << 1), + EINA_FNMATCH_PERIOD = (1 << 2), + EINA_FNMATCH_LEADING_DIR = (1 << 3), + EINA_FNMATCH_CASEFOLD = (1 << 4), + EINA_FNMATCH_FILE_NAME = EINA_FNMATCH_PATHNAME, +} Eina_Fnmatch_Flags; + +EINA_API Eina_Bool eina_fnmatch(const char *glob, const char *string, Eina_Fnmatch_Flags flags); + +#endif diff --git a/src/lib/eina/meson.build b/src/lib/eina/meson.build index afe945d754..f611bf4c5a 100644 --- a/src/lib/eina/meson.build +++ b/src/lib/eina/meson.build @@ -19,6 +19,7 @@ public_sub_headers = [ 'eina_debug_private.h', 'eina_log.h', 'eina_inline_log.x', +'eina_fnmatch.h', 'eina_fp.h', 'eina_inline_f32p32.x', 'eina_inline_f16p16.x', @@ -142,6 +143,7 @@ eina_src = files([ 'eina_evlog.c', 'eina_file_common.h', 'eina_file_common.c', +'eina_fnmatch.c', 'eina_fp.c', 'eina_hamster.c', 'eina_hash.c', diff --git a/src/static_libs/fnmatch/COPYRIGHT b/src/static_libs/fnmatch/COPYRIGHT new file mode 100644 index 0000000000..c1628e9ac8 --- /dev/null +++ b/src/static_libs/fnmatch/COPYRIGHT @@ -0,0 +1,193 @@ +musl as a whole is licensed under the following standard MIT license: + +---------------------------------------------------------------------- +Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +---------------------------------------------------------------------- + +Authors/contributors include: + +A. Wilcox +Ada Worcester +Alex Dowad +Alex Suykov +Alexander Monakov +Andre McCurdy +Andrew Kelley +Anthony G. Basile +Aric Belsito +Arvid Picciani +Bartosz Brachaczek +Benjamin Peterson +Bobby Bingham +Boris Brezillon +Brent Cook +Chris Spiegel +Clément Vasseur +Daniel Micay +Daniel Sabogal +Daurnimator +David Carlier +David Edelsohn +Denys Vlasenko +Dmitry Ivanov +Dmitry V. Levin +Drew DeVault +Emil Renner Berthing +Fangrui Song +Felix Fietkau +Felix Janda +Gianluca Anzolin +Hauke Mehrtens +He X +Hiltjo Posthuma +Isaac Dunham +Jaydeep Patil +Jens Gustedt +Jeremy Huntwork +Jo-Philipp Wich +Joakim Sindholt +John Spencer +Julien Ramseier +Justin Cormack +Kaarle Ritvanen +Khem Raj +Kylie McClain +Leah Neukirchen +Luca Barbato +Luka Perkov +M Farkas-Dyck (Strake) +Mahesh Bodapati +Markus Wichmann +Masanori Ogino +Michael Clark +Michael Forney +Mikhail Kremnyov +Natanael Copa +Nicholas J. Kain +orc +Pascal Cuoq +Patrick Oppenlander +Petr Hosek +Petr Skocik +Pierre Carrier +Reini Urban +Rich Felker +Richard Pennington +Ryan Fairfax +Samuel Holland +Segev Finer +Shiz +sin +Solar Designer +Stefan Kristiansson +Stefan O'Rear +Szabolcs Nagy +Timo Teräs +Trutz Behn +Valentin Ochs +Will Dietz +William Haddon +William Pitcock + +Portions of this software are derived from third-party works licensed +under terms compatible with the above MIT license: + +The TRE regular expression implementation (src/regex/reg* and +src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed +under a 2-clause BSD license (license text in the source files). The +included version has been heavily modified by Rich Felker in 2012, in +the interests of size, simplicity, and namespace cleanliness. + +Much of the math library code (src/math/* and src/complex/*) is +Copyright © 1993,2004 Sun Microsystems or +Copyright © 2003-2011 David Schultz or +Copyright © 2003-2009 Steven G. Kargl or +Copyright © 2003-2009 Bruce D. Evans or +Copyright © 2008 Stephen L. Moshier or +Copyright © 2017-2018 Arm Limited +and labelled as such in comments in the individual source files. All +have been licensed under extremely permissive terms. + +The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 +The Android Open Source Project and is licensed under a two-clause BSD +license. It was taken from Bionic libc, used on Android. + +The AArch64 memcpy and memset code (src/string/aarch64/*) are +Copyright © 1999-2019, Arm Limited. + +The implementation of DES for crypt (src/crypt/crypt_des.c) is +Copyright © 1994 David Burren. It is licensed under a BSD license. + +The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was +originally written by Solar Designer and placed into the public +domain. The code also comes with a fallback permissive license for use +in jurisdictions that may not recognize the public domain. + +The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 +Valentin Ochs and is licensed under an MIT-style license. + +The x86_64 port was written by Nicholas J. Kain and is licensed under +the standard MIT terms. + +The mips and microblaze ports were originally written by Richard +Pennington for use in the ellcc project. The original code was adapted +by Rich Felker for build system and code conventions during upstream +integration. It is licensed under the standard MIT terms. + +The mips64 port was contributed by Imagination Technologies and is +licensed under the standard MIT terms. + +The powerpc port was also originally written by Richard Pennington, +and later supplemented and integrated by John Spencer. It is licensed +under the standard MIT terms. + +All other files which have no copyright comments are original works +produced specifically for use as part of this library, written either +by Rich Felker, the main author of the library, or by one or more +contibutors listed above. Details on authorship of individual files +can be found in the git version control history of the project. The +omission of copyright and license comments in each file is in the +interest of source tree size. + +In addition, permission is hereby granted for all public header files +(include/* and arch/*/bits/*) and crt files intended to be linked into +applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit +the copyright notice and permission notice otherwise required by the +license, and to use these files without any requirement of +attribution. These files include substantial contributions from: + +Bobby Bingham +John Spencer +Nicholas J. Kain +Rich Felker +Richard Pennington +Stefan Kristiansson +Szabolcs Nagy + +all of whom have explicitly granted such permission. + +This file previously contained text expressing a belief that most of +the files covered by the above exception were sufficiently trivial not +to be subject to copyright, resulting in confusion over whether it +negated the permissions granted in the license. In the spirit of +permissive licensing, and of not having licensing issues being an +obstacle to adoption, that text has been removed. diff --git a/src/static_libs/fnmatch/fnmatch.c b/src/static_libs/fnmatch/fnmatch.c new file mode 100644 index 0000000000..089ccb5cbf --- /dev/null +++ b/src/static_libs/fnmatch/fnmatch.c @@ -0,0 +1,325 @@ +/* + * LICENSE: MIT, see COPYRIGHT file in the directory + */ + +/* + * An implementation of what I call the "Sea of Stars" algorithm for + * POSIX fnmatch(). The basic idea is that we factor the pattern into + * a head component (which we match first and can reject without ever + * measuring the length of the string), an optional tail component + * (which only exists if the pattern contains at least one star), and + * an optional "sea of stars", a set of star-separated components + * between the head and tail. After the head and tail matches have + * been removed from the input string, the components in the "sea of + * stars" are matched sequentially by searching for their first + * occurrence past the end of the previous match. + * + * - Rich Felker, April 2012 + */ + +#include +#include "fnmatch.h" +#include +#include +#include +/* #include "locale_impl.h" */ + +#define END 0 +#define UNMATCHABLE -2 +#define BRACKET -3 +#define QUESTION -4 +#define STAR -5 + +static int str_next(const char *str, size_t n, size_t *step) +{ + if (!n) { + *step = 0; + return 0; + } + if (str[0] >= 128U) { + wchar_t wc; + int k = mbtowc(&wc, str, n); + if (k<0) { + *step = 1; + return -1; + } + *step = k; + return wc; + } + *step = 1; + return str[0]; +} + +static int pat_next(const char *pat, size_t m, size_t *step, int flags) +{ + int esc = 0; + if (!m || !*pat) { + *step = 0; + return END; + } + *step = 1; + if (pat[0]=='\\' && pat[1] && !(flags & __FNM_NOESCAPE)) { + *step = 2; + pat++; + esc = 1; + goto escaped; + } + if (pat[0]=='[') { + size_t k = 1; + if (k= 128U) { + wchar_t wc; + int k = mbtowc(&wc, pat, m); + if (k<0) { + *step = 0; + return UNMATCHABLE; + } + *step = k + esc; + return wc; + } + return pat[0]; +} + +static int casefold(int k) +{ + int c = towupper(k); + return c == k ? towlower(k) : c; +} + +static int match_bracket(const char *p, int k, int kfold) +{ + wchar_t wc; + int inv = 0; + p++; + if (*p=='^' || *p=='!') { + inv = 1; + p++; + } + if (*p==']') { + if (k==']') return !inv; + p++; + } else if (*p=='-') { + if (k=='-') return !inv; + p++; + } + wc = p[-1]; + for (; *p != ']'; p++) { + if (p[0]=='-' && p[1]!=']') { + wchar_t wc2; + int l = mbtowc(&wc2, p+1, 4); + if (l < 0) return 0; + if (wc <= wc2) + if ((unsigned)k-wc <= wc2-wc || + (unsigned)kfold-wc <= wc2-wc) + return !inv; + p += l-1; + continue; + } + if (p[0]=='[' && (p[1]==':' || p[1]=='.' || p[1]=='=')) { + const char *p0 = p+2; + int z = p[1]; + p+=3; + while (p[-1]!=z || p[0]!=']') p++; + if (z == ':' && p-1-p0 < 16) { + char buf[16]; + memcpy(buf, p0, p-1-p0); + buf[p-1-p0] = 0; + if (iswctype(k, wctype(buf)) || + iswctype(kfold, wctype(buf))) + return !inv; + } + continue; + } + if (*p < 128U) { + wc = (unsigned char)*p; + } else { + int l = mbtowc(&wc, p, 4); + if (l < 0) return 0; + p += l-1; + } + if (wc==k || wc==kfold) return !inv; + } + return inv; +} + +static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n, int flags) +{ + const char *p, *ptail, *endpat; + const char *s, *stail, *endstr; + size_t pinc, sinc, tailcnt=0; + int c, k, kfold; + + if (flags & __FNM_PERIOD) { + if (*str == '.' && *pat != '.') + return __FNM_NOMATCH; + } + for (;;) { + switch ((c = pat_next(pat, m, &pinc, flags))) { + case UNMATCHABLE: + return __FNM_NOMATCH; + case STAR: + pat++; + m--; + break; + default: + k = str_next(str, n, &sinc); + if (k <= 0) + return (c==END) ? 0 : __FNM_NOMATCH; + str += sinc; + n -= sinc; + kfold = flags & __FNM_CASEFOLD ? casefold(k) : k; + if (c == BRACKET) { + if (!match_bracket(pat, k, kfold)) + return __FNM_NOMATCH; + } else if (c != QUESTION && k != c && kfold != c) { + return __FNM_NOMATCH; + } + pat+=pinc; + m-=pinc; + continue; + } + break; + } + + /* Compute real pat length if it was initially unknown/-1 */ + m = strnlen(pat, m); + endpat = pat + m; + + /* Find the last * in pat and count chars needed after it */ + for (p=ptail=pat; pstr && tailcnt; tailcnt--) { + if (s[-1] < 128U || MB_CUR_MAX==1) s--; + else while ((unsigned char)*--s-0x80U<0x40 && s>str); + } + if (tailcnt) return __FNM_NOMATCH; + stail = s; + + /* Check that the pat and str tails match */ + p = ptail; + for (;;) { + c = pat_next(p, endpat-p, &pinc, flags); + p += pinc; + if ((k = str_next(s, endstr-s, &sinc)) <= 0) { + if (c != END) return __FNM_NOMATCH; + break; + } + s += sinc; + kfold = flags & __FNM_CASEFOLD ? casefold(k) : k; + if (c == BRACKET) { + if (!match_bracket(p-pinc, k, kfold)) + return __FNM_NOMATCH; + } else if (c != QUESTION && k != c && kfold != c) { + return __FNM_NOMATCH; + } + } + + /* We're all done with the tails now, so throw them out */ + endstr = stail; + endpat = ptail; + + /* Match pattern components until there are none left */ + while (pat 0) str += sinc; + else for (str++; str_next(str, endstr-str, &sinc)<0; str++); + } + + return 0; +} + +int __fnmatch(const char *pat, const char *str, int flags) +{ + const char *s, *p; + size_t inc; + int c; + if (flags & __FNM_PATHNAME) for (;;) { + for (s=str; *s && *s!='/'; s++); + for (p=pat; (c=pat_next(p, -1, &inc, flags))!=END && c!='/'; p+=inc); + if (c!=*s && (!*s || !(flags & __FNM_LEADING_DIR))) + return __FNM_NOMATCH; + if (fnmatch_internal(pat, p-pat, str, s-str, flags)) + return __FNM_NOMATCH; + if (!c) return 0; + str = s+1; + pat = p+inc; + } else if (flags & __FNM_LEADING_DIR) { + for (s=str; *s; s++) { + if (*s != '/') continue; + if (!fnmatch_internal(pat, -1, str, s-str, flags)) + return 0; + } + } + return fnmatch_internal(pat, -1, str, -1, flags); +} diff --git a/src/static_libs/fnmatch/fnmatch.h b/src/static_libs/fnmatch/fnmatch.h new file mode 100644 index 0000000000..074661388b --- /dev/null +++ b/src/static_libs/fnmatch/fnmatch.h @@ -0,0 +1,28 @@ +/* + * LICENSE: MIT, see COPYRIGHT file in the directory + */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __FNM_PATHNAME 0x1 +#define __FNM_NOESCAPE 0x2 +#define __FNM_PERIOD 0x4 +#define __FNM_LEADING_DIR 0x8 +#define __FNM_CASEFOLD 0x10 +#define __FNM_FILE_NAME __FNM_PATHNAME + +#define __FNM_NOMATCH 1 +#define __FNM_NOSYS (-1) + +int __fnmatch(const char *, const char *, int); + +#ifdef __cplusplus +} +#endif + +#endif