1 /* lrexlib.c - POSIX & PCRE regular expression library */
2 /* POSIX regexs can use Spencer extensions for matching NULs if available
4 /* Reuben Thomas nov00-06oct03 */
16 #if !defined(WITH_POSIX) && !defined(WITH_PCRE)
17 #error Define WITH_POSIX or WITH_PCRE, otherwise this library is useless!
21 /* POSIX regex methods */
27 static int rex_comp(lua_State *L)
32 regex_t *pr = (regex_t *)lua_newuserdata(L, sizeof(regex_t));
33 pattern = luaL_checklstring(L, 1, &l);
35 pr->re_endp = pattern + lua_strlen(L, 1);
36 res = regcomp(pr, pattern, REG_EXTENDED | REG_PEND);
38 res = regcomp(pr, pattern, REG_EXTENDED);
41 size_t sz = regerror(res, pr, NULL, 0);
43 regerror(res, pr, errbuf, sz);
44 lua_pushstring(L, errbuf);
47 luaL_getmetatable(L, "regex_t");
48 lua_setmetatable(L, -2);
52 static void rex_getargs(lua_State *L, size_t *len, size_t *ncapt,
53 const char **text, regex_t **pr, regmatch_t **match)
56 *pr = (regex_t *)lua_touserdata(L, 1);
58 *text = luaL_checklstring(L, 2, len);
60 *text = luaL_checklstring(L, 2, NULL);
62 *ncapt = (*pr)->re_nsub;
63 luaL_checkstack(L, *ncapt + 2, "too many captures");
64 *match = malloc((*ncapt + 1) * sizeof(regmatch_t));
67 static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
72 for (i = 1; i <= ncapt; i++) {
73 if (match[i].rm_so >= 0) {
74 lua_pushlstring(L, text + match[i].rm_so,
75 match[i].rm_eo - match[i].rm_so);
76 lua_rawseti(L, -2, i);
81 static int rex_match(lua_State *L)
97 &ncapt, &text, &pr, &match);
100 match[0].rm_eo = len;
101 res = regexec(pr, text, ncapt + 1, match, REG_STARTEND);
103 res = regexec(pr, text, ncapt + 1, match, 0);
106 lua_pushnumber(L, match[0].rm_so + 1);
107 lua_pushnumber(L, match[0].rm_eo);
108 rex_push_matches(L, text, match, ncapt);
109 lua_pushstring(L, "n");
110 lua_pushnumber(L, ncapt);
117 static int rex_gmatch(lua_State *L)
123 size_t ncapt, nmatch = 0, maxmatch = 0, limit = 0;
133 &ncapt, &text, &pr, &match);
134 luaL_checktype(L, 3, LUA_TFUNCTION);
135 if (lua_gettop(L) > 3) {
136 maxmatch = (size_t)luaL_checknumber(L, 4);
139 while (!limit || nmatch < maxmatch) {
142 match[0].rm_eo = len;
143 res = regexec(pr, text, ncapt + 1, match, REG_STARTEND);
145 res = regexec(pr, text, ncapt + 1, match, 0);
149 lua_pushlstring(L, text + match[0].rm_so, match[0].rm_eo - match[0].rm_so);
150 rex_push_matches(L, text, match, ncapt);
152 text += match[0].rm_eo;
154 len -= match[0].rm_eo;
160 lua_pushnumber(L, nmatch);
164 static int rex_gc (lua_State *L)
166 regex_t *r = (regex_t *)luaL_checkudata(L, 1, "regex_t");
172 static const luaL_Reg rexmeta[] = {
173 {"match", rex_match},
174 {"gmatch", rex_gmatch},
179 #endif /* WITH_POSIX */
186 #include <pcre/pcre.h>
188 static int pcre_comp(lua_State *L)
194 pcre **ppr = (pcre **)lua_newuserdata(L, sizeof(pcre **));
196 pattern = luaL_checklstring(L, 1, &l);
197 pr = pcre_compile(pattern, 0, &error, &erroffset, NULL);
199 lua_pushstring(L, error);
203 luaL_getmetatable(L, "pcre");
204 lua_setmetatable(L, -2);
208 static void pcre_getargs(lua_State *L, int *len, int *ncapt, const char **text,
209 pcre ***ppr, int **match)
212 *ppr = (pcre **)lua_touserdata(L, 1);
213 *text = luaL_checklstring(L, 2, len);
214 pcre_fullinfo(**ppr, NULL, PCRE_INFO_CAPTURECOUNT, ncapt);
215 luaL_checkstack(L, *ncapt + 2, "too many captures");
216 /* need (2 ints per capture, plus one for substring match) * 3/2 */
217 *match = malloc((*ncapt + 1) * 3 * sizeof(int));
220 static void pcre_push_matches(lua_State *L, const char *text, int *match,
225 for (i = 1; i <= ncapt; i++) {
226 if (match[i * 2] >= 0) {
227 lua_pushlstring(L, text + match[i * 2],
228 match[i * 2 + 1] - match[i * 2]);
229 lua_rawseti(L, -2, i);
234 static int pcre_match(lua_State *L)
242 pcre_getargs(L, &len, &ncapt, &text, &ppr, &match);
243 res = pcre_exec(*ppr, NULL, text, len, 0, 0, match, (ncapt + 1) * 3);
245 lua_pushnumber(L, match[0] + 1);
246 lua_pushnumber(L, match[1]);
247 pcre_push_matches(L, text, match, ncapt);
248 lua_pushstring(L, "n");
249 lua_pushnumber(L, ncapt);
256 static int pcre_gmatch(lua_State *L)
261 int ncapt, nmatch = 0, maxmatch;
265 pcre_getargs(L, &len, &ncapt, &text, &ppr, &match);
266 luaL_checktype(L, 3, LUA_TFUNCTION);
267 if (lua_gettop(L) > 3) {
268 maxmatch = (int)luaL_checknumber(L, 4);
271 while (!limit || nmatch < maxmatch) {
272 res = pcre_exec(*ppr, NULL, text, len, 0, 0, match, (ncapt + 1) * 3);
275 lua_pushlstring(L, text + match[0], match[1] - match[0]);
276 pcre_push_matches(L, text, match, ncapt);
284 lua_pushnumber(L, nmatch);
288 static int pcre_gc (lua_State *L)
290 pcre **ppr = (pcre **)luaL_checkudata(L, 1, "pcre");
296 static const luaL_reg pcremeta[] = {
297 {"match", pcre_match},
298 {"gmatch", pcre_gmatch},
303 #endif /* defined(WITH_PCRE) */
306 /* Open the library */
308 static const luaL_Reg rexlib[] = {
310 {"newPOSIX", rex_comp},
313 {"newPCRE", pcre_comp},
318 static void createmeta(lua_State *L, const char *name)
320 luaL_newmetatable(L, name); /* create new metatable */
321 lua_pushliteral(L, "__index");
322 lua_pushvalue(L, -2); /* push metatable */
323 lua_rawset(L, -3); /* metatable.__index = metatable */
326 LUALIB_API int luaopen_rex(lua_State *L)
329 createmeta(L, "regex_t");
330 luaL_openlib(L, NULL, rexmeta, 0);
334 createmeta(L, "pcre");
335 luaL_openlib(L, NULL, pcremeta, 0);
338 luaL_openlib(L, "rex", rexlib, 0);