1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
25 * regcomp() regex_t cache
32 #define CACHE 8 /* default # cached re's */
33 #define ROUND 64 /* pattern buffer size round */
35 typedef unsigned long Key_t
;
37 typedef struct Cache_s
47 typedef struct State_s
55 static State_t matchstate
;
66 for (i
= matchstate
.size
; i
--;)
67 if (matchstate
.cache
[i
] && matchstate
.cache
[i
]->keep
)
69 matchstate
.cache
[i
]->keep
= 0;
70 regfree(&matchstate
.cache
[i
]->re
);
75 * return regcomp() compiled re for pattern and reflags
79 regcache(const char* pattern
, regflags_t reflags
, int* status
)
90 * 0 pattern flushes the cache and reflags>0 extends cache
97 if (reflags
> matchstate
.size
)
99 if (matchstate
.cache
= newof(matchstate
.cache
, Cache_t
*, reflags
, 0))
100 matchstate
.size
= reflags
;
111 if (!matchstate
.cache
)
113 if (!(matchstate
.cache
= newof(0, Cache_t
*, CACHE
, 0)))
115 matchstate
.size
= CACHE
;
119 * flush the cache if the locale changed
120 * the ast setlocale() intercept maintains
121 * persistent setlocale() return values
124 if ((s
= setlocale(LC_CTYPE
, NiL
)) != matchstate
.locale
)
126 matchstate
.locale
= s
;
131 * check if the pattern is in the cache
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;
140 for (i
= matchstate
.size
; i
--;)
141 if (!matchstate
.cache
[i
])
143 else if (!matchstate
.cache
[i
]->keep
)
145 else if (*(Key_t
*)matchstate
.cache
[i
]->pattern
== key
&& !strcmp(matchstate
.cache
[i
]->pattern
, pattern
) && matchstate
.cache
[i
]->reflags
== reflags
)
147 else if (!matchstate
.cache
[old
] || matchstate
.cache
[old
]->serial
> matchstate
.cache
[i
]->serial
)
158 if (!(cp
= matchstate
.cache
[unused
]) && !(cp
= matchstate
.cache
[unused
] = newof(0, Cache_t
, 1, 0)))
161 *status
= REG_ESPACE
;
169 if ((i
= strlen(pattern
) + 1) >= cp
->size
)
171 cp
->size
= roundof(i
, ROUND
);
172 if (!(cp
->pattern
= newof(cp
->pattern
, char, cp
->size
, 0)))
175 *status
= REG_ESPACE
;
179 strcpy(cp
->pattern
, pattern
);
180 while (++i
< sizeof(Key_t
))
182 pattern
= (const char*)cp
->pattern
;
183 if (i
= regcomp(&cp
->re
, pattern
, reflags
))
190 cp
->reflags
= reflags
;
193 cp
= matchstate
.cache
[i
];
194 cp
->serial
= ++matchstate
.serial
;