summaryrefslogtreecommitdiffstats
path: root/lib/glob/gm_loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/glob/gm_loop.c')
-rw-r--r--lib/glob/gm_loop.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/lib/glob/gm_loop.c b/lib/glob/gm_loop.c
new file mode 100644
index 0000000..ac516f8
--- /dev/null
+++ b/lib/glob/gm_loop.c
@@ -0,0 +1,208 @@
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#if EXTENDED_GLOB
+int
+EXTGLOB_PATTERN_P (pat)
+ const CHAR *pat;
+{
+ switch (pat[0])
+ {
+ case L('*'):
+ case L('+'):
+ case L('!'):
+ case L('@'):
+ case L('?'):
+ return (pat[1] == L('(')); /* ) */
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+#endif
+
+/* Return 1 of the first character of STRING could match the first
+ character of pattern PAT. Compiled to both single and wiide character
+ versions. FLAGS is a subset of strmatch flags; used to do case-insensitive
+ matching for now. */
+int
+MATCH_PATTERN_CHAR (pat, string, flags)
+ CHAR *pat, *string;
+ int flags;
+{
+ CHAR c;
+
+ if (*string == 0)
+ return (*pat == L('*')); /* XXX - allow only * to match empty string */
+
+ switch (c = *pat++)
+ {
+ default:
+ return (FOLD(*string) == FOLD(c));
+ case L('\\'):
+ return (FOLD(*string) == FOLD(*pat));
+ case L('?'):
+ return (*pat == L('(') ? 1 : (*string != L'\0'));
+ case L('*'):
+ return (1);
+ case L('+'):
+ case L('!'):
+ case L('@'):
+ return (*pat == L('(') ? 1 : (FOLD(*string) == FOLD(c)));
+ case L('['):
+ return (*string != L('\0'));
+ }
+}
+
+int
+MATCHLEN (pat, max)
+ CHAR *pat;
+ size_t max;
+{
+ CHAR c;
+ int matlen, bracklen, t, in_cclass, in_collsym, in_equiv;
+
+ if (*pat == 0)
+ return (0);
+
+ matlen = in_cclass = in_collsym = in_equiv = 0;
+ while (c = *pat++)
+ {
+ switch (c)
+ {
+ default:
+ matlen++;
+ break;
+ case L('\\'):
+ if (*pat == 0)
+ return ++matlen;
+ else
+ {
+ matlen++;
+ pat++;
+ }
+ break;
+ case L('?'):
+ if (*pat == LPAREN)
+ return (matlen = -1); /* XXX for now */
+ else
+ matlen++;
+ break;
+ case L('*'):
+ return (matlen = -1);
+ case L('+'):
+ case L('!'):
+ case L('@'):
+ if (*pat == LPAREN)
+ return (matlen = -1); /* XXX for now */
+ else
+ matlen++;
+ break;
+ case L('['):
+ /* scan for ending `]', skipping over embedded [:...:] */
+ bracklen = 1;
+ c = *pat++;
+ do
+ {
+ if (c == 0)
+ {
+ pat--; /* back up to NUL */
+ matlen += bracklen;
+ goto bad_bracket;
+ }
+ else if (c == L('\\'))
+ {
+ /* *pat == backslash-escaped character */
+ bracklen++;
+ /* If the backslash or backslash-escape ends the string,
+ bail. The ++pat skips over the backslash escape */
+ if (*pat == 0 || *++pat == 0)
+ {
+ matlen += bracklen;
+ goto bad_bracket;
+ }
+ }
+ else if (c == L('[') && *pat == L(':')) /* character class */
+ {
+ pat++;
+ bracklen++;
+ in_cclass = 1;
+ }
+ else if (in_cclass && c == L(':') && *pat == L(']'))
+ {
+ pat++;
+ bracklen++;
+ in_cclass = 0;
+ }
+ else if (c == L('[') && *pat == L('.')) /* collating symbol */
+ {
+ pat++;
+ bracklen++;
+ if (*pat == L(']')) /* right bracket can appear as collating symbol */
+ {
+ pat++;
+ bracklen++;
+ }
+ in_collsym = 1;
+ }
+ else if (in_collsym && c == L('.') && *pat == L(']'))
+ {
+ pat++;
+ bracklen++;
+ in_collsym = 0;
+ }
+ else if (c == L('[') && *pat == L('=')) /* equivalence class */
+ {
+ pat++;
+ bracklen++;
+ if (*pat == L(']')) /* right bracket can appear as equivalence class */
+ {
+ pat++;
+ bracklen++;
+ }
+ in_equiv = 1;
+ }
+ else if (in_equiv && c == L('=') && *pat == L(']'))
+ {
+ pat++;
+ bracklen++;
+ in_equiv = 0;
+ }
+ else
+ bracklen++;
+ }
+ while ((c = *pat++) != L(']'));
+ matlen++; /* bracket expression can only match one char */
+bad_bracket:
+ break;
+ }
+ }
+
+ return matlen;
+}
+
+#undef EXTGLOB_PATTERN_P
+#undef MATCH_PATTERN_CHAR
+#undef MATCHLEN
+#undef FOLD
+#undef L
+#undef LPAREN
+#undef RPAREN
+#undef INT
+#undef CHAR