File: reg.c

package info (click to toggle)
epic 3.004-10
  • links: PTS
  • area: main
  • in suites: slink
  • size: 5,180 kB
  • ctags: 3,207
  • sloc: ansic: 40,836; makefile: 526; sh: 121; perl: 17
file content (203 lines) | stat: -rw-r--r-- 4,754 bytes parent folder | download | duplicates (4)
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;
}