gecko-dev/lib/xp/xp_regexp.c

307 строки
8.0 KiB
C
Исходник Обычный вид История

1999-04-28 02:05:39 +04:00
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* *
*
*
* shexp.c: shell-like wildcard match routines
*
* See shexp.h for public documentation.
*
* Rob McCool
*
*/
#include "xp_regexp.h"
#include "plstr.h"
#include "prmem.h"
/* ----------------------------- shexp_valid ------------------------------ */
PRIVATE int
1999-07-31 03:59:53 +04:00
_valid_subexp(char *expr, char stop)
1999-04-28 02:05:39 +04:00
{
register int x,y,t;
int nsc,np,tld;
x=0;nsc=0;tld=0;
1999-07-31 03:59:53 +04:00
while(expr[x] && (expr[x] != stop)) {
switch(expr[x]) {
1999-04-28 02:05:39 +04:00
case '~':
if(tld) return INVALID_SXP;
else ++tld;
case '*':
case '?':
case '^':
case '$':
++nsc;
break;
case '[':
++nsc;
1999-07-31 03:59:53 +04:00
if((!expr[++x]) || (expr[x] == ']'))
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
1999-07-31 03:59:53 +04:00
for(++x;expr[x] && (expr[x] != ']');++x)
if(expr[x] == '\\')
if(!expr[++x])
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
1999-07-31 03:59:53 +04:00
if(!expr[x])
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
break;
case '(':
++nsc;np = 0;
while(1) {
1999-07-31 03:59:53 +04:00
if(expr[++x] == ')')
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
1999-07-31 03:59:53 +04:00
for(y=x;(expr[y]) && (expr[y] != '|') && (expr[y] != ')');++y)
if(expr[y] == '\\')
if(!expr[++y])
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
1999-07-31 03:59:53 +04:00
if(!expr[y])
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
1999-07-31 03:59:53 +04:00
if(expr[y] == '|')
1999-04-28 02:05:39 +04:00
++np;
1999-07-31 03:59:53 +04:00
t = _valid_subexp(&expr[x],expr[y]);
1999-04-28 02:05:39 +04:00
if(t == INVALID_SXP)
return INVALID_SXP;
x+=t;
1999-07-31 03:59:53 +04:00
if(expr[x] == ')') {
1999-04-28 02:05:39 +04:00
if(!np)
return INVALID_SXP;
break;
}
}
break;
case ')':
case ']':
return INVALID_SXP;
case '\\':
1999-07-31 03:59:53 +04:00
if(!expr[++x])
1999-04-28 02:05:39 +04:00
return INVALID_SXP;
default:
break;
}
++x;
}
if((!stop) && (!nsc))
return NON_SXP;
1999-07-31 03:59:53 +04:00
return ((expr[x] == stop) ? x : INVALID_SXP);
1999-04-28 02:05:39 +04:00
}
PUBLIC int
1999-07-31 03:59:53 +04:00
XP_RegExpValid(char *expr)
1999-04-28 02:05:39 +04:00
{
int x;
1999-07-31 03:59:53 +04:00
x = _valid_subexp(expr, '\0');
1999-04-28 02:05:39 +04:00
return (x < 0 ? x : VALID_SXP);
}
/* ----------------------------- shexp_match ----------------------------- */
#define MATCH 0
#define NOMATCH 1
#define ABORTED -1
1999-07-31 03:59:53 +04:00
PRIVATE int _shexp_match(char *str, char *expr, PRBool case_insensitive);
1999-04-28 02:05:39 +04:00
PRIVATE int
1999-07-31 03:59:53 +04:00
_handle_union(char *str, char *expr, PRBool case_insensitive)
1999-04-28 02:05:39 +04:00
{
1999-07-31 03:59:53 +04:00
char *e2 = (char *) PR_Malloc(sizeof(char)*strlen(expr));
1999-04-28 02:05:39 +04:00
register int t,p2,p1 = 1;
int cp;
while(1) {
1999-07-31 03:59:53 +04:00
for(cp=1;expr[cp] != ')';cp++)
if(expr[cp] == '\\')
1999-04-28 02:05:39 +04:00
++cp;
1999-07-31 03:59:53 +04:00
for(p2 = 0;(expr[p1] != '|') && (p1 != cp);p1++,p2++) {
if(expr[p1] == '\\')
e2[p2++] = expr[p1++];
e2[p2] = expr[p1];
1999-04-28 02:05:39 +04:00
}
1999-07-31 03:59:53 +04:00
for (t=cp+1; ((e2[p2] = expr[t]) != 0); ++t,++p2) {}
1999-04-28 02:05:39 +04:00
if(_shexp_match(str,e2, case_insensitive) == MATCH) {
PR_Free(e2);
return MATCH;
}
if(p1 == cp) {
PR_Free(e2);
return NOMATCH;
}
else ++p1;
}
}
PRIVATE int
1999-07-31 03:59:53 +04:00
_shexp_match(char *str, char *expr, PRBool case_insensitive)
1999-04-28 02:05:39 +04:00
{
register int x,y;
int ret,neg;
ret = 0;
1999-07-31 03:59:53 +04:00
for(x=0,y=0;expr[y];++y,++x) {
if((!str[x]) && (expr[y] != '(') && (expr[y] != '$') && (expr[y] != '*'))
1999-04-28 02:05:39 +04:00
ret = ABORTED;
else {
1999-07-31 03:59:53 +04:00
switch(expr[y]) {
1999-04-28 02:05:39 +04:00
case '$':
if( (str[x]) )
ret = NOMATCH;
else
--x; /* we don't want loop to increment x */
break;
case '*':
1999-07-31 03:59:53 +04:00
while(expr[++y] == '*'){}
if(!expr[y])
1999-04-28 02:05:39 +04:00
return MATCH;
while(str[x]) {
1999-07-31 03:59:53 +04:00
switch(_shexp_match(&str[x++],&expr[y], case_insensitive)) {
1999-04-28 02:05:39 +04:00
case NOMATCH:
continue;
case ABORTED:
ret = ABORTED;
break;
default:
return MATCH;
}
break;
}
1999-07-31 03:59:53 +04:00
if((expr[y] == '$') && (expr[y+1] == '\0') && (!str[x]))
1999-04-28 02:05:39 +04:00
return MATCH;
else
ret = ABORTED;
break;
case '[':
1999-07-31 03:59:53 +04:00
neg = ((expr[++y] == '^') && (expr[y+1] != ']'));
1999-04-28 02:05:39 +04:00
if (neg)
++y;
1999-07-31 03:59:53 +04:00
if ((isalnum(expr[y])) && (expr[y+1] == '-') &&
(isalnum(expr[y+2])) && (expr[y+3] == ']'))
1999-04-28 02:05:39 +04:00
{
1999-07-31 03:59:53 +04:00
int start = expr[y], end = expr[y+2];
1999-04-28 02:05:39 +04:00
/* Droolproofing for pinheads not included */
if(neg ^ ((str[x] < start) || (str[x] > end))) {
ret = NOMATCH;
break;
}
y+=3;
}
else {
int matched;
1999-07-31 03:59:53 +04:00
for (matched=0;expr[y] != ']';y++)
matched |= (str[x] == expr[y]);
1999-04-28 02:05:39 +04:00
if (neg ^ (!matched))
ret = NOMATCH;
}
break;
case '(':
1999-07-31 03:59:53 +04:00
return _handle_union(&str[x],&expr[y], case_insensitive);
1999-04-28 02:05:39 +04:00
break;
case '?':
break;
case '\\':
++y;
default:
if(case_insensitive)
{
1999-07-31 03:59:53 +04:00
if(toupper(str[x]) != toupper(expr[y]))
1999-04-28 02:05:39 +04:00
ret = NOMATCH;
}
else
{
1999-07-31 03:59:53 +04:00
if(str[x] != expr[y])
1999-04-28 02:05:39 +04:00
ret = NOMATCH;
}
break;
}
}
if(ret)
break;
}
return (ret ? ret : (str[x] ? NOMATCH : MATCH));
}
PUBLIC int
1999-07-31 03:59:53 +04:00
XP_RegExpMatch(char *str, char *xp, PRBool case_insensitive) {
1999-04-28 02:05:39 +04:00
register int x;
1999-07-31 03:59:53 +04:00
char *expr = PL_strdup(xp);
1999-04-28 02:05:39 +04:00
1999-07-31 03:59:53 +04:00
if(!expr)
1999-04-28 02:05:39 +04:00
return 1;
1999-07-31 03:59:53 +04:00
for(x=strlen(expr)-1;x;--x) {
if((expr[x] == '~') && (expr[x-1] != '\\')) {
expr[x] = '\0';
if(_shexp_match(str,&expr[++x], case_insensitive) == MATCH)
1999-04-28 02:05:39 +04:00
goto punt;
break;
}
}
1999-07-31 03:59:53 +04:00
if(_shexp_match(str,expr, FALSE) == MATCH) {
PR_Free(expr);
1999-04-28 02:05:39 +04:00
return 0;
}
punt:
1999-07-31 03:59:53 +04:00
PR_Free(expr);
1999-04-28 02:05:39 +04:00
return 1;
}
/* ------------------------------ shexp_cmp ------------------------------- */
1999-06-16 05:01:09 +04:00
#if 0
1999-04-28 02:05:39 +04:00
PUBLIC int
1999-07-31 03:59:53 +04:00
XP_RegExpSearch(char *str, char *expr)
1999-04-28 02:05:39 +04:00
{
1999-07-31 03:59:53 +04:00
switch(XP_RegExpValid(expr))
1999-04-28 02:05:39 +04:00
{
case INVALID_SXP:
return -1;
case NON_SXP:
1999-07-31 03:59:53 +04:00
return (strcmp(expr,str) ? 1 : 0);
1999-04-28 02:05:39 +04:00
default:
1999-07-31 03:59:53 +04:00
return XP_RegExpMatch(str, expr, FALSE);
1999-04-28 02:05:39 +04:00
}
}
PUBLIC int
1999-07-31 03:59:53 +04:00
XP_RegExpCaseSearch(char *str, char *expr)
1999-04-28 02:05:39 +04:00
{
1999-07-31 03:59:53 +04:00
switch(XP_RegExpValid(expr))
1999-04-28 02:05:39 +04:00
{
case INVALID_SXP:
return -1;
case NON_SXP:
1999-07-31 03:59:53 +04:00
return (strcmp(expr,str) ? 1 : 0);
1999-04-28 02:05:39 +04:00
default:
1999-07-31 03:59:53 +04:00
return XP_RegExpMatch(str, expr, TRUE);
1999-04-28 02:05:39 +04:00
}
}
1999-06-16 05:01:09 +04:00
#endif
1999-04-28 02:05:39 +04:00