Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

360 lines
9.4 KiB
C

static char sccsid[] = "@(#)65 1.6.1.5 src/bos/usr/ccs/lib/libc/__fnmatch_C.c, libcpat, bos411, 9428A410j 3/30/94 14:54:39";
/*
* COMPONENT_NAME: (LIBCPAT) Standard C Library Pattern Functions
*
* FUNCTIONS: __fnmatch_C
*
* ORIGINS: 27
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
*
* (C) COPYRIGHT International Business Machines Corp. 1991, 1992
* All Rights Reserved
* Licensed Materials - Property of IBM
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#define _ILS_MACROS
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/localedef.h>
#include <fnmatch.h>
#include "patlocal.h"
static int bracket( /* compare [] expression to character */
_LC_collate_objhdl_t,
const char *,
char **,
uchar_t,
int);
/************************************************************************/
/* __fnmatch_C() - Single byte method for Filename Matching */
/* - works for C locale */
/* */
/* hdl - ptr to __lc_collate structure */
/* ppat - ptr to filename pattern */
/* string - ptr to beginning of filename */
/* pstr - ptr to current position within filename */
/* flags - fnmatch() flags, see <fnmatch.h> */
/************************************************************************/
int
__fnmatch_C(_LC_collate_objhdl_t hdl, const char *ppat, const char *string,
const char *pstr, int flags)
{
int stat; /* recursive __fnmatch_C() return status */
/*
* Loop through pattern, matching string characters with pattern
* Return success when end-of-pattern and end-of-string reached simultaneously
* Return no match if pattern/string mismatch
*/
while (*ppat != '\0')
{
switch (*ppat)
{
/*
* <backslash> does not quote the next character if FNM_NOESCAPE flag is set
* Return no match if pattern ends with quoting <backslash>
*/
case '\\':
if ((flags & FNM_NOESCAPE) == 0)
if (*++ppat == '\0')
return (FNM_NOMATCH);
/*
* Ordinary character in pattern matches itself in string
* Continue if pattern character matches string character
* Return no match if pattern character does not match string character
*/
default:
ordinary:
if (*ppat++ == *pstr++)
break;
else
return (FNM_NOMATCH);
/*
* <asterisk> matches zero or more string characters
* Cannot match <slash> if FNM_PATHNAME is set
* Cannot match leading <period> if FNM_PERIOD is set
* Consecutive <asterisk> are redundant
*
* Return success if remaining pattern matches remaining string
* Otherwise advance to the next string character and try again
* Return no match if string exhausted and more pattern remains
*/
case '*':
while (*++ppat == '*')
;
if (*ppat == '\0')
{
if ((flags & FNM_PATHNAME) != 0 && strchr(pstr, '/') != NULL)
return (FNM_NOMATCH);
if (*pstr == '.' && (flags & FNM_PERIOD) != 0)
if (pstr == string || (pstr[-1] == '/' && (flags & FNM_PATHNAME) != 0))
return (FNM_NOMATCH);
return (0);
}
while (*pstr != '\0')
{
stat = __fnmatch_C(hdl, ppat, string, pstr,
flags);
if (stat != FNM_NOMATCH)
return (stat);
if (*pstr == '/')
{
if ((flags & FNM_PATHNAME) != 0)
return (FNM_NOMATCH);
}
else if (*pstr == '.' && (flags & FNM_PERIOD) != 0)
if (pstr == string || (pstr[-1] =='/' && (flags & FNM_PATHNAME) != 0))
return (FNM_NOMATCH);
pstr++;
}
return (FNM_NOMATCH);
/*
* <question-mark> matches any single character
* Cannot match <slash> if FNM_PATHNAME is set
* Cannot match leading <period> if FNM_PERIOD is set
*
* Return no match if string is exhausted
* Otherwise continue with next pattern and string character
*/
case '?':
if (*pstr == '/')
{
if ((flags & FNM_PATHNAME) != 0)
return (FNM_NOMATCH);
}
else if (*pstr == '.' && (flags & FNM_PERIOD) != 0)
if (pstr == string || (pstr[-1] == '/' && (flags & FNM_PATHNAME) != 0))
return (FNM_NOMATCH);
if (*pstr != '\0')
{
pstr++;
ppat++;
break;
}
else
return(FNM_NOMATCH);
/*
* <left-bracket> begins a [bracket expression] which matches single collating element
* [bracket expression] cannot match <slash> if FNM_PATHNAME is set
* [bracket expression] cannot match leading <period> if FNM_PERIOD is set
*/
case '[':
if (*pstr == '/')
{
if ((flags & FNM_PATHNAME) != 0)
return (FNM_NOMATCH);
}
else if (*pstr == '.' && (flags & FNM_PERIOD) != 0)
if (pstr == string || (pstr[-1] == '/' && (flags & FNM_PATHNAME) != 0))
return (FNM_NOMATCH);
/*
* Compare next filename character to [bracket expression]
* > 0 no match
* = 0 match found
* < 0 error, treat [] as individual characters
*/
stat = bracket(hdl, ppat+1, &ppat, *pstr, flags);
if (stat == 0)
pstr++;
else if (stat > 0)
return (FNM_NOMATCH);
else
goto ordinary;
break;
}
}
/*
* <NUL> following end-of-pattern
* Return success if string is also at <NUL>
* Return no match if string not at <NUL>
*/
if (*pstr == '\0')
return (0);
else
return (FNM_NOMATCH);
}
/************************************************************************/
/* bracket() - Determine if [bracket] matches filename character */
/* */
/* pdhl - ptr to __lc_collate structure */
/* ppat - ptr to position of '[' in pattern */
/* pend - ptr to character after trailing ']' in pattern */
/* fc - process code of next filename character */
/* flags - fnmatch() flags, see <fnmatch.h> */
/************************************************************************/
static int
bracket(_LC_collate_objhdl_t hdl, const char *ppat, char **pend, uchar_t fc,
int flags)
{
int dash; /* <hyphen> found for a-z range expr */
int found; /* match found flag */
uchar_t min_fc; /* minimum range value */
uchar_t max_fc; /* maximum range value */
int neg; /* nonmatching [] expression */
char *pb; /* ptr to [bracket] pattern */
char *pclass; /* class[] ptr */
char *pi; /* ptr to international [] expression */
uchar_t prev_min_fc; /* low end of range expr */
char type; /* international [] type =:. */
char class[CLASS_SIZE+1]; /* character class with <NUL> */
/*
* Leading <exclamation-mark> designates nonmatching [bracket expression]
*/
pb = ppat;
neg = 0;
if (*pb == '!')
{
pb++;
neg++;
}
/*
* Loop through each [] character, comparing to file code of string character
*/
dash = 0;
found = 0;
prev_min_fc = 0;
min_fc = 0;
max_fc = 0;
while (*pb != '\0')
{
/*
* Preserve minimum file code of previous character for range expression
* Decode next [] element
*/
if (dash == 0)
prev_min_fc = min_fc;
switch (*pb)
{
/*
* Ordinary character
*/
default:
ordinary:
if (*pb == fc)
found = 1;
min_fc = *pb++;
max_fc = min_fc;
break;
/*
* <hyphen> deliniates a range expression unless it is first character of []
* or it immediately follows another <hyphen> and is therefore an end point
*/
case '-':
if (dash == 0 && !((neg == 0 && pb == ppat) || (neg != 0 && pb == ppat + 1)))
{
dash = '-';
pb++;
continue;
}
goto ordinary;
/*
* Final <right-bracket> so return status based upon whether match was found
* Return character after final ] if match is found
* Ordinary character if first character of [barcket expression]
*/
case ']':
if ((neg == 0 && pb > ppat) || (neg != 0 && pb > ppat + 1))
{
*pend = ++pb;
if (dash && dash == fc)
found = 1;
if ((found ^ neg) != 0)
return (0);
else
return (FNM_NOMATCH);
}
goto ordinary;
/*
* Embedded <slash> not allowed if FNM_PATHNAME is set
*/
case '/':
if ((flags & FNM_PATHNAME) != 0)
return (-1);
goto ordinary;
/*
* <left-bracket> initiates one of the following internationalization
* character expressions
* [: :] character class
* [= =] equivalence character class
* [. .] collation symbol
*
* it is treated as itself if not followed by appropriate special character
* it is treated as itself if any error is encountered
*/
case '[':
pi = pb + 2;
if ((type = pb[1]) == ':')
{
pclass = class;
while (1)
{
if (*pi == '\0')
return (-1);
if (*pi == ':' && pi[1] == ']')
break;
if (pclass >= &class[CLASS_SIZE])
return (-1);
*pclass++ = *pi++;
}
if (pclass == class)
return (-1);
*pclass = '\0';
if (is_wctype((wchar_t)fc, get_wctype(class)) != 0)
found = 1;
min_fc = 0;
pb = pi + 2;
break;
}
/*
* equivalence character class or collation symbol
* treat as ordinary if not [= =]
*/
else if (type == '=' || type == '.')
{
if (*pi == '\0' || pi[1] != type || pi[2] != ']')
return (-1);
if ((uchar_t)*pi == fc)
found = 1;
min_fc = (uchar_t)*pi;
max_fc = min_fc;
pb = pi + 3;
break;
}
else
goto ordinary;
} /* end of switch */
/*
* Return if range expression is illegal
* Check for the completion of a range expression and determine
* whether filename character falls between end points
*/
if (dash != 0)
{
dash = 0;
if (prev_min_fc == 0 || min_fc == 0 || prev_min_fc > max_fc)
return (-1);
if (fc >= prev_min_fc && fc <= max_fc)
found = 1;
min_fc = 0;
}
} /* end of while */
/*
* Return < 0 since <NUL> was found
*/
return (-1);
}