624 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			624 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// _MATCH.CPP
 | 
						|
//
 | 
						|
//  Source file for ArchiveLib 1.0
 | 
						|
//
 | 
						|
//  Copyright (c) Greenleaf Software, Inc. 1994
 | 
						|
//  All Rights Reserved
 | 
						|
//
 | 
						|
// CONTENTS
 | 
						|
//
 | 
						|
//  is_pattern()
 | 
						|
//  is_valid_pattern()
 | 
						|
//  matche()
 | 
						|
//  matche_after_star()
 | 
						|
//  match()
 | 
						|
//  main()  (For testing, w/conditional compile)
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  Some nice code written by J. Kercheval, in the public domain.
 | 
						|
//  This code provides us with the pattern matching functions used 
 | 
						|
//  by the ALName functions.  It all seems to work without any trouble
 | 
						|
//  at all.
 | 
						|
//
 | 
						|
//  I tried to change this file as little as possible.  I modified the
 | 
						|
//  name of the file, and removed BOOLEAN, TRUE, and FALSE from the
 | 
						|
//  header file.  Other than that, it is just as I found it.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//  May 22, 1994  1.0A  : First release
 | 
						|
//
 | 
						|
//
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#pragma hdrstop
 | 
						|
 | 
						|
/*
 | 
						|
 EPSHeader
 | 
						|
 | 
						|
   File: match.c
 | 
						|
   Author: J. Kercheval
 | 
						|
   Created: Sat, 01/05/1991  22:21:49
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
 EPSRevision History
 | 
						|
 | 
						|
   J. Kercheval  Wed, 02/20/1991  22:29:01  Released to Public Domain
 | 
						|
   J. Kercheval  Fri, 02/22/1991  15:29:01  fix '\' bugs (two :( of them)
 | 
						|
   J. Kercheval  Sun, 03/10/1991  19:31:29  add error return to matche()
 | 
						|
   J. Kercheval  Sun, 03/10/1991  20:11:11  add is_valid_pattern code
 | 
						|
   J. Kercheval  Sun, 03/10/1991  20:37:11  beef up main()
 | 
						|
   J. Kercheval  Tue, 03/12/1991  22:25:10  Released as V1.1 to Public Domain
 | 
						|
   J. Kercheval  Thu, 03/14/1991  22:22:25  remove '\' for DOS file parsing
 | 
						|
   J. Kercheval  Mon, 05/13/1991  21:49:05  ifdef full match code
 | 
						|
   J. Kercheval  Mon, 01/06/1992  21:31:44  add match character defines
 | 
						|
*/
 | 
						|
 | 
						|
/*
 | 
						|
 * Wildcard Pattern Matching
 | 
						|
 */
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#include "_match.h"
 | 
						|
//
 | 
						|
// The next five lines used to be in the header file
 | 
						|
//
 | 
						|
#ifndef BOOLEAN
 | 
						|
#define BOOLEAN int
 | 
						|
#define TRUE 1
 | 
						|
#define FALSE 0
 | 
						|
#endif
 | 
						|
 | 
						|
/* character defines */
 | 
						|
#define MATCH_CHAR_SINGLE               '?'
 | 
						|
#define MATCH_CHAR_KLEENE_CLOSURE       '*'
 | 
						|
#define MATCH_CHAR_RANGE_OPEN           '['
 | 
						|
#define MATCH_CHAR_RANGE                '-'
 | 
						|
#define MATCH_CHAR_RANGE_CLOSE          ']'
 | 
						|
#define MATCH_CHAR_LITERAL              '\\'
 | 
						|
#define MATCH_CHAR_NULL                 '\0'
 | 
						|
#define MATCH_CHAR_CARAT_NEGATE         '^'
 | 
						|
#define MATCH_CHAR_EXCLAMATION_NEGATE   '!'
 | 
						|
 | 
						|
/* forward function prototypes */
 | 
						|
int matche_after_star( register const char *pattern, register char *text);
 | 
						|
int fast_match_after_star(register char *pattern, register char *text);
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * Return TRUE if PATTERN has any special wildcard characters
 | 
						|
 *
 | 
						|
 ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
