Initial commit of code released on 2002-07-15
This commit is contained in:
316
Sources/match.c
Normal file
316
Sources/match.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/* @(#)$Id: match.c,v 1.10 1999/03/06 19:15:34 seks Exp $ */
|
||||
|
||||
/* Undernet Channel Service (X)
|
||||
* Copyright (C) 1995-2002 Robin Thellend
|
||||
*
|
||||
* 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* The author can be contact by email at <csfeedback@robin.pfft.net>
|
||||
*
|
||||
* Please note that this software is unsupported and mostly
|
||||
* obsolete. It was replaced by GNUworld/CMaster. See
|
||||
* http://gnuworld.sourceforge.net/ for more information.
|
||||
*/
|
||||
|
||||
#include "h.h"
|
||||
#include <regex.h>
|
||||
|
||||
static int matchX(char *, char *);
|
||||
|
||||
int mycasecmp(char *s1, char *s2)
|
||||
{
|
||||
register unsigned char *c1 = (unsigned char *)s1, *c2 = (unsigned char *)s2;
|
||||
register int d;
|
||||
|
||||
while (!(d = (toupper(*c1) - toupper(*c2))) && *c1)
|
||||
{
|
||||
c1++;
|
||||
c2++;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
char *strcasestr(register char *s1, char *s2)
|
||||
{
|
||||
register char *a, *b;
|
||||
|
||||
while (*s1)
|
||||
{
|
||||
a = s1;
|
||||
b = s2;
|
||||
while (*b && *a && toupper(*a) == toupper(*b))
|
||||
{
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
if (!*b)
|
||||
return s1;
|
||||
s1++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* xmatch() returns 1 if both pat1 and pat2 can *possibly*
|
||||
* match the same string. It returns 0 otherwise.
|
||||
*/
|
||||
int xmatch(char *pat1, char *pat2)
|
||||
{
|
||||
if (!strcmp(pat1, "*") || !strcmp(pat2, "*"))
|
||||
return 1;
|
||||
while (*pat1 && *pat2)
|
||||
{
|
||||
if (*pat1 == '*' && *pat2 == '*')
|
||||
return (matchX(pat1 + 1, pat2 + 1) || matchX(pat2 + 1, pat1 + 1));
|
||||
if (*pat1 == '*')
|
||||
return matchX(pat1 + 1, pat2);
|
||||
if (*pat2 == '*')
|
||||
return matchX(pat2 + 1, pat1);
|
||||
if (*pat1 == '?' || *pat2 == '?' || toupper(*pat1) == toupper(*pat2))
|
||||
{
|
||||
pat1++;
|
||||
pat2++;
|
||||
if ((!*pat1 && !strcmp(pat2, "*")) ||
|
||||
(!*pat2 && !strcmp(pat1, "*")))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (*pat1 || *pat2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int matchX(char *pat1, char *pat2)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (xmatch(pat1, pat2))
|
||||
return 1;
|
||||
}
|
||||
while (*pat2++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int match(register char *string, register char *mask)
|
||||
{
|
||||
char *stack[200][2] = {{NULL, NULL}};
|
||||
register char type = 0;
|
||||
register short quote, level = 0;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
quote = 0;
|
||||
switch (*mask)
|
||||
{
|
||||
case '*':
|
||||
type = '*';
|
||||
if (++level == 200)
|
||||
return 0;
|
||||
stack[level][0] = mask;
|
||||
stack[level][1] = string;
|
||||
while (*++mask == '*'); /* '*' eats any following '*' */
|
||||
break;
|
||||
case '\\':
|
||||
quote++;
|
||||
mask++;
|
||||
/* no break! */
|
||||
default:
|
||||
if (toupper(*string) == toupper(*mask) || (*mask == '?' && !quote))
|
||||
{
|
||||
mask++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (stack[level][0] == NULL && --level > 0);
|
||||
if (level <= 0)
|
||||
return 0;
|
||||
mask = stack[level][0];
|
||||
string = stack[level][1];
|
||||
level--;
|
||||
}
|
||||
string++;
|
||||
}
|
||||
}
|
||||
while (*mask == '*') /* Skip everything that can */
|
||||
mask++; /* match an empty string. */
|
||||
|
||||
return (*mask) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* compare() will return 1 if p1 and p2 can match the same
|
||||
* nick!user@host. p1 and p2 are nick!user@host masks.
|
||||
*/
|
||||
int compare(char *p1, char *p2)
|
||||
{
|
||||
char tmp1[200], tmp2[200];
|
||||
register char *s1 = tmp1, *s2 = tmp2;
|
||||
register int ip1, ip2, in_uh = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ip1 = ip2 = 1;
|
||||
|
||||
while (*p1 && *p1 != '!' && *p1 != '@')
|
||||
{
|
||||
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
|
||||
ip1 = 0;
|
||||
*(s1++) = *(p1++);
|
||||
}
|
||||
if (!in_uh && *p1 == '\0')
|
||||
in_uh = 1;
|
||||
|
||||
while (*p2 && *p2 != '!' && *p2 != '@')
|
||||
{
|
||||
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p2 == '*' || s2 != tmp2))
|
||||
ip2 = 0;
|
||||
*(s2++) = *(p2++);
|
||||
}
|
||||
|
||||
*s2 = *s1 = '\0';
|
||||
|
||||
if (*p1 != *p2)
|
||||
{
|
||||
if (*p1 == '!')
|
||||
{
|
||||
s1 = tmp1;
|
||||
if (*p1)
|
||||
p1++;
|
||||
while (*p1 && *p1 != '@')
|
||||
{
|
||||
if (ip1 && !isdigit(*p1) && *p1 != '.' && (*p1 != '*' || p1[1]) && (*p1 == '*' || s1 != tmp1))
|
||||
ip1 = 0;
|
||||
*(s1++) = *(p1++);
|
||||
}
|
||||
if (!in_uh && *p1 == '\0')
|
||||
in_uh = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
s2 = tmp2;
|
||||
if (*p2)
|
||||
p2++;
|
||||
while (*p2 && *p2 != '@')
|
||||
{
|
||||
if (ip2 && !isdigit(*p2) && *p2 != '.' && (*p2 != '*' || p2[1]) && (*p1 == '*' || s2 != tmp2))
|
||||
ip2 = 0;
|
||||
*(s2++) = *(p2++);
|
||||
}
|
||||
}
|
||||
*s2 = *s1 = '\0';
|
||||
}
|
||||
if ((in_uh && ip1 != ip2) || !xmatch(tmp1, tmp2))
|
||||
return 0;
|
||||
|
||||
if (*p1)
|
||||
p1++;
|
||||
if (*p2)
|
||||
p2++;
|
||||
|
||||
s1 = tmp1;
|
||||
s2 = tmp2;
|
||||
|
||||
}
|
||||
while (*p1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int key_match(char *s, char *tok[])
|
||||
{
|
||||
register int k;
|
||||
|
||||
for (k = 0; tok[k] != NULL; k++)
|
||||
{
|
||||
if (!strcasestr(s, tok[k]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void string_swap(char *buf, size_t size, char *orig, char *new)
|
||||
{
|
||||
char *ptr, *buf2;
|
||||
|
||||
buf2 = (char *)alloca(sizeof(char) * size);
|
||||
while ((ptr = strstr((buf), orig)))
|
||||
{
|
||||
*ptr = '\0';
|
||||
strncpy(buf2, buf, size - 1);
|
||||
strncat(buf2, new, size - strlen(buf) - 1);
|
||||
strncat(buf2, ptr + strlen(orig), size - strlen(buf) - strlen(new) - 1);
|
||||
strcpy(buf, buf2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* regex_cmp() (stolen from RCSD)
|
||||
* This function compares a regular expression (patern) with a string.
|
||||
* Return value: 1 if there is a match
|
||||
* 0 otherwise
|
||||
*
|
||||
* Note: if patern is NULL, the last patern that was passed to the
|
||||
* function is used.
|
||||
*/
|
||||
#define HAVE_REGEXEC
|
||||
int regex_cmp(char *patern, char *string)
|
||||
{
|
||||
#if defined(HAVE_REGEXEC)
|
||||
static regex_t preg;
|
||||
static int called_once = 0;
|
||||
register int cmpv = 0, execv;
|
||||
|
||||
if (patern != NULL)
|
||||
{
|
||||
if (called_once)
|
||||
regfree(&preg);
|
||||
cmpv = regcomp(&preg, patern, REG_EXTENDED | REG_ICASE | REG_NOSUB);
|
||||
}
|
||||
|
||||
called_once = 1;
|
||||
|
||||
if (cmpv == 0)
|
||||
execv = regexec(&preg, string, 0, NULL, 0);
|
||||
|
||||
return cmpv ? 0 : execv ? 0 : 1;
|
||||
|
||||
#elif defined(HAVE_RE_EXEC)
|
||||
register char *ptr;
|
||||
|
||||
ptr = re_comp(patern);
|
||||
return ptr ? 0 : re_exec(string);
|
||||
|
||||
#else
|
||||
#error neither re_exec() nor rexexec() :/
|
||||
#endif
|
||||
}
|
||||
#ifdef MATCHALONE
|
||||
void main(void)
|
||||
{
|
||||
char str1[80];
|
||||
char str2[80];
|
||||
puts("#1");
|
||||
gets(str1);
|
||||
puts("#2");
|
||||
gets(str2);
|
||||
printf("match: %d\n", match(str1, str2));
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user