mirror of
				https://github.com/osmarks/ngircd.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	- neues Modul "match" begonnen.
This commit is contained in:
		
							
								
								
									
										254
									
								
								src/ngircd/match.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								src/ngircd/match.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,254 @@ | |||||||
|  | /* | ||||||
|  |  * ngIRCd -- The Next Generation IRC Daemon | ||||||
|  |  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) | ||||||
|  |  * | ||||||
|  |  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen | ||||||
|  |  * der GNU General Public License (GPL), wie von der Free Software Foundation | ||||||
|  |  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 | ||||||
|  |  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. | ||||||
|  |  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste | ||||||
|  |  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. | ||||||
|  |  * | ||||||
|  |  * $Id: match.c,v 1.1 2002/06/26 15:42:58 alex Exp $ | ||||||
|  |  * | ||||||
|  |  * match.c: Wildcard Pattern Matching | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #include "portab.h" | ||||||
|  |  | ||||||
|  | #include "imp.h" | ||||||
|  | #include <assert.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "exp.h" | ||||||
|  | #include "match.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Die Pattern-Matching-Funkionen [Matche(), Matche_After_Star()] basieren | ||||||
|  |  * auf Versionen von J. Kercheval. Die Version 1.1 wurde am 12.03.1991 als | ||||||
|  |  * "public domain" freigegeben: | ||||||
|  |  * <http://www.snippets.org/snippets/portable/MATCH+C.php3> | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | LOCAL INT Matche PARAMS(( REGISTER CHAR *p, REGISTER CHAR *t )); | ||||||
|  | LOCAL INT Matche_After_Star PARAMS(( REGISTER CHAR *p, REGISTER CHAR *t )); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define MATCH_PATTERN	6	/* bad pattern */ | ||||||
|  | #define MATCH_LITERAL	5	/* match failure on literal match */ | ||||||
|  | #define MATCH_RANGE	4	/* match failure on [..] construct */ | ||||||
|  | #define MATCH_ABORT	3	/* premature end of text string */ | ||||||
|  | #define MATCH_END	2	/* premature end of pattern string */ | ||||||
|  | #define MATCH_VALID	1	/* valid match */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GLOBAL BOOLEAN | ||||||
|  | Match( CHAR *Pattern, CHAR *String ) | ||||||
|  | { | ||||||
|  | 	/* Pattern mit String vergleichen */ | ||||||
|  | 	if( Matche( Pattern, String ) == MATCH_VALID ) return TRUE; | ||||||
|  | 	else return FALSE; | ||||||
|  | } /* Match */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | LOCAL INT | ||||||
|  | Matche( REGISTER CHAR *p, REGISTER CHAR *t ) | ||||||
|  | { | ||||||
|  | 	REGISTER CHAR range_start, range_end; | ||||||
|  | 	BOOLEAN invert; | ||||||
|  | 	BOOLEAN member_match; | ||||||
|  | 	BOOLEAN loop; | ||||||
|  |  | ||||||
|  | 	for( ; *p; p++, t++ ) | ||||||
|  | 	{ | ||||||
|  | 		/* if this is the end of the text then this is the end of the match */ | ||||||
|  | 		if( ! *t ) | ||||||
|  | 		{ | ||||||
|  | 			return ( *p == '*' && *++p == '\0' ) ? MATCH_VALID : MATCH_ABORT; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* determine and react to pattern type */ | ||||||
|  | 		switch( *p ) | ||||||
|  | 		{ | ||||||
|  | 			case '?':	/* single any character match */ | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			case '*':	/* multiple any character match */ | ||||||
|  | 				return Matche_After_Star( p, t ); | ||||||
|  |  | ||||||
|  | 			case '[':	/* [..] construct, single member/exclusion character match */ | ||||||
|  | 				/* move to beginning of range */ | ||||||
|  | 				p++; | ||||||
|  |  | ||||||
|  | 				/* check if this is a member match or exclusion match */ | ||||||
|  | 				invert = FALSE; | ||||||
|  | 				if( *p == '!' || *p == '^' ) | ||||||
|  | 				{ | ||||||
|  | 					invert = TRUE; | ||||||
|  | 					p++; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				/* if closing bracket here or at range start then we have a malformed pattern */ | ||||||
|  | 				if ( *p == ']' ) return MATCH_PATTERN; | ||||||
|  |  | ||||||
|  | 				member_match = FALSE; | ||||||
|  | 				loop = TRUE; | ||||||
|  |  | ||||||
|  | 				while( loop ) | ||||||
|  | 				{ | ||||||
|  | 					/* if end of construct then loop is done */ | ||||||
|  | 					if( *p == ']' ) | ||||||
|  | 					{ | ||||||
|  | 						loop = FALSE; | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					/* matching a '!', '^', '-', '\' or a ']' */ | ||||||
|  | 					if( *p == '\\' ) range_start = range_end = *++p; | ||||||
|  | 					else  range_start = range_end = *p; | ||||||
|  |  | ||||||
|  | 					/* if end of pattern then bad pattern (Missing ']') */ | ||||||
|  | 					if( ! *p ) return MATCH_PATTERN; | ||||||
|  |  | ||||||
|  | 					/* check for range bar */ | ||||||
|  | 					if( *++p == '-' ) | ||||||
|  | 					{ | ||||||
|  | 						/* get the range end */ | ||||||
|  | 						range_end = *++p; | ||||||
|  |  | ||||||
|  | 						/* if end of pattern or construct then bad pattern */ | ||||||
|  | 						if( range_end == '\0' || range_end == ']' ) return MATCH_PATTERN; | ||||||
|  |  | ||||||
|  | 						/* special character range end */ | ||||||
|  | 						if( range_end == '\\' ) | ||||||
|  | 						{ | ||||||
|  | 							range_end = *++p; | ||||||
|  |  | ||||||
|  | 							/* if end of text then we have a bad pattern */ | ||||||
|  | 							if ( ! range_end ) return MATCH_PATTERN; | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						/* move just beyond this range */ | ||||||
|  | 						p++; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					/* if the text character is in range then match found. make sure the range | ||||||
|  | 					 * letters have the proper relationship to one another before comparison */ | ||||||
|  | 					if( range_start < range_end ) | ||||||
|  | 					{ | ||||||
|  | 						if( *t >= range_start && *t <= range_end ) | ||||||
|  | 						{ | ||||||
|  | 							member_match = TRUE; | ||||||
|  | 							loop = FALSE; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					else | ||||||
|  | 					{ | ||||||
|  | 						if( *t >= range_end && *t <= range_start ) | ||||||
|  | 						{ | ||||||
|  | 							member_match = TRUE; | ||||||
|  | 							loop = FALSE; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				/* if there was a match in an exclusion set then no match */ | ||||||
|  | 				/* if there was no match in a member set then no match */ | ||||||
|  | 				if(( invert && member_match ) || ! ( invert || member_match )) return MATCH_RANGE; | ||||||
|  |  | ||||||
|  | 				/* if this is not an exclusion then skip the rest of the [...] | ||||||
|  | 				 * construct that already matched. */ | ||||||
|  | 				if( member_match ) | ||||||
|  | 				{ | ||||||
|  | 					while( *p != ']' ) | ||||||
|  | 					{ | ||||||
|  | 						/* bad pattern (Missing ']') */ | ||||||
|  | 						if( ! *p ) return MATCH_PATTERN; | ||||||
|  |  | ||||||
|  | 						/* skip exact match */ | ||||||
|  | 						if( *p == '\\' ) | ||||||
|  | 						{ | ||||||
|  | 							p++; | ||||||
|  |  | ||||||
|  | 							/* if end of text then we have a bad pattern */ | ||||||
|  | 							if( ! *p ) return MATCH_PATTERN; | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						/* move to next pattern char */ | ||||||
|  | 						p++; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			case '\\':	/* next character is quoted and must match exactly */ | ||||||
|  | 				/* move pattern pointer to quoted char and fall through */ | ||||||
|  | 				p++; | ||||||
|  |  | ||||||
|  | 				/* if end of text then we have a bad pattern */ | ||||||
|  | 				if( ! *p ) return MATCH_PATTERN; | ||||||
|  |  | ||||||
|  | 				/* must match this character exactly */ | ||||||
|  | 			default: | ||||||
|  | 				if( *p != *t ) return MATCH_LITERAL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	/* if end of text not reached then the pattern fails */ | ||||||
|  |  | ||||||
|  | 	if( *t ) return MATCH_END; | ||||||
|  | 	else return MATCH_VALID; | ||||||
|  | } /* Matche */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | LOCAL INT | ||||||
|  | Matche_After_Star( REGISTER CHAR *p, REGISTER CHAR *t ) | ||||||
|  | { | ||||||
|  | 	REGISTER INT nextp, match = 0; | ||||||
|  |  | ||||||
|  | 	/* pass over existing ? and * in pattern */ | ||||||
|  | 	while( *p == '?' || *p == '*' ) | ||||||
|  | 	{ | ||||||
|  | 		/* take one char for each ? and + */ | ||||||
|  | 		if (*p == '?') | ||||||
|  | 		{ | ||||||
|  | 			/* if end of text then no match */ | ||||||
|  | 			if( ! *t++ ) return MATCH_ABORT; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* move to next char in pattern */ | ||||||
|  | 		p++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* if end of pattern we have matched regardless of text left */ | ||||||
|  | 	if( ! *p ) return MATCH_VALID; | ||||||
|  |  | ||||||
|  | 	/* get the next character to match which must be a literal or '[' */ | ||||||
|  | 	nextp = *p; | ||||||
|  | 	if( nextp == '\\' ) | ||||||
|  | 	{ | ||||||
|  | 		nextp = p[1]; | ||||||
|  |  | ||||||
|  | 		/* if end of text then we have a bad pattern */ | ||||||
|  | 		if( ! nextp ) return MATCH_PATTERN; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Continue until we run out of text or definite result seen */ | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		/* a precondition for matching is that the next character | ||||||
|  | 		 * in the pattern match the next character in the text or that | ||||||
|  | 		 * the next pattern char is the beginning of a range.  Increment | ||||||
|  | 		 * text pointer as we go here */ | ||||||
|  | 		if( nextp == *t || nextp == '[' ) match = Matche( p, t ); | ||||||
|  |  | ||||||
|  | 		/* if the end of text is reached then no match */ | ||||||
|  | 		if( ! *t++ ) match = MATCH_ABORT; | ||||||
|  | 	} while( match != MATCH_VALID && match != MATCH_ABORT && match != MATCH_PATTERN ); | ||||||
|  |  | ||||||
|  | 	/* return result */ | ||||||
|  | 	return match; | ||||||
|  | } /* Matche_After_Star */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -eof- */ | ||||||
							
								
								
									
										28
									
								
								src/ngircd/match.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/ngircd/match.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | /* | ||||||
|  |  * ngIRCd -- The Next Generation IRC Daemon | ||||||
|  |  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) | ||||||
|  |  * | ||||||
|  |  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen | ||||||
|  |  * der GNU General Public License (GPL), wie von der Free Software Foundation | ||||||
|  |  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 | ||||||
|  |  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. | ||||||
|  |  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste | ||||||
|  |  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. | ||||||
|  |  * | ||||||
|  |  * $Id: match.h,v 1.1 2002/06/26 15:42:58 alex Exp $ | ||||||
|  |  * | ||||||
|  |  * match.h: Wildcard Pattern Matching (Header) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifndef __match_h__ | ||||||
|  | #define __match_h__ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GLOBAL BOOLEAN Match PARAMS(( CHAR *Pattern, CHAR *String )); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -eof- */ | ||||||
		Reference in New Issue
	
	Block a user
	 Alexander Barton
					Alexander Barton