BOOLEAN is_pattern( const char *p )
 | 
						|
{
 | 
						|
    while (*p) {
 | 
						|
        switch (*p++) {
 | 
						|
                case MATCH_CHAR_SINGLE:
 | 
						|
                case MATCH_CHAR_KLEENE_CLOSURE:
 | 
						|
                case MATCH_CHAR_RANGE_OPEN:
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
                case MATCH_CHAR_LITERAL:
 | 
						|
#endif
 | 
						|
 | 
						|
                return TRUE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * Return TRUE if PATTERN has is a well formed regular expression according
 | 
						|
 * to the above syntax
 | 
						|
 *
 | 
						|
 * error_type is a return code based on the type of pattern error.  Zero is
 | 
						|
 * returned in error_type if the pattern is a valid one.  error_type return
 | 
						|
 * values are as follows:
 | 
						|
 *
 | 
						|
 *   PATTERN_VALID - pattern is well formed
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
 *   PATTERN_ESC   - pattern has invalid escape ('\' at end of pattern)
 | 
						|
#endif
 | 
						|
 | 
						|
 *   PATTERN_RANGE - [..] construct has a no end range in a '-' pair (ie [a-])
 | 
						|
 *   PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
 | 
						|
 *   PATTERN_EMPTY - [..] construct is empty (ie [])
 | 
						|
 *
 | 
						|
 ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
BOOLEAN is_valid_pattern( const char *p, int *error_type )
 | 
						|
{
 | 
						|
 | 
						|
    /* init error_type */
 | 
						|
    *error_type = PATTERN_VALID;
 | 
						|
 | 
						|
    /* loop through pattern to EOS */
 | 
						|
    while (*p) {
 | 
						|
 | 
						|
        /* determine pattern type */
 | 
						|
        switch (*p) {
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
                /* check literal escape, it cannot be at end of pattern */
 | 
						|
            case MATCH_CHAR_LITERAL:
 | 
						|
                if (!*++p) {
 | 
						|
                    *error_type = PATTERN_ESC;
 | 
						|
                    return FALSE;
 | 
						|
                }
 | 
						|
                p++;
 | 
						|
                break;
 | 
						|
#endif
 | 
						|
 | 
						|
                /* the [..] construct must be well formed */
 | 
						|
            case MATCH_CHAR_RANGE_OPEN:
 | 
						|
                p++;
 | 
						|
 | 
						|
                /* if the next character is ']' then bad pattern */
 | 
						|
                if (*p == MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
                    *error_type = PATTERN_EMPTY;
 | 
						|
                    return FALSE;
 | 
						|
                }
 | 
						|
 | 
						|
                /* if end of pattern here then bad pattern */
 | 
						|
                if (!*p) {
 | 
						|
                    *error_type = PATTERN_CLOSE;
 | 
						|
                    return FALSE;
 | 
						|
                }
 | 
						|
 | 
						|
                /* loop to end of [..] construct */
 | 
						|
                while (*p != MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
 | 
						|
                    /* check for literal escape */
 | 
						|
                    if (*p == MATCH_CHAR_LITERAL) {
 | 
						|
                        p++;
 | 
						|
 | 
						|
                        /* if end of pattern here then bad pattern */
 | 
						|
                        if (!*p++) {
 | 
						|
                            *error_type = PATTERN_ESC;
 | 
						|
                            return FALSE;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                        p++;
 | 
						|
 | 
						|
                    /* if end of pattern here then bad pattern */
 | 
						|
                    if (!*p) {
 | 
						|
                        *error_type = PATTERN_CLOSE;
 | 
						|
                        return FALSE;
 | 
						|
                    }
 | 
						|
 | 
						|
                    /* if this a range */
 | 
						|
                    if (*p == MATCH_CHAR_RANGE) {
 | 
						|
 | 
						|
                        /* we must have an end of range */
 | 
						|
                        if (!*++p || *p == MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
                            *error_type = PATTERN_RANGE;
 | 
						|
                            return FALSE;
 | 
						|
                        }
 | 
						|
                        else {
 | 
						|
 | 
						|
                            /* check for literal escape */
 | 
						|
                            if (*p == MATCH_CHAR_LITERAL)
 | 
						|
                                p++;
 | 
						|
 | 
						|
                            /* if end of pattern here then bad pattern */
 | 
						|
                            if (!*p++) {
 | 
						|
                                *error_type = PATTERN_ESC;
 | 
						|
                                return FALSE;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                break;
 | 
						|
 | 
						|
                /* all other characters are valid pattern elements */
 | 
						|
            case MATCH_CHAR_KLEENE_CLOSURE:
 | 
						|
            case MATCH_CHAR_SINGLE:
 | 
						|
            default:            /* "normal" character */
 | 
						|
                p++;
 | 
						|
                break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * Match the pattern PATTERN against the string TEXT;
 | 
						|
 *
 | 
						|
 * returns MATCH_VALID if pattern matches, or an errorcode as follows
 | 
						|
 * otherwise:
 | 
						|
 *
 | 
						|
 *           MATCH_PATTERN  - bad pattern
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
 *           MATCH_LITERAL  - match failure on literal mismatch
 | 
						|
#endif
 | 
						|
 | 
						|
 *           MATCH_RANGE    - match failure on [..] construct
 | 
						|
 *           MATCH_ABORT    - premature end of text string
 | 
						|
 *           MATCH_END      - premature end of pattern string
 | 
						|
 *           MATCH_VALID    - valid match
 | 
						|
 *
 | 
						|
 *
 | 
						|
 * A match means the entire string TEXT is used up in matching.
 | 
						|
 *
 | 
						|
 * In the pattern string:
 | 
						|
 *      `*' matches any sequence of characters (zero or more)
 | 
						|
 *      `?' matches any character
 | 
						|
 *      [SET] matches any character in the specified set,
 | 
						|
 *      [!SET] or [^SET] matches any character not in the specified set.
 | 
						|
 *      \ is allowed within a set to escape a character like ']' or '-'
 | 
						|
 *
 | 
						|
 * A set is composed of characters or ranges; a range looks like character
 | 
						|
 * hyphen character (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the minimal set of
 | 
						|
 * characters allowed in the [..] pattern construct.  Other characters are
 | 
						|
 * allowed (ie. 8 bit characters) if your system will support them.
 | 
						|
 *
 | 
						|
 * To suppress the special syntactic significance of any of `[]*?!^-\', and
 | 
						|
 * match the character exactly, precede it with a `\'.
 | 
						|
 *
 | 
						|
 ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
int matche( const char *p, char *t)
 | 
						|
{
 | 
						|
    register char range_start, range_end;       /* start and end in range */
 | 
						|
 | 
						|
    BOOLEAN invert;             /* is this [..] or [!..] */
 | 
						|
    BOOLEAN member_match;       /* have I matched the [..] construct? */
 | 
						|
    BOOLEAN loop;               /* should I terminate? */
 | 
						|
 | 
						|
    for (; *p; p++, t++) {
 | 
						|
 | 
						|
        /* if this is the end of the text then this is the end of the match */
 | 
						|
        if (!*t) {
 | 
						|
            return (*p == MATCH_CHAR_KLEENE_CLOSURE &&
 | 
						|
                    *++p == MATCH_CHAR_NULL) ?
 | 
						|
                MATCH_VALID : MATCH_ABORT;
 | 
						|
        }
 | 
						|
 | 
						|
        /* determine and react to pattern type */
 | 
						|
        switch (*p) {
 | 
						|
 | 
						|
                /* single any character match */
 | 
						|
            case MATCH_CHAR_SINGLE:
 | 
						|
                break;
 | 
						|
 | 
						|
                /* multiple any character match */
 | 
						|
            case MATCH_CHAR_KLEENE_CLOSURE:
 | 
						|
                return matche_after_star(p, t);
 | 
						|
 | 
						|
                /* [..] construct, single member/exclusion character match */
 | 
						|
            case MATCH_CHAR_RANGE_OPEN:{
 | 
						|
 | 
						|
                    /* move to beginning of range */
 | 
						|
                    p++;
 | 
						|
 | 
						|
                    /* check if this is a member match or exclusion match */
 | 
						|
                    invert = FALSE;
 | 
						|
                    if (*p == MATCH_CHAR_EXCLAMATION_NEGATE ||
 | 
						|
                        *p == MATCH_CHAR_CARAT_NEGATE) {
 | 
						|
                        invert = TRUE;
 | 
						|
                        p++;
 | 
						|
                    }
 | 
						|
 | 
						|
                    /* if closing bracket here or at range start then we have
 | 
						|
                     * a malformed pattern */
 | 
						|
                    if (*p == MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
                        return MATCH_PATTERN;
 | 
						|
                    }
 | 
						|
 | 
						|
                    member_match = FALSE;
 | 
						|
                    loop = TRUE;
 | 
						|
 | 
						|
                    while (loop) {
 | 
						|
 | 
						|
                        /* if end of construct then loop is done */
 | 
						|
                        if (*p == MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
                            loop = FALSE;
 | 
						|
                            continue;
 | 
						|
                        }
 | 
						|
 | 
						|
                        /* matching a '!', '^', '-', '\' or a ']' */
 | 
						|
                        if (*p == MATCH_CHAR_LITERAL) {
 | 
						|
                            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 == MATCH_CHAR_RANGE) {
 | 
						|
 | 
						|
                            /* get the range end */
 | 
						|
                            range_end = *++p;
 | 
						|
 | 
						|
                            /* if end of pattern or construct then bad
 | 
						|
                             * pattern */
 | 
						|
                            if (range_end == MATCH_CHAR_NULL ||
 | 
						|
                                range_end == MATCH_CHAR_RANGE_CLOSE)
 | 
						|
                                return MATCH_PATTERN;
 | 
						|
 | 
						|
                            /* special character range end */
 | 
						|
                            if (range_end == MATCH_CHAR_LITERAL) {
 | 
						|
                                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 != MATCH_CHAR_RANGE_CLOSE) {
 | 
						|
 | 
						|
                            /* bad pattern (Missing MATCH_CHAR_RANGE_CLOSE) */
 | 
						|
                            if (!*p)
 | 
						|
                                return MATCH_PATTERN;
 | 
						|
 | 
						|
                            /* skip exact match */
 | 
						|
                            if (*p == MATCH_CHAR_LITERAL) {
 | 
						|
                                p++;
 | 
						|
 | 
						|
                                /* if end of text then we have a bad pattern */
 | 
						|
                                if (!*p)
 | 
						|
                                    return MATCH_PATTERN;
 | 
						|
                            }
 | 
						|
 | 
						|
                            /* move to next pattern char */
 | 
						|
                            p++;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
                /* next character is quoted and must match exactly */
 | 
						|
            case MATCH_CHAR_LITERAL:
 | 
						|
 | 
						|
                /* 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;
 | 
						|
#endif
 | 
						|
 | 
						|
                /* 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * recursively call matche() with final segment of PATTERN and of TEXT.
 | 
						|
 *
 | 
						|
 ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
int matche_after_star( register const char *p, register char *t)
 | 
						|
{
 | 
						|
    register int match = 0;
 | 
						|
    register nextp;
 | 
						|
 | 
						|
    /* pass over existing ? and * in pattern */
 | 
						|
    while (*p == MATCH_CHAR_SINGLE ||
 | 
						|
           *p == MATCH_CHAR_KLEENE_CLOSURE) {
 | 
						|
 | 
						|
        /* take one char for each ? and + */
 | 
						|
        if (*p == MATCH_CHAR_SINGLE) {
 | 
						|
 | 
						|
            /* 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;
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
    if (nextp == MATCH_CHAR_LITERAL) {
 | 
						|
        nextp = p[1];
 | 
						|
 | 
						|
        /* if end of text then we have a bad pattern */
 | 
						|
        if (!nextp)
 | 
						|
            return MATCH_PATTERN;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    /* 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_CHAR_RANGE_OPEN) {
 | 
						|
            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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*----------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * match() is a shell to matche() to return only BOOLEAN values.
 | 
						|
 *
 | 
						|
 ---------------------------------------------------------------------------*/
 | 
						|
 | 
						|
BOOLEAN match( char *p, char *t)
 | 
						|
{
 | 
						|
    int error_type;
 | 
						|
 | 
						|
    error_type = matche(p, t);
 | 
						|
    return (error_type == MATCH_VALID) ? TRUE : FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#ifdef TEST
 | 
						|
 | 
						|
/*
 | 
						|
    * This test main expects as first arg the pattern and as second arg
 | 
						|
    * the match string.  Output is yaeh or nay on match.  If nay on
 | 
						|
    * match then the error code is parsed and written.
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
int main(int argc, char *argv[])
 | 
						|
{
 | 
						|
    int error;
 | 
						|
    int is_valid_error;
 | 
						|
 | 
						|
    if (argc != 3) {
 | 
						|
        printf("Usage:  MATCH Pattern Text\n");
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        printf("Pattern: %s\n", argv[1]);
 | 
						|
        printf("Text   : %s\n", argv[2]);
 | 
						|
 | 
						|
        if ( !is_pattern(argv[1])) {
 | 
						|
            printf("    First Argument Is Not A Pattern\n");
 | 
						|
        }
 | 
						|
        else {
 | 
						|
 | 
						|
#ifdef FILE_MATCH
 | 
						|
            match(argv[1], argv[2]) ? printf("TRUE") : printf("FALSE");
 | 
						|
#endif
 | 
						|
 | 
						|
            error = matche(argv[1], argv[2]);
 | 
						|
            is_valid_pattern(argv[1], &is_valid_error);
 | 
						|
 | 
						|
            switch (error) {
 | 
						|
                case MATCH_VALID:
 | 
						|
                    printf("    Match Successful");
 | 
						|
                    if (is_valid_error != PATTERN_VALID)
 | 
						|
                        printf(" -- is_valid_pattern() is complaining\n");
 | 
						|
                    else
 | 
						|
                        printf("\n");
 | 
						|
                    break;
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
                case MATCH_LITERAL:
 | 
						|
                    printf("    Match Failed on Literal\n");
 | 
						|
                    break;
 | 
						|
#endif
 | 
						|
 | 
						|
                case MATCH_RANGE:
 | 
						|
                    printf("    Match Failed on [..]\n");
 | 
						|
                    break;
 | 
						|
                case MATCH_ABORT:
 | 
						|
                    printf("    Match Failed on Early Text Termination\n");
 | 
						|
                    break;
 | 
						|
                case MATCH_END:
 | 
						|
                    printf("    Match Failed on Early Pattern Termination\n");
 | 
						|
                    break;
 | 
						|
                case MATCH_PATTERN:
 | 
						|
                    switch (is_valid_error) {
 | 
						|
                        case PATTERN_VALID:
 | 
						|
                            printf("    Internal Disagreement On Pattern\n");
 | 
						|
                            break;
 | 
						|
 | 
						|
#ifndef FILE_MATCH
 | 
						|
                        case PATTERN_ESC:
 | 
						|
                            printf("    Literal Escape at End of Pattern\n");
 | 
						|
                            break;
 | 
						|
#endif
 | 
						|
 | 
						|
                        case PATTERN_RANGE:
 | 
						|
                            printf("    No End of Range in [..] Construct\n");
 | 
						|
                            break;
 | 
						|
                        case PATTERN_CLOSE:
 | 
						|
                            printf("    [..] Construct is Open\n");
 | 
						|
                            break;
 | 
						|
                        case PATTERN_EMPTY:
 | 
						|
                            printf("    [..] Construct is Empty\n");
 | 
						|
                            break;
 | 
						|
                        default:
 | 
						|
                            printf("    Internal Error in is_valid_pattern()\n");
 | 
						|
                    }
 | 
						|
                    break;
 | 
						|
                default:
 | 
						|
                    printf("    Internal Error in matche()\n");
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    return (0);
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |