|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1985-2011 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Glenn Fowler <gsf@research.att.com> *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* Phong Vo <kpv@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#pragma prototyped
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* regcomp() regex_t cache
|
|
Packit Service |
a8c26c |
* at&t research
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <ast.h>
|
|
Packit Service |
a8c26c |
#include <regex.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define CACHE 8 /* default # cached re's */
|
|
Packit Service |
a8c26c |
#define ROUND 64 /* pattern buffer size round */
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef unsigned long Key_t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct Cache_s
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
char* pattern;
|
|
Packit Service |
a8c26c |
regex_t re;
|
|
Packit Service |
a8c26c |
unsigned long serial;
|
|
Packit Service |
a8c26c |
regflags_t reflags;
|
|
Packit Service |
a8c26c |
int keep;
|
|
Packit Service |
a8c26c |
int size;
|
|
Packit Service |
a8c26c |
} Cache_t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct State_s
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
unsigned int size;
|
|
Packit Service |
a8c26c |
unsigned long serial;
|
|
Packit Service |
a8c26c |
char* locale;
|
|
Packit Service |
a8c26c |
Cache_t** cache;
|
|
Packit Service |
a8c26c |
} State_t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static State_t matchstate;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* flush the cache
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static void
|
|
Packit Service |
a8c26c |
flushcache(void)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int i;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = matchstate.size; i--;)
|
|
Packit Service |
a8c26c |
if (matchstate.cache[i] && matchstate.cache[i]->keep)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
matchstate.cache[i]->keep = 0;
|
|
Packit Service |
a8c26c |
regfree(&matchstate.cache[i]->re);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* return regcomp() compiled re for pattern and reflags
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
regex_t*
|
|
Packit Service |
a8c26c |
regcache(const char* pattern, regflags_t reflags, int* status)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register Cache_t* cp;
|
|
Packit Service |
a8c26c |
register int i;
|
|
Packit Service |
a8c26c |
char* s;
|
|
Packit Service |
a8c26c |
int empty;
|
|
Packit Service |
a8c26c |
int unused;
|
|
Packit Service |
a8c26c |
int old;
|
|
Packit Service |
a8c26c |
Key_t key;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* 0 pattern flushes the cache and reflags>0 extends cache
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!pattern)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
flushcache();
|
|
Packit Service |
a8c26c |
i = 0;
|
|
Packit Service |
a8c26c |
if (reflags > matchstate.size)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (matchstate.cache = newof(matchstate.cache, Cache_t*, reflags, 0))
|
|
Packit Service |
a8c26c |
matchstate.size = reflags;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
matchstate.size = 0;
|
|
Packit Service |
a8c26c |
i = 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (status)
|
|
Packit Service |
a8c26c |
*status = i;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (!matchstate.cache)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (!(matchstate.cache = newof(0, Cache_t*, CACHE, 0)))
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
matchstate.size = CACHE;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* flush the cache if the locale changed
|
|
Packit Service |
a8c26c |
* the ast setlocale() intercept maintains
|
|
Packit Service |
a8c26c |
* persistent setlocale() return values
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if ((s = setlocale(LC_CTYPE, NiL)) != matchstate.locale)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
matchstate.locale = s;
|
|
Packit Service |
a8c26c |
flushcache();
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* check if the pattern is in the cache
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = 0; i < sizeof(key) && pattern[i]; i++)
|
|
Packit Service |
a8c26c |
((char*)&key)[i] = pattern[i];
|
|
Packit Service |
a8c26c |
for (; i < sizeof(key); i++)
|
|
Packit Service |
a8c26c |
((char*)&key)[i] = 0;
|
|
Packit Service |
a8c26c |
empty = unused = -1;
|
|
Packit Service |
a8c26c |
old = 0;
|
|
Packit Service |
a8c26c |
for (i = matchstate.size; i--;)
|
|
Packit Service |
a8c26c |
if (!matchstate.cache[i])
|
|
Packit Service |
a8c26c |
empty = i;
|
|
Packit Service |
a8c26c |
else if (!matchstate.cache[i]->keep)
|
|
Packit Service |
a8c26c |
unused = i;
|
|
Packit Service |
a8c26c |
else if (*(Key_t*)matchstate.cache[i]->pattern == key && !strcmp(matchstate.cache[i]->pattern, pattern) && matchstate.cache[i]->reflags == reflags)
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
else if (!matchstate.cache[old] || matchstate.cache[old]->serial > matchstate.cache[i]->serial)
|
|
Packit Service |
a8c26c |
old = i;
|
|
Packit Service |
a8c26c |
if (i < 0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (unused < 0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (empty < 0)
|
|
Packit Service |
a8c26c |
unused = old;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
unused = empty;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (!(cp = matchstate.cache[unused]) && !(cp = matchstate.cache[unused] = newof(0, Cache_t, 1, 0)))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (status)
|
|
Packit Service |
a8c26c |
*status = REG_ESPACE;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (cp->keep)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
cp->keep = 0;
|
|
Packit Service |
a8c26c |
regfree(&cp->re);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if ((i = strlen(pattern) + 1) > cp->size)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
cp->size = roundof(i, ROUND);
|
|
Packit Service |
a8c26c |
if (!(cp->pattern = newof(cp->pattern, char, cp->size, 0)))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (status)
|
|
Packit Service |
a8c26c |
*status = REG_ESPACE;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
strcpy(cp->pattern, pattern);
|
|
Packit Service |
a8c26c |
while (++i < sizeof(Key_t))
|
|
Packit Service |
a8c26c |
cp->pattern[i] = 0;
|
|
Packit Service |
a8c26c |
pattern = (const char*)cp->pattern;
|
|
Packit Service |
a8c26c |
if (i = regcomp(&cp->re, pattern, reflags))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (status)
|
|
Packit Service |
a8c26c |
*status = i;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
cp->keep = 1;
|
|
Packit Service |
a8c26c |
cp->reflags = reflags;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
cp = matchstate.cache[i];
|
|
Packit Service |
a8c26c |
cp->serial = ++matchstate.serial;
|
|
Packit Service |
a8c26c |
if (status)
|
|
Packit Service |
a8c26c |
*status = 0;
|
|
Packit Service |
a8c26c |
return &cp->re;
|
|
Packit Service |
a8c26c |
}
|