summaryrefslogtreecommitdiffstats
path: root/third-party/mmatch/mmatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'third-party/mmatch/mmatch.c')
-rw-r--r--third-party/mmatch/mmatch.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/third-party/mmatch/mmatch.c b/third-party/mmatch/mmatch.c
new file mode 100644
index 0000000..b68f1bf
--- /dev/null
+++ b/third-party/mmatch/mmatch.c
@@ -0,0 +1,309 @@
+/*
+ * IRC - Internet Relay Chat, common/match.c
+ * Copyright (C) 1990 Jarkko Oikarinen
+ *
+ * This program 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 1, or (at your option)
+ * any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: Match.cpp,v 1.2 2005/08/15 10:08:50 shroud23 Exp $
+ */
+
+#include <ctype.h>
+#include "mmatch.h"
+
+#define ToLower tolower
+
+/*
+ * mmatch()
+ *
+ * Written by Run (carlo@runaway.xs4all.nl), 25-10-96
+ *
+ *
+ * From: Carlo Wood <carlo@runaway.xs4all.nl>
+ * Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
+ * Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
+ * To: coder-com@mail.undernet.org (coder committee)
+ * Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
+ *
+ * We need a new function `mmatch(const char *old_mask, const char *new_mask)'
+ * which returns `true' likewise the current `match' (start with copying it),
+ * but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
+ * as follows: a '*' in `new_mask' does not match a '?' in `old_mask' and
+ * a '?' in `new_mask' does not match a '\?' in `old_mask'.
+ * And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
+ * And last but not least, '\?' and '\*' in `new_mask' now become one character.
+ */
+
+#if 0
+int mmatch(const char *old_mask, const char *new_mask)
+{
+ const char *m = old_mask;
+ const char *n = new_mask;
+ const char *ma = m;
+ const char *na = n;
+ int wild = 0;
+ int mq = 0, nq = 0;
+
+ while (1)
+ {
+ if (*m == '*')
+ {
+ while (*m == '*')
+ m++;
+ wild = 1;
+ ma = m;
+ na = n;
+ }
+
+ if (!*m)
+ {
+ if (!*n)
+ return 0;
+ for (m--; (m > old_mask) && (*m == '?'); m--)
+ ;
+ if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
+ return 0;
+ if (!wild)
+ return 1;
+ m = ma;
+
+ /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+ if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
+ ++na;
+
+ n = ++na;
+ }
+ else if (!*n)
+ {
+ while (*m == '*')
+ m++;
+ return (*m != 0);
+ }
+ if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+ {
+ m++;
+ mq = 1;
+ }
+ else
+ mq = 0;
+
+ /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+ if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
+ {
+ n++;
+ nq = 1;
+ }
+ else
+ nq = 0;
+
+/*
+ * This `if' has been changed compared to match() to do the following:
+ * Match when:
+ * old (m) new (n) boolean expression
+ * * any (*m == '*' && !mq) ||
+ * ? any except '*' (*m == '?' && !mq && (*n != '*' || nq)) ||
+ * any except * or ? same as m (!((*m == '*' || *m == '?') && !mq) &&
+ * ToLower(*m) == ToLower(*n) &&
+ * !((mq && !nq) || (!mq && nq)))
+ *
+ * Here `any' also includes \* and \? !
+ *
+ * After reworking the boolean expressions, we get:
+ * (Optimized to use boolean shortcircuits, with most frequently occuring
+ * cases upfront (which took 2 hours!)).
+ */
+ if ((*m == '*' && !mq) ||
+ ((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
+ (*m == '?' && !mq && (*n != '*' || nq)))
+ {
+ if (*m)
+ m++;
+ if (*n)
+ n++;
+ }
+ else
+ {
+ if (!wild)
+ return 1;
+ m = ma;
+
+ /* Added to `mmatch' : Because '\?' and '\*' now is one character: */
+ if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
+ ++na;
+
+ n = ++na;
+ }
+ }
+}
+#endif
+
+/*
+ * Compare if a given string (name) matches the given
+ * mask (which can contain wild cards: '*' - match any
+ * number of chars, '?' - match any single character.
+ *
+ * return 0, if match
+ * 1, if no match
+ */
+
+/*
+ * match
+ *
+ * Rewritten by Andrea Cocito (Nemesi), November 1998.
+ *
+ */
+
+/****************** Nemesi's match() ***************/
+
+int match(const char *mask, const char *str)
+{
+ const char *m = mask, *s = str;
+ char ch;
+ const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */
+
+ /* Process the "head" of the mask, if any */
+ while ((ch = *m++) && (ch != '*'))
+ switch (ch)
+ {
+ case '\\':
+ if (*m == '?' || *m == '*')
+ ch = *m++;
+ default:
+ if (ToLower(*s) != ToLower(ch))
+ return 1;
+ case '?':
+ if (!*s++)
+ return 1;
+ };
+ if (!ch)
+ return *s;
+
+ /* We got a star: quickly find if/where we match the next char */
+got_star:
+ bm = m; /* Next try rollback here */
+ while ((ch = *m++))
+ switch (ch)
+ {
+ case '?':
+ if (!*s++)
+ return 1;
+ case '*':
+ bm = m;
+ continue; /* while */
+ case '\\':
+ if (*m == '?' || *m == '*')
+ ch = *m++;
+ default:
+ goto break_while; /* C is structured ? */
+ };
+break_while:
+ if (!ch)
+ return 0; /* mask ends with '*', we got it */
+ ch = ToLower(ch);
+ if (!*s) /* String is already empty, don't continue */
+ return 1; /* This fixes the #quakenet access denied bug */
+ while (ToLower(*s++) != ch)
+ if (!*s)
+ return 1;
+ bs = s; /* Next try start from here */
+
+ /* Check the rest of the "chunk" */
+ while ((ch = *m++))
+ {
+ switch (ch)
+ {
+ case '*':
+ goto got_star;
+ case '\\':
+ if (*m == '?' || *m == '*')
+ ch = *m++;
+ default:
+ if (ToLower(*s) != ToLower(ch))
+ {
+ /* If we've run out of string, give up */
+ if (!*bs)
+ return 1;
+ m = bm;
+ s = bs;
+ goto got_star;
+ };
+ case '?':
+ if (!*s++)
+ return 1;
+ };
+ };
+ if (*s)
+ {
+ m = bm;
+ s = bs;
+ goto got_star;
+ };
+ return 0;
+}
+
+/*
+ * collapse()
+ * Collapse a pattern string into minimal components.
+ * This particular version is "in place", so that it changes the pattern
+ * which is to be reduced to a "minimal" size.
+ *
+ * (C) Carlo Wood - 6 Oct 1998
+ * Speedup rewrite by Andrea Cocito, December 1998.
+ * Note that this new optimized alghoritm can *only* work in place.
+ */
+
+#if 0
+char *collapse(char *pattern)
+{
+ int star = 0;
+ char *m = pattern;
+ char *b;
+
+ if (m)
+ {
+ do
+ {
+ if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
+ {
+ b = m;
+ do
+ {
+ if (*m == '*')
+ star = 1;
+ else
+ {
+ if (star && (*m != '?'))
+ {
+ *b++ = '*';
+ star = 0;
+ };
+ *b++ = *m;
+ if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+ *b++ = *++m;
+ };
+ }
+ while (*m++);
+ break;
+ }
+ else
+ {
+ if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+ m++;
+ };
+ }
+ while (*m++);
+ };
+ return pattern;
+}
+#endif