RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: lua/local/ lrexlib.c rpm/ CHANGES

From: Ralf S. Engelschall <rse@rpm5.org>
Date: Thu 02 Aug 2007 - 21:06:59 CEST
Message-Id: <20070802190659.C8B4A34844E@rpm5.org>
  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
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.