Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/regex/regcache.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
/*
25
* regcomp() regex_t cache
26
* at&t research
27
*/
28
29
#include <ast.h>
30
#include <regex.h>
31
32
#define CACHE 8 /* default # cached re's */
33
#define ROUND 64 /* pattern buffer size round */
34
35
typedef unsigned long Key_t;
36
37
typedef struct Cache_s
38
{
39
char* pattern;
40
regex_t re;
41
unsigned long serial;
42
regflags_t reflags;
43
int keep;
44
int size;
45
} Cache_t;
46
47
typedef struct State_s
48
{
49
unsigned int size;
50
unsigned long serial;
51
char* locale;
52
Cache_t** cache;
53
} State_t;
54
55
static State_t matchstate;
56
57
/*
58
* flush the cache
59
*/
60
61
static void
62
flushcache(void)
63
{
64
register int i;
65
66
for (i = matchstate.size; i--;)
67
if (matchstate.cache[i] && matchstate.cache[i]->keep)
68
{
69
matchstate.cache[i]->keep = 0;
70
regfree(&matchstate.cache[i]->re);
71
}
72
}
73
74
/*
75
* return regcomp() compiled re for pattern and reflags
76
*/
77
78
regex_t*
79
regcache(const char* pattern, regflags_t reflags, int* status)
80
{
81
register Cache_t* cp;
82
register int i;
83
char* s;
84
int empty;
85
int unused;
86
int old;
87
Key_t key;
88
89
/*
90
* 0 pattern flushes the cache and reflags>0 extends cache
91
*/
92
93
if (!pattern)
94
{
95
flushcache();
96
i = 0;
97
if (reflags > matchstate.size)
98
{
99
if (matchstate.cache = newof(matchstate.cache, Cache_t*, reflags, 0))
100
matchstate.size = reflags;
101
else
102
{
103
matchstate.size = 0;
104
i = 1;
105
}
106
}
107
if (status)
108
*status = i;
109
return 0;
110
}
111
if (!matchstate.cache)
112
{
113
if (!(matchstate.cache = newof(0, Cache_t*, CACHE, 0)))
114
return 0;
115
matchstate.size = CACHE;
116
}
117
118
/*
119
* flush the cache if the locale changed
120
* the ast setlocale() intercept maintains
121
* persistent setlocale() return values
122
*/
123
124
if ((s = setlocale(LC_CTYPE, NiL)) != matchstate.locale)
125
{
126
matchstate.locale = s;
127
flushcache();
128
}
129
130
/*
131
* check if the pattern is in the cache
132
*/
133
134
for (i = 0; i < sizeof(key) && pattern[i]; i++)
135
((char*)&key)[i] = pattern[i];
136
for (; i < sizeof(key); i++)
137
((char*)&key)[i] = 0;
138
empty = unused = -1;
139
old = 0;
140
for (i = matchstate.size; i--;)
141
if (!matchstate.cache[i])
142
empty = i;
143
else if (!matchstate.cache[i]->keep)
144
unused = i;
145
else if (*(Key_t*)matchstate.cache[i]->pattern == key && !strcmp(matchstate.cache[i]->pattern, pattern) && matchstate.cache[i]->reflags == reflags)
146
break;
147
else if (!matchstate.cache[old] || matchstate.cache[old]->serial > matchstate.cache[i]->serial)
148
old = i;
149
if (i < 0)
150
{
151
if (unused < 0)
152
{
153
if (empty < 0)
154
unused = old;
155
else
156
unused = empty;
157
}
158
if (!(cp = matchstate.cache[unused]) && !(cp = matchstate.cache[unused] = newof(0, Cache_t, 1, 0)))
159
{
160
if (status)
161
*status = REG_ESPACE;
162
return 0;
163
}
164
if (cp->keep)
165
{
166
cp->keep = 0;
167
regfree(&cp->re);
168
}
169
if ((i = strlen(pattern) + 1) > cp->size)
170
{
171
cp->size = roundof(i, ROUND);
172
if (!(cp->pattern = newof(cp->pattern, char, cp->size, 0)))
173
{
174
if (status)
175
*status = REG_ESPACE;
176
return 0;
177
}
178
}
179
strcpy(cp->pattern, pattern);
180
while (++i < sizeof(Key_t))
181
cp->pattern[i] = 0;
182
pattern = (const char*)cp->pattern;
183
if (i = regcomp(&cp->re, pattern, reflags))
184
{
185
if (status)
186
*status = i;
187
return 0;
188
}
189
cp->keep = 1;
190
cp->reflags = reflags;
191
}
192
else
193
cp = matchstate.cache[i];
194
cp->serial = ++matchstate.serial;
195
if (status)
196
*status = 0;
197
return &cp->re;
198
}
199
200