RPM Package Manager, CVS Repository
http://rpm5.org/cvs/
____________________________________________________________________________
Server: rpm5.org Name: Ralf S. Engelschall
Root: /v/rpm/cvs Email: rse@rpm5.org
Module: rpm lua Date: 02-Aug-2007 21:06:59
Branch: HEAD Handle: 2007080220065900
Modified files:
lua/local lrexlib.c
rpm CHANGES
Log:
Upgrade Lua regular expression library (lua/local/lrexlib.c) from
ancient version 1.x (nov00-06oct03) to at least latest version 1.19
(may04-18dec04) from the 1.x branch. Notice: the latest existing version
is 2.2.0, but this is differently source-structured, so cannot be
included such easily.
Summary:
Revision Changes Path
1.8 +508 -210 lua/local/lrexlib.c
1.1550 +1 -0 rpm/CHANGES
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: lua/local/lrexlib.c
============================================================================
$ cvs diff -u -r1.7 -r1.8 lrexlib.c
--- lua/local/lrexlib.c 1 Aug 2007 15:55:29 -0000 1.7
+++ lua/local/lrexlib.c 2 Aug 2007 19:06:59 -0000 1.8
@@ -1,7 +1,7 @@
/* lrexlib.c - POSIX & PCRE regular expression library */
-/* POSIX regexs can use Spencer extensions for matching NULs if available
- (REG_BASIC) */
-/* Reuben Thomas nov00-06oct03 */
+/* POSIX regexs can use Spencer extensions for matching NULs if available */
+/* Reuben Thomas nov00-18dec04 */
+/* Shmuel Zeigerman may04-18dec04 */
#include <stdio.h>
#include <stdlib.h>
@@ -12,163 +12,296 @@
#include "lrexlib.h"
#ifdef LUA_USE_POSIX
-#define WITH_POSIX
+#define LREXLIB_POSIX
#endif
#ifdef LUA_USE_PCRE
-#define WITH_PCRE
+#define LREXLIB_PCRE
#endif
-/*@access regex_t @*/
-
/* Sanity check */
-#if !defined(WITH_POSIX) && !defined(WITH_PCRE)
-#error Define WITH_POSIX or WITH_PCRE, otherwise this library is useless!
+#if !defined(LREXLIB_POSIX) && !defined(LREXLIB_PCRE)
+#error Define LREXLIB_POSIX or LREXLIB_PCRE, otherwise this library is useless!
#endif
+static void L_lua_error(lua_State *L, const char *message)
+{
+ lua_pushstring(L, message);
+ lua_error(L);
+}
+
+static void *Lmalloc(lua_State *L, size_t size)
+{
+ void *p = malloc(size);
+ if(p == NULL)
+ L_lua_error(L, "malloc failed");
+ return p;
+}
+
+static int get_startoffset(lua_State *L, int stackpos, size_t len)
+{
+ int startoffset = luaL_optint(L, stackpos, 1);
+ if(startoffset > 0)
+ startoffset--;
+ else if(startoffset < 0) {
+ startoffset += len;
+ if(startoffset < 0)
+ startoffset = 0;
+ }
+ return startoffset;
+}
+
+static int udata_tostring (lua_State *L, const char* type_handle,
+ const char* type_name)
+{
+ char buf[256];
+ void *udata = luaL_checkudata(L, 1, type_handle);
+ if(udata) {
+ sprintf(buf, "%s (%p)", type_name, udata);
+ lua_pushstring(L, buf);
+ }
+ else {
+ sprintf(buf, "must be userdata of type '%s'", type_name);
+ luaL_argerror(L, 1, buf);
+ }
+ return 1;
+}
+
+typedef struct { const char* key; int val; } flags_pair;
+
+static int get_flags (lua_State *L, const flags_pair *arr)
+{
+ const flags_pair *p;
+ lua_newtable(L);
+ for(p=arr; p->key != NULL; p++) {
+ lua_pushstring(L, p->key);
+ lua_pushnumber(L, p->val);
+ lua_rawset(L, -3);
+ }
+ return 1;
+}
+
+static void createmeta(lua_State *L, const char *name)
+{
+ luaL_newmetatable(L, name); /* create new metatable */
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2); /* push metatable */
+ lua_rawset(L, -3); /* metatable.__index = metatable */
+}
/* POSIX regex methods */
-#ifdef WITH_POSIX
+#ifdef LREXLIB_POSIX
#include <regex.h>
-static int rex_comp(lua_State *L)
- /*@modifies L @*/
-{
- size_t l;
- const char *pattern;
+/* Test if regex.h corresponds to the extended POSIX library,
+ i.e. H.Spencer's
+*/
+#if defined(REG_BASIC) && defined(REG_STARTEND)
+#define LREXLIB_POSIX_EXT
+#endif
+
+const char posix_handle[] = "posix_regex_handle";
+const char posix_typename[] = "posix_regex";
+
+typedef struct {
+ regex_t r;
+ regmatch_t *match;
+} posix2; /* a better name is needed */
+
+static int posix_comp(lua_State *L) {
int res;
- regex_t *pr = (regex_t *)lua_newuserdata(L, sizeof(regex_t));
- pattern = luaL_checklstring(L, 1, &l);
-#ifdef REG_BASIC
- pr->re_endp = pattern + lua_strlen(L, 1);
- res = regcomp(pr, pattern, REG_EXTENDED | REG_PEND);
-#else
- res = regcomp(pr, pattern, REG_EXTENDED);
+ posix2 *p2;
+ size_t clen;
+ const char *pattern = luaL_checklstring(L, 1, &clen);
+ int cflags = luaL_optint(L, 2, REG_EXTENDED);
+
+#ifdef LREXLIB_POSIX_EXT
+ if((cflags & REG_EXTENDED) && (cflags & REG_NOSPEC)) {
+ L_lua_error(L,
+ "flags REG_EXTENDED and REG_NOSPEC must not be specified together");
+ }
#endif
+
+ p2 = (posix2 *)lua_newuserdata(L, sizeof(posix2));
+ p2->match = NULL;
+
+#ifdef LREXLIB_POSIX_EXT
+ if(cflags & REG_PEND)
+ p2->r.re_endp = pattern + clen;
+#endif
+
+ res = regcomp(&p2->r, pattern, cflags);
if (res) {
- size_t sz = regerror(res, pr, NULL, 0);
- char *errbuf = alloca(sz);
- regerror(res, pr, errbuf, sz);
+ size_t sz = regerror(res, &p2->r, NULL, 0);
+ char *errbuf = (char *) Lmalloc(L, sz);
+ regerror(res, &p2->r, errbuf, sz);
lua_pushstring(L, errbuf);
+ free(errbuf);
lua_error(L);
}
- luaL_getmetatable(L, "regex_t");
+
+ p2->match =
+ (regmatch_t *) Lmalloc(L, (p2->r.re_nsub + 1) * sizeof(regmatch_t));
+ luaL_getmetatable(L, posix_handle);
lua_setmetatable(L, -2);
return 1;
}
-static void rex_getargs(lua_State *L, /*@unused@*/ size_t *len, size_t *ncapt,
- const char **text, regex_t **pr, regmatch_t **match)
- /*@modifies L, *ncapt, *text, *pr, *match @*/
-{
- luaL_checkany(L, 1);
- *pr = (regex_t *)lua_touserdata(L, 1);
-/*@-observertrans -dependenttrans @*/
-#ifdef REG_BASIC
- *text = luaL_checklstring(L, 2, len);
-#else
- *text = luaL_checklstring(L, 2, NULL);
-#endif
-/*@=observertrans =dependenttrans @*/
- *ncapt = (*pr)->re_nsub;
- luaL_checkstack(L, *ncapt + 2, "too many captures");
- *match = malloc((*ncapt + 1) * sizeof(regmatch_t));
+static void posix_getargs
+ (lua_State *L, posix2 **p2, const char **text, size_t *text_len)
+{
+ *p2 = (posix2 *)luaL_checkudata(L, 1, posix_handle);
+ luaL_argcheck(L, *p2 != NULL, 1, "compiled regexp expected");
+ *text = luaL_checklstring(L, 2, text_len);
}
-static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
- size_t ncapt)
- /*@modifies L @*/
+typedef void (*posix_push_matches)
+ (lua_State *L, const char *text, int startoffset,
+ regmatch_t *match, size_t ncapt);
+
+static void posix_push_substrings
+ (lua_State *L, const char *text, int startoffset,
+ regmatch_t *match, size_t ncapt)
{
size_t i;
+ if(startoffset) {
+ /* suppress compiler warning */
+ }
lua_newtable(L);
for (i = 1; i <= ncapt; i++) {
if (match[i].rm_so >= 0) {
- lua_pushlstring(L, text + match[i].rm_so,
- match[i].rm_eo - match[i].rm_so);
- lua_rawseti(L, -2, i);
+ lua_pushlstring
+ (L, text + match[i].rm_so, match[i].rm_eo - match[i].rm_so);
+ }
+ else
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, i);
+ }
+}
+
+static void posix_push_offsets
+ (lua_State *L, const char *text, int startoffset,
+ regmatch_t *match, size_t ncapt)
+{
+ size_t i, j;
+ if(text) {
+ /* suppress compiler warning */
+ }
+ lua_newtable(L);
+ for (i=1, j=1; i <= ncapt; i++) {
+ if (match[i].rm_so >= 0) {
+ lua_pushnumber(L, startoffset + match[i].rm_so + 1);
+ lua_rawseti(L, -2, j++);
+ lua_pushnumber(L, startoffset + match[i].rm_eo);
+ lua_rawseti(L, -2, j++);
+ }
+ else {
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, j++);
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, j++);
}
}
}
-static int rex_match(lua_State *L)
- /*@modifies L @*/
+static int posix_match_generic(lua_State *L, posix_push_matches push_matches)
{
- int res;
-#ifdef REG_BASIC
- size_t len;
-#endif
- size_t ncapt;
+ size_t elen;
const char *text;
- regex_t *pr;
- regmatch_t *match;
- rex_getargs(L,
-#ifdef REG_BASIC
- &len,
+ posix2 *p2;
+ int startoffset;
+ int res;
+
+#ifdef LREXLIB_POSIX_EXT
+ int eflags = luaL_optint(L, 4, REG_STARTEND);
#else
- NULL,
+ int eflags = luaL_optint(L, 4, 0);
#endif
- &ncapt, &text, &pr, &match);
-#ifdef REG_BASIC
- match[0].rm_so = 0;
- match[0].rm_eo = len;
- res = regexec(pr, text, ncapt + 1, match, REG_STARTEND);
+
+ posix_getargs(L, &p2, &text, &elen);
+ startoffset = get_startoffset(L, 3, elen);
+
+#ifdef LREXLIB_POSIX_EXT
+ if(eflags & REG_STARTEND) {
+ p2->match[0].rm_so = startoffset;
+ p2->match[0].rm_eo = elen;
+ startoffset = 0;
+ }
+ else
+ text += startoffset;
#else
- res = regexec(pr, text, ncapt + 1, match, 0);
+ text += startoffset;
#endif
+
+ /* execute the search */
+ res = regexec(&p2->r, text, p2->r.re_nsub + 1, p2->match, eflags);
if (res == 0) {
- lua_pushnumber(L, match[0].rm_so + 1);
- lua_pushnumber(L, match[0].rm_eo);
- rex_push_matches(L, text, match, ncapt);
- lua_pushstring(L, "n");
- lua_pushnumber(L, ncapt);
- lua_rawset(L, -3);
+ lua_pushnumber(L, p2->match[0].rm_so + 1 + startoffset);
+ lua_pushnumber(L, p2->match[0].rm_eo + startoffset);
+ (*push_matches)(L, text, startoffset, p2->match, p2->r.re_nsub);
return 3;
- } else
- return 0;
+ }
+ return 0;
}
-static int rex_gmatch(lua_State *L)
- /*@modifies L @*/
+static int posix_match(lua_State *L)
{
+ return posix_match_generic(L, posix_push_substrings);
+}
+
+static int posix_exec(lua_State *L)
+{
+ return posix_match_generic(L, posix_push_offsets);
+}
+
+static int posix_gmatch(lua_State *L) {
int res;
-#ifdef REG_BASIC
size_t len;
-#endif
- size_t ncapt, nmatch = 0, maxmatch = 0, limit = 0;
+ size_t nmatch = 0, limit = 0;
const char *text;
- regex_t *pr;
- regmatch_t *match;
- rex_getargs(L,
-#ifdef REG_BASIC
- &len,
+ posix2 *p2;
+ size_t maxmatch = (size_t)luaL_optnumber(L, 4, 0);
+
+#ifdef LREXLIB_POSIX_EXT
+ int eflags = luaL_optint(L, 5, REG_STARTEND);
#else
- NULL,
+ int eflags = luaL_optint(L, 5, 0);
#endif
- &ncapt, &text, &pr, &match);
+
+ posix_getargs(L, &p2, &text, &len);
luaL_checktype(L, 3, LUA_TFUNCTION);
- if (lua_gettop(L) > 3) {
- maxmatch = (size_t)luaL_checknumber(L, 4);
+
+ if(maxmatch > 0) /* this must be stated in the docs */
limit = 1;
- }
+
while (!limit || nmatch < maxmatch) {
-#ifdef REG_BASIC
- match[0].rm_so = 0;
- match[0].rm_eo = len;
- res = regexec(pr, text, ncapt + 1, match, REG_STARTEND);
-#else
- res = regexec(pr, text, ncapt + 1, match, 0);
+
+#ifdef LREXLIB_POSIX_EXT
+ if(eflags & REG_STARTEND) {
+ p2->match[0].rm_so = 0;
+ p2->match[0].rm_eo = len;
+ }
#endif
+
+ res = regexec(&p2->r, text, p2->r.re_nsub + 1, p2->match, eflags);
if (res == 0) {
+ nmatch++;
lua_pushvalue(L, 3);
- lua_pushlstring(L, text + match[0].rm_so, match[0].rm_eo - match[0].rm_so);
- rex_push_matches(L, text, match, ncapt);
- lua_call(L, 2, 0);
- text += match[0].rm_eo;
-#ifdef REG_BASIC
- len -= match[0].rm_eo;
+ lua_pushlstring(L, text + p2->match[0].rm_so,
+ p2->match[0].rm_eo - p2->match[0].rm_so);
+ posix_push_substrings(L, text, 0, p2->match, p2->r.re_nsub);
+ lua_call(L, 2, 1);
+ if(lua_toboolean(L, -1))
+ break;
+ lua_pop(L, 1);
+ text += p2->match[0].rm_eo;
+
+#ifdef LREXLIB_POSIX_EXT
+ if(eflags & REG_STARTEND)
+ len -= p2->match[0].rm_eo;
#endif
- nmatch++;
+
} else
break;
}
@@ -176,127 +309,260 @@
return 1;
}
-static int rex_gc (lua_State *L)
- /*@modifies L @*/
-{
- regex_t *r = (regex_t *)luaL_checkudata(L, 1, "regex_t");
- if (r)
- regfree(r);
+static int posix_gc (lua_State *L) {
+ posix2 *p2 = (posix2 *)luaL_checkudata(L, 1, posix_handle);
+ if (p2) {
+ regfree(&p2->r);
+ if(p2->match)
+ free(p2->match);
+ }
return 0;
}
-/*@-readonlytrans@*/
-/*@unchecked@*/
-static const luaL_reg rexmeta[] = {
- {"match", rex_match},
- {"gmatch", rex_gmatch},
- {"__gc", rex_gc},
+static int posix_tostring (lua_State *L) {
+ return udata_tostring(L, posix_handle, posix_typename);
+}
+
+static flags_pair posix_flags[] =
+{
+#ifdef LREXLIB_POSIX_EXT
+ { "BASIC", REG_BASIC },
+ { "NOSPEC", REG_NOSPEC },
+ { "PEND", REG_PEND },
+ { "STARTEND", REG_STARTEND },
+#endif
+ { "EXTENDED", REG_EXTENDED },
+ { "ICASE", REG_ICASE },
+ { "NOSUB", REG_NOSUB },
+ { "NEWLINE", REG_NEWLINE },
+ { "NOTBOL", REG_NOTBOL },
+ { "NOTEOL", REG_NOTEOL },
+ { NULL, 0 }
+};
+
+static int posix_get_flags (lua_State *L) {
+ return get_flags(L, posix_flags);
+}
+
+static const luaL_reg posixmeta[] = {
+ {"exec", posix_exec},
+ {"match", posix_match},
+ {"gmatch", posix_gmatch},
+ {"__gc", posix_gc},
+ {"__tostring", posix_tostring},
{NULL, NULL}
};
-/*@=readonlytrans@*/
-#endif /* WITH_POSIX */
+#endif /* LREXLIB_POSIX */
/* PCRE methods */
-#ifdef WITH_PCRE
+#ifdef LREXLIB_PCRE
+#include <locale.h>
#include <pcre.h>
-static int pcre_comp(lua_State *L)
+const char pcre_handle[] = "pcre_regex_handle";
+const char pcre_typename[] = "pcre_regex";
+
+typedef struct {
+ pcre *pr;
+ pcre_extra *extra;
+ int *match;
+ int ncapt;
+ const unsigned char *tables;
+} pcre2; /* a better name is needed */
+
+static const unsigned char *Lpcre_maketables(lua_State *L, int stackpos)
{
- size_t l;
- const char *pattern;
+ const unsigned char *tables;
+ char old_locale[256];
+ const char *locale = luaL_checkstring(L, stackpos);
+
+ strcpy(old_locale, setlocale(LC_CTYPE, NULL)); /* store the locale */
+ if(NULL == setlocale(LC_CTYPE, locale)) /* set new locale */
+ L_lua_error(L, "cannot set locale");
+ tables = pcre_maketables(); /* make tables with new locale */
+ setlocale(LC_CTYPE, old_locale); /* restore the old locale */
+ return tables;
+}
+
+static int Lpcre_comp(lua_State *L)
+{
+ char buf[256];
const char *error;
int erroffset;
- pcre **ppr = (pcre **)lua_newuserdata(L, sizeof(pcre **));
- pcre *pr;
- pattern = luaL_checklstring(L, 1, &l);
- pr = pcre_compile(pattern, 0, &error, &erroffset, NULL);
- if (!pr) {
- lua_pushstring(L, error);
- lua_error(L);
- }
- *ppr = pr;
- luaL_getmetatable(L, "pcre");
+ pcre2 *ud;
+ size_t clen; /* clen isn't used in PCRE */
+ const char *pattern = luaL_checklstring(L, 1, &clen);
+ int cflags = luaL_optint(L, 2, 0);
+ const unsigned char *tables = NULL;
+
+ if(lua_gettop(L) > 2 && !lua_isnil(L, 3))
+ tables = Lpcre_maketables(L, 3);
+
+ ud = (pcre2*)lua_newuserdata(L, sizeof(pcre2));
+ luaL_getmetatable(L, pcre_handle);
lua_setmetatable(L, -2);
+ ud->match = NULL;
+ ud->extra = NULL;
+ ud->tables = tables; /* keep this for eventual freeing */
+
+ ud->pr = pcre_compile(pattern, cflags, &error, &erroffset, tables);
+ if(!ud->pr) {
+ sprintf(buf, "%s (pattern offset: %d)", error, erroffset+1);
+ /* show offset 1-based as it's common in Lua */
+ L_lua_error(L, buf);
+ }
+
+ ud->extra = pcre_study(ud->pr, 0, &error);
+ if(error) L_lua_error(L, error);
+
+ pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_CAPTURECOUNT, &ud->ncapt);
+ /* need (2 ints per capture, plus one for substring match) * 3/2 */
+ ud->match = (int *) Lmalloc(L, (ud->ncapt + 1) * 3 * sizeof(int));
+
return 1;
}
-static void pcre_getargs(lua_State *L, size_t *len, int *ncapt, const char **text,
- pcre ***ppr, int **match)
+static void Lpcre_getargs(lua_State *L, pcre2 **pud, const char **text,
+ size_t *text_len)
{
- luaL_checkany(L, 1);
- *ppr = (pcre **)lua_touserdata(L, 1);
- *text = luaL_checklstring(L, 2, len);
- pcre_fullinfo(**ppr, NULL, PCRE_INFO_CAPTURECOUNT, ncapt);
- luaL_checkstack(L, *ncapt + 2, "too many captures");
- /* need (2 ints per capture, plus one for substring match) * 3/2 */
- *match = malloc((*ncapt + 1) * 3 * sizeof(int));
+ *pud = (pcre2 *)luaL_checkudata(L, 1, pcre_handle);
+ luaL_argcheck(L, *pud != NULL, 1, "compiled regexp expected");
+ *text = luaL_checklstring(L, 2, text_len);
}
-static void pcre_push_matches(lua_State *L, const char *text, int *match,
- int ncapt)
+typedef void (*Lpcre_push_matches) (lua_State *L, const char *text, pcre2 *ud);
+
+static void Lpcre_push_substrings (lua_State *L, const char *text, pcre2 *ud)
{
int i;
+ int namecount;
+ unsigned char *name_table;
+ int name_entry_size;
+ unsigned char *tabptr;
+ const int *match = ud->match;
+
lua_newtable(L);
- for (i = 1; i <= ncapt; i++) {
- if (match[i * 2] >= 0) {
- lua_pushlstring(L, text + match[i * 2],
- match[i * 2 + 1] - match[i * 2]);
- lua_rawseti(L, -2, i);
+ for (i = 1; i <= ud->ncapt; i++) {
+ int j = i * 2;
+ if (match[j] >= 0)
+ lua_pushlstring(L, text + match[j], match[j + 1] - match[j]);
+ else
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, i);
+ }
+
+ /* now do named subpatterns - NJG */
+ pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMECOUNT, &namecount);
+ if (namecount <= 0)
+ return;
+ pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMETABLE, &name_table);
+ pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size);
+ tabptr = name_table;
+ for (i = 0; i < namecount; i++) {
+ int n = (tabptr[0] << 8) | tabptr[1]; /* number of the capturing parenthesis */
+ if (n > 0 && n <= ud->ncapt) { /* check range */
+ int j = n * 2;
+ lua_pushstring(L, (char *)(tabptr + 2)); /* name of the capture, zero terminated */
+ if (match[j] >= 0)
+ lua_pushlstring(L, text + match[j], match[j + 1] - match[j]);
+ else
+ lua_pushboolean(L, 0);
+ lua_rawset(L, -3);
}
+ tabptr += name_entry_size;
}
}
-static int pcre_match(lua_State *L)
+static void Lpcre_push_offsets (lua_State *L, const char *text, pcre2 * ud)
+{
+ int i, j, k;
+ if(text) {
+ /* suppress compiler warning */
+ }
+ lua_newtable(L);
+ for (i=1, j=1; i <= ud->ncapt; i++) {
+ k = i * 2;
+ if (ud->match[k] >= 0) {
+ lua_pushnumber(L, ud->match[k] + 1);
+ lua_rawseti(L, -2, j++);
+ lua_pushnumber(L, ud->match[k+1]);
+ lua_rawseti(L, -2, j++);
+ }
+ else {
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, j++);
+ lua_pushboolean(L, 0);
+ lua_rawseti(L, -2, j++);
+ }
+ }
+}
+
+static int Lpcre_match_generic(lua_State *L, Lpcre_push_matches push_matches)
{
int res;
const char *text;
- pcre **ppr;
- int *match;
- int ncapt;
- size_t len;
- pcre_getargs(L, &len, &ncapt, &text, &ppr, &match);
- res = pcre_exec(*ppr, NULL, text, (int)len, 0, 0, match, (ncapt + 1) * 3);
+ pcre2 *ud;
+ size_t elen;
+ int startoffset;
+ int eflags = luaL_optint(L, 4, 0);
+
+ Lpcre_getargs(L, &ud, &text, &elen);
+ startoffset = get_startoffset(L, 3, elen);
+
+ res = pcre_exec(ud->pr, ud->extra, text, (int)elen, startoffset, eflags,
+ ud->match, (ud->ncapt + 1) * 3);
if (res >= 0) {
- lua_pushnumber(L, match[0] + 1);
- lua_pushnumber(L, match[1]);
- pcre_push_matches(L, text, match, ncapt);
- lua_pushstring(L, "n");
- lua_pushnumber(L, ncapt);
- lua_rawset(L, -3);
+ lua_pushnumber(L, ud->match[0] + 1);
+ lua_pushnumber(L, ud->match[1]);
+ (*push_matches)(L, text, ud);
return 3;
- } else
- return 0;
+ }
+ return 0;
+}
+
+static int Lpcre_match(lua_State *L)
+{
+ return Lpcre_match_generic(L, Lpcre_push_substrings);
+}
+
+static int Lpcre_exec(lua_State *L)
+{
+ return Lpcre_match_generic(L, Lpcre_push_offsets);
}
-static int pcre_gmatch(lua_State *L)
+static int Lpcre_gmatch(lua_State *L)
{
int res;
- const char *text;
- int limit = 0;
- int ncapt, nmatch = 0, maxmatch;
- pcre **ppr;
- int *match;
size_t len;
- pcre_getargs(L, &len, &ncapt, &text, &ppr, &match);
+ int nmatch = 0, limit = 0;
+ const char *text;
+ pcre2 *ud;
+ int maxmatch = luaL_optint(L, 4, 0);
+ int eflags = luaL_optint(L, 5, 0);
+ int startoffset = 0;
+ Lpcre_getargs(L, &ud, &text, &len);
luaL_checktype(L, 3, LUA_TFUNCTION);
- if (lua_gettop(L) > 3) {
- maxmatch = (int)luaL_checknumber(L, 4);
+
+ if(maxmatch > 0) /* this must be stated in the docs */
limit = 1;
- }
+
while (!limit || nmatch < maxmatch) {
- res = pcre_exec(*ppr, NULL, text, (int)len, 0, 0, match, (ncapt + 1) * 3);
- if (res == 0) {
- lua_pushvalue(L, 3);
- lua_pushlstring(L, text + match[0], match[1] - match[0]);
- pcre_push_matches(L, text, match, ncapt);
- lua_call(L, 2, 0);
- text += match[1];
- len -= match[1];
+ res = pcre_exec(ud->pr, ud->extra, text, (int)len, startoffset, eflags,
+ ud->match, (ud->ncapt + 1) * 3);
+ if (res >= 0) {
nmatch++;
+ lua_pushvalue(L, 3);
+ lua_pushlstring(L, text + ud->match[0], ud->match[1] - ud->match[0]);
+ Lpcre_push_substrings(L, text, ud);
+ lua_call(L, 2, 1);
+ if(lua_toboolean(L, -1))
+ break;
+ lua_pop(L, 1);
+ startoffset = ud->match[1];
} else
break;
}
@@ -304,57 +570,89 @@
return 1;
}
-static int pcre_gc (lua_State *L)
+static int Lpcre_gc (lua_State *L)
{
- pcre **ppr = (pcre **)luaL_checkudata(L, 1, "pcre");
- if (ppr)
- pcre_free(*ppr);
+ pcre2 *ud = (pcre2 *)luaL_checkudata(L, 1, pcre_handle);
+ if (ud) {
+ if(ud->pr) pcre_free(ud->pr);
+ if(ud->extra) pcre_free(ud->extra);
+ if(ud->tables) pcre_free((void *)ud->tables);
+ if(ud->match) free(ud->match);
+ }
return 0;
}
+static int Lpcre_tostring (lua_State *L) {
+ return udata_tostring(L, pcre_handle, pcre_typename);
+}
+
+static int Lpcre_vers (lua_State *L)
+{
+ lua_pushstring(L, pcre_version());
+ return 1;
+}
+
+static flags_pair pcre_flags[] =
+{
+ { "CASELESS", PCRE_CASELESS },
+ { "MULTILINE", PCRE_MULTILINE },
+ { "DOTALL", PCRE_DOTALL },
+ { "EXTENDED", PCRE_EXTENDED },
+ { "ANCHORED", PCRE_ANCHORED },
+ { "DOLLAR_ENDONLY", PCRE_DOLLAR_ENDONLY },
+ { "EXTRA", PCRE_EXTRA },
+ { "NOTBOL", PCRE_NOTBOL },
+ { "NOTEOL", PCRE_NOTEOL },
+ { "UNGREEDY", PCRE_UNGREEDY },
+ { "NOTEMPTY", PCRE_NOTEMPTY },
+ { "UTF8", PCRE_UTF8 },
+#if PCRE_MAJOR >= 4
+ { "NO_AUTO_CAPTURE", PCRE_NO_AUTO_CAPTURE },
+ { "NO_UTF8_CHECK", PCRE_NO_UTF8_CHECK },
+#endif
+ { NULL, 0 }
+};
+
+static int Lpcre_get_flags (lua_State *L) {
+ return get_flags(L, pcre_flags);
+}
+
static const luaL_reg pcremeta[] = {
- {"match", pcre_match},
- {"gmatch", pcre_gmatch},
- {"__gc", pcre_gc},
+ {"exec", Lpcre_exec},
+ {"match", Lpcre_match},
+ {"gmatch", Lpcre_gmatch},
+ {"__gc", Lpcre_gc},
+ {"__tostring", Lpcre_tostring},
{NULL, NULL}
};
-#endif /* defined(WITH_PCRE) */
+#endif /* defined(LREXLIB_PCRE) */
/* Open the library */
-/*@-readonlytrans@*/
-/*@unchecked@*/
static const luaL_reg rexlib[] = {
-#ifdef WITH_POSIX
- {"newPOSIX", rex_comp},
-#endif
-#ifdef WITH_PCRE
- {"newPCRE", pcre_comp},
+#ifdef LREXLIB_POSIX
+ {"newPOSIX", posix_comp},
+ {"flagsPOSIX", posix_get_flags},
+#endif
+#ifdef LREXLIB_PCRE
+ {"newPCRE", Lpcre_comp},
+ {"flagsPCRE", Lpcre_get_flags},
+ {"versionPCRE", Lpcre_vers},
#endif
{NULL, NULL}
};
-/*@=readonlytrans@*/
-
-static void createmeta(lua_State *L, const char *name)
- /*@modifies L @*/
-{
- luaL_newmetatable(L, name); /* create new metatable */
- lua_pushliteral(L, "__index");
- lua_pushvalue(L, -2); /* push metatable */
- lua_rawset(L, -3); /* metatable.__index = metatable */
-}
LUALIB_API int luaopen_rex(lua_State *L)
{
-#ifdef WITH_POSIX
- createmeta(L, "regex_t");
- luaL_openlib(L, NULL, rexmeta, 0);
+#ifdef LREXLIB_POSIX
+ createmeta(L, posix_handle);
+ luaL_openlib(L, NULL, posixmeta, 0);
lua_pop(L, 1);
#endif
-#ifdef WITH_PCRE
- createmeta(L, "pcre");
+#ifdef LREXLIB_PCRE
+ createmeta(L, pcre_handle);
luaL_openlib(L, NULL, pcremeta, 0);
lua_pop(L, 1);
#endif
@@ .
patch -p0 <<'@@ .'
Index: rpm/CHANGES
============================================================================
$ cvs diff -u -r1.1549 -r1.1550 CHANGES
--- rpm/CHANGES 2 Aug 2007 18:38:19 -0000 1.1549
+++ rpm/CHANGES 2 Aug 2007 19:06:59 -0000 1.1550
@@ -1,4 +1,5 @@
4.5 -> 5.0:
+ - rse: upgrade lua/local/lrexlib.c from version 1.x (nov00-06oct03) to latest version 1.19 (may04-18dec04)
- jbj: teach headerGetExtension() to lookup extensions.
- jbj: chain through new headerCompundFormats.
- jbj: refactor most header extensions from -lrpm to -lrpmdb. heh, no filenames, very sick and sad.
@@ .
Received on Thu Aug 2 21:06:59 2007