/* match.c -
 *
 *	String matching operations.
 *
 *     ********************************************************************* 
 *     * Copyright (C) 1985, 1990 Regents of the University of California. * 
 *     * Permission to use, copy, modify, and distribute this              * 
 *     * software and its documentation for any purpose and without        * 
 *     * fee is hereby granted, provided that the above copyright          * 
 *     * notice appear in all copies.  The University of California        * 
 *     * makes no representations about the suitability of this            * 
 *     * software for any purpose.  It is provided "as is" without         * 
 *     * express or implied warranty.  Export of this software outside     * 
 *     * of the United States of America may require an export license.    * 
 *     *********************************************************************
 */

#ifndef lint
static char rcsid[] = "$Header: /ufs/repository/magic/utils/match.c,v 1.3 2006/02/08 03:48:40 fang Exp $";
#endif  /* not lint */

#include <stdio.h>
#include "misc/magic.h"
#include "textio/textio.h"

/*
 * ----------------------------------------------------------------------------
 *
 * Match --
 *
 * 	Sees if two strings match, using csh-like pattern matching.
 *
 * Results:
 *	TRUE is returned if the two strings match, FALSE is returned
 *	if they don't.  The first string, pattern, can contain the
 *	special characters *, ?, \, and [], which are matched as by
 *	the csh.
 *
 * Side effects:
 *	None.
 *
 * ----------------------------------------------------------------------------
 */

int
Match(pattern, string)
    register char *pattern;	/* csh-like pattern. */
    register char *string;	/* String to check for match against pattern.*/
{
    char c2;

    while (TRUE)
    {
	/* See if we're at the end of both pattern and string.  If
	 * so, we succeeded.  If we're at the end of pattern, but not
	 * of string, we failed.
	 */
	
	if (*pattern == 0)
	{
	    if (*string == 0) return TRUE;
	    else return FALSE;
	}
	if ((*string == 0) && (*pattern != '*')) return FALSE;

	/* Check for a "*" as the next pattern character.  It matches
	 * any substring.  We handle this by calling ourselves
	 * recursively for each postfix of string, until either we
	 * match or we reach the end of the string.
	 */
	
	if (*pattern == '*')
	{
	    pattern += 1;
	    if (*pattern == 0) return TRUE;
	    while (*string != 0)
	    {
		if (Match(pattern, string)) return TRUE;
		string += 1;
	    }
	    return FALSE;
	}
    
	/* Check for a "?" as the next pattern character.  It matches
	 * any single character.
	 */

	if (*pattern == '?') goto thisCharOK;

	/* Check for a "[" as the next pattern character.  It is followed
	 * by a list of characters that are acceptable, or by a range
	 * (two characters separated by "-").
	 */
	
	if (*pattern == '[')
	{
	    pattern += 1;
	    while (TRUE)
	    {
		if ((*pattern == ']') || (*pattern == 0)) return FALSE;
		if (*pattern == *string) break;
		if (pattern[1] == '-')
		{
		    c2 = pattern[2];
		    if (c2 == 0) return FALSE;
		    if ((*pattern <= *string) && (c2 >= *string)) break;
		    if ((*pattern >= *string) && (c2 <= *string)) break;
		    pattern += 2;
		}
		pattern += 1;
	    }
	    while ((*pattern != ']') && (*pattern != 0)) pattern += 1;
	    goto thisCharOK;
	}
    
	/* If the next pattern character is '\', just strip off the '\'
	 * so we do exact matching on the character that follows.
	 */
	
	if (*pattern == '\\')
	{
	    pattern += 1;
	    if (*pattern == 0) return FALSE;
	}

	/* There's no special character.  Just make sure that the next
	 * characters of each string match.
	 */
	
	if (*pattern != *string) return FALSE;

	thisCharOK: pattern += 1;
	string += 1;
    }
}
