1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/*
* The original was spagetti. I have replaced Michael's code with some of
* my own which is a thousand times more readable and can also handle '%',
* which substitutes anything except a space. This should enable people
* to position things better based on argument. I have also added '?', which
* substitutes to any single character. And of course it still handles '*'.
* this should be more efficient than the previous version too.
*
* Thus this whole file becomes:
*
* Written By Troy Rollo
*
* Copyright(c) 1992
*
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
*/
#if 0
static char rcsid[] = "@(#)$Id: reg.c,v 1.6 1994/07/02 02:32:13 mrg Exp $";
#endif
#include "irc.h"
#include "ircaux.h"
#include "output.h"
static int total_explicit;
/*
* The following #define is here because we *know* its behaviour.
* The behaviour of toupper tends to be undefined when it's given
* a non lower case letter.
* All the systems supported by IRCII should be ASCII
*/
#define mkupper(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : c)
#ifdef __STDC__
int match(char *pattern, char *string)
#else
int match(pattern, string)
char *pattern,
*string;
#endif
{
char type;
#if 0
if ((!pattern || !string) && !x_debug)
{
yell("match: pattern or string is NULL!");
return 0;
}
#endif
while (*string && *pattern && *pattern != '*' && *pattern != '%')
{
if (*pattern == '\\' && *(pattern + 1))
{
if (!*++pattern || !(mkupper(*pattern) ==
mkupper(*string)))
return 0;
else
pattern++, string++, total_explicit++;
}
if (*pattern == '?')
pattern++, string++;
else if (mkupper(*pattern) == mkupper(*string))
pattern++, string++, total_explicit++;
else
break;
}
if (*pattern == '*' || *pattern == '%')
{
type = (*pattern++);
while (*string)
{
if (match(pattern, string))
return 1;
else if (type == '*' || *string != ' ')
string++;
else
break;
}
}
if (!*string && !*pattern)
return 1;
return 0;
}
/*
* This version of wild_match returns 1 + the count of characters
* explicitly matched if a match occurs. That way we can look for
* the best match in a list
*/
/* \\[ and \\] handling done by Jeremy Nelson
* EPIC will not use the new pattern matcher currently used by
* ircii because i am not convinced that it is 1) better * and
* 2) i think the \\[ \\] stuff is important.
*/
#ifdef __STDC__
int wild_match (char *pattern, char *str)
#else
int wild_match(pattern, str)
char *pattern,
*str;
#endif
{
char *ptr;
char *ptr2 = pattern;
int nest = 0;
char my_buff[2048];
char *arg;
int best_total = 0;
total_explicit = 0;
/* Is there a \[ in the pattern to be expanded? */
/* This stuff here just reduces the \[ \] set into a series of
* one-simpler patterns and then recurses */
if ((ptr2 = strstr(pattern, "\\[")))
{
/* we will have to null this out, but not until weve used it */
char *placeholder = ptr2;
ptr = ptr2;
/* yes. whats the character after it? (first time
through is a trivial case) */
do
{
switch (ptr[1])
{
/* step over it and add to nest */
case '[' : ptr2 = ptr + 2 ;
nest++;
break;
/* step over it and remove nest */
case ']' : ptr2 = ptr + 2;
nest--;
break;
}
}
/* Repeat while there are more backslashes to look at and
* we have are still in nested \[ \] sets
*/
while ((nest) && (ptr = index(ptr2, '\\')));
/* right now, we know ptr points to a \] or to null */
/* remember that && short circuits and that ptr will
not be set to null if (nest) is zero... */
if (ptr)
{
/* null out and step over the original \[ */
*placeholder = '\0';
placeholder += 2;
/* null out and step over the matching \] */
*ptr = '\0';
ptr +=2;
/* grab words ("" sets or space words) one at a time
* and attempt to match all of them. The best value
* matched is the one used.
*/
while ((arg = new_next_arg(placeholder, &placeholder)))
{
int tmpval;
strcpy(my_buff, pattern);
strcat(my_buff, arg);
strcat(my_buff, ptr);
/* the total_explicit we return is whichever
* pattern has the highest total_explicit */
if ((tmpval = wild_match(my_buff, str)))
{
if (tmpval > best_total)
best_total = tmpval;
}
}
return best_total; /* end of expansion section */
}
/* Possibly an unmatched \[ \] set */
else
{
total_explicit = 0;
if (match(pattern, str))
return total_explicit + 1;
else
{
#if 0
yell("Unmatched \\[ !");
#endif
return 0;
}
}
}
/* trivial case (no expansion) when weve expanded all the way out */
else if (match(pattern, str))
return total_explicit+1;
else
return 0;
}
|