packages feed

lpeg 1.0.4 → 1.1.0

raw patch · 29 files changed

+4767/−4231 lines, 29 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -2,6 +2,12 @@  `lpeg` uses [PVP Versioning][]. +## lpeg-1.1.0++Released 2023-09-27.++-   Update to the latest upstream version, LPeg version 1.1.+ ## lpeg-1.0.4  Released 2023-03-13.
− cbits/lpeg-1.0.2/lpcap.c
@@ -1,555 +0,0 @@-/*-** $Id: lpcap.c $-** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-*/--#include "lua.h"-#include "lauxlib.h"--#include "lpcap.h"-#include "lptypes.h"---#define captype(cap)	((cap)->kind)--#define isclosecap(cap)	(captype(cap) == Cclose)--#define closeaddr(c)	((c)->s + (c)->siz - 1)--#define isfullcap(cap)	((cap)->siz != 0)--#define getfromktable(cs,v)	lua_rawgeti((cs)->L, ktableidx((cs)->ptop), v)--#define pushluaval(cs)		getfromktable(cs, (cs)->cap->idx)----/*-** Put at the cache for Lua values the value indexed by 'v' in ktable-** of the running pattern (if it is not there yet); returns its index.-*/-static int updatecache (CapState *cs, int v) {-  int idx = cs->ptop + 1;  /* stack index of cache for Lua values */-  if (v != cs->valuecached) {  /* not there? */-    getfromktable(cs, v);  /* get value from 'ktable' */-    lua_replace(cs->L, idx);  /* put it at reserved stack position */-    cs->valuecached = v;  /* keep track of what is there */-  }-  return idx;-}---static int pushcapture (CapState *cs);---/*-** Goes back in a list of captures looking for an open capture-** corresponding to a close-*/-static Capture *findopen (Capture *cap) {-  int n = 0;  /* number of closes waiting an open */-  for (;;) {-    cap--;-    if (isclosecap(cap)) n++;  /* one more open to skip */-    else if (!isfullcap(cap))-      if (n-- == 0) return cap;-  }-}---/*-** Go to the next capture-*/-static void nextcap (CapState *cs) {-  Capture *cap = cs->cap;-  if (!isfullcap(cap)) {  /* not a single capture? */-    int n = 0;  /* number of opens waiting a close */-    for (;;) {  /* look for corresponding close */-      cap++;-      if (isclosecap(cap)) {-        if (n-- == 0) break;-      }-      else if (!isfullcap(cap)) n++;-    }-  }-  cs->cap = cap + 1;  /* + 1 to skip last close (or entire single capture) */-}---/*-** Push on the Lua stack all values generated by nested captures inside-** the current capture. Returns number of values pushed. 'addextra'-** makes it push the entire match after all captured values. The-** entire match is pushed also if there are no other nested values,-** so the function never returns zero.-*/-static int pushnestedvalues (CapState *cs, int addextra) {-  Capture *co = cs->cap;-  if (isfullcap(cs->cap++)) {  /* no nested captures? */-    lua_pushlstring(cs->L, co->s, co->siz - 1);  /* push whole match */-    return 1;  /* that is it */-  }-  else {-    int n = 0;-    while (!isclosecap(cs->cap))  /* repeat for all nested patterns */-      n += pushcapture(cs);-    if (addextra || n == 0) {  /* need extra? */-      lua_pushlstring(cs->L, co->s, cs->cap->s - co->s);  /* push whole match */-      n++;-    }-    cs->cap++;  /* skip close entry */-    return n;-  }-}---/*-** Push only the first value generated by nested captures-*/-static void pushonenestedvalue (CapState *cs) {-  int n = pushnestedvalues(cs, 0);-  if (n > 1)-    lua_pop(cs->L, n - 1);  /* pop extra values */-}---/*-** Try to find a named group capture with the name given at the top of-** the stack; goes backward from 'cap'.-*/-static Capture *findback (CapState *cs, Capture *cap) {-  lua_State *L = cs->L;-  while (cap-- > cs->ocap) {  /* repeat until end of list */-    if (isclosecap(cap))-      cap = findopen(cap);  /* skip nested captures */-    else if (!isfullcap(cap))-      continue; /* opening an enclosing capture: skip and get previous */-    if (captype(cap) == Cgroup) {-      getfromktable(cs, cap->idx);  /* get group name */-      if (lp_equal(L, -2, -1)) {  /* right group? */-        lua_pop(L, 2);  /* remove reference name and group name */-        return cap;-      }-      else lua_pop(L, 1);  /* remove group name */-    }-  }-  luaL_error(L, "back reference '%s' not found", lua_tostring(L, -1));-  return NULL;  /* to avoid warnings */-}---/*-** Back-reference capture. Return number of values pushed.-*/-static int backrefcap (CapState *cs) {-  int n;-  Capture *curr = cs->cap;-  pushluaval(cs);  /* reference name */-  cs->cap = findback(cs, curr);  /* find corresponding group */-  n = pushnestedvalues(cs, 0);  /* push group's values */-  cs->cap = curr + 1;-  return n;-}---/*-** Table capture: creates a new table and populates it with nested-** captures.-*/-static int tablecap (CapState *cs) {-  lua_State *L = cs->L;-  int n = 0;-  lua_newtable(L);-  if (isfullcap(cs->cap++))-    return 1;  /* table is empty */-  while (!isclosecap(cs->cap)) {-    if (captype(cs->cap) == Cgroup && cs->cap->idx != 0) {  /* named group? */-      pushluaval(cs);  /* push group name */-      pushonenestedvalue(cs);-      lua_settable(L, -3);-    }-    else {  /* not a named group */-      int i;-      int k = pushcapture(cs);-      for (i = k; i > 0; i--)  /* store all values into table */-        lua_rawseti(L, -(i + 1), n + i);-      n += k;-    }-  }-  cs->cap++;  /* skip close entry */-  return 1;  /* number of values pushed (only the table) */-}---/*-** Table-query capture-*/-static int querycap (CapState *cs) {-  int idx = cs->cap->idx;-  pushonenestedvalue(cs);  /* get nested capture */-  lua_gettable(cs->L, updatecache(cs, idx));  /* query cap. value at table */-  if (!lua_isnil(cs->L, -1))-    return 1;-  else {  /* no value */-    lua_pop(cs->L, 1);  /* remove nil */-    return 0;-  }-}---/*-** Fold capture-*/-static int foldcap (CapState *cs) {-  int n;-  lua_State *L = cs->L;-  int idx = cs->cap->idx;-  if (isfullcap(cs->cap++) ||  /* no nested captures? */-      isclosecap(cs->cap) ||  /* no nested captures (large subject)? */-      (n = pushcapture(cs)) == 0)  /* nested captures with no values? */-    return luaL_error(L, "no initial value for fold capture");-  if (n > 1)-    lua_pop(L, n - 1);  /* leave only one result for accumulator */-  while (!isclosecap(cs->cap)) {-    lua_pushvalue(L, updatecache(cs, idx));  /* get folding function */-    lua_insert(L, -2);  /* put it before accumulator */-    n = pushcapture(cs);  /* get next capture's values */-    lua_call(L, n + 1, 1);  /* call folding function */-  }-  cs->cap++;  /* skip close entry */-  return 1;  /* only accumulator left on the stack */-}---/*-** Function capture-*/-static int functioncap (CapState *cs) {-  int n;-  int top = lua_gettop(cs->L);-  pushluaval(cs);  /* push function */-  n = pushnestedvalues(cs, 0);  /* push nested captures */-  lua_call(cs->L, n, LUA_MULTRET);  /* call function */-  return lua_gettop(cs->L) - top;  /* return function's results */-}---/*-** Select capture-*/-static int numcap (CapState *cs) {-  int idx = cs->cap->idx;  /* value to select */-  if (idx == 0) {  /* no values? */-    nextcap(cs);  /* skip entire capture */-    return 0;  /* no value produced */-  }-  else {-    int n = pushnestedvalues(cs, 0);-    if (n < idx)  /* invalid index? */-      return luaL_error(cs->L, "no capture '%d'", idx);-    else {-      lua_pushvalue(cs->L, -(n - idx + 1));  /* get selected capture */-      lua_replace(cs->L, -(n + 1));  /* put it in place of 1st capture */-      lua_pop(cs->L, n - 1);  /* remove other captures */-      return 1;-    }-  }-}---/*-** Return the stack index of the first runtime capture in the given-** list of captures (or zero if no runtime captures)-*/-int finddyncap (Capture *cap, Capture *last) {-  for (; cap < last; cap++) {-    if (cap->kind == Cruntime)-      return cap->idx;  /* stack position of first capture */-  }-  return 0;  /* no dynamic captures in this segment */-}---/*-** Calls a runtime capture. Returns number of captures "removed" by the-** call, that is, those inside the group capture. Captures to be added-** are on the Lua stack.-*/-int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {-  int n, id;-  lua_State *L = cs->L;-  int otop = lua_gettop(L);-  Capture *open = findopen(close);  /* get open group capture */-  assert(captype(open) == Cgroup);-  id = finddyncap(open, close);  /* get first dynamic capture argument */-  close->kind = Cclose;  /* closes the group */-  close->s = s;-  cs->cap = open; cs->valuecached = 0;  /* prepare capture state */-  luaL_checkstack(L, 4, "too many runtime captures");-  pushluaval(cs);  /* push function to be called */-  lua_pushvalue(L, SUBJIDX);  /* push original subject */-  lua_pushinteger(L, s - cs->s + 1);  /* push current position */-  n = pushnestedvalues(cs, 0);  /* push nested captures */-  lua_call(L, n + 2, LUA_MULTRET);  /* call dynamic function */-  if (id > 0) {  /* are there old dynamic captures to be removed? */-    int i;-    for (i = id; i <= otop; i++)-      lua_remove(L, id);  /* remove old dynamic captures */-    *rem = otop - id + 1;  /* total number of dynamic captures removed */-  }-  else-    *rem = 0;  /* no dynamic captures removed */-  return close - open - 1;  /* number of captures to be removed */-}---/*-** Auxiliary structure for substitution and string captures: keep-** information about nested captures for future use, avoiding to push-** string results into Lua-*/-typedef struct StrAux {-  int isstring;  /* whether capture is a string */-  union {-    Capture *cp;  /* if not a string, respective capture */-    struct {  /* if it is a string... */-      const char *s;  /* ... starts here */-      const char *e;  /* ... ends here */-    } s;-  } u;-} StrAux;--#define MAXSTRCAPS	10--/*-** Collect values from current capture into array 'cps'. Current-** capture must be Cstring (first call) or Csimple (recursive calls).-** (In first call, fills %0 with whole match for Cstring.)-** Returns number of elements in the array that were filled.-*/-static int getstrcaps (CapState *cs, StrAux *cps, int n) {-  int k = n++;-  cps[k].isstring = 1;  /* get string value */-  cps[k].u.s.s = cs->cap->s;  /* starts here */-  if (!isfullcap(cs->cap++)) {  /* nested captures? */-    while (!isclosecap(cs->cap)) {  /* traverse them */-      if (n >= MAXSTRCAPS)  /* too many captures? */-        nextcap(cs);  /* skip extra captures (will not need them) */-      else if (captype(cs->cap) == Csimple)  /* string? */-        n = getstrcaps(cs, cps, n);  /* put info. into array */-      else {-        cps[n].isstring = 0;  /* not a string */-        cps[n].u.cp = cs->cap;  /* keep original capture */-        nextcap(cs);-        n++;-      }-    }-    cs->cap++;  /* skip close */-  }-  cps[k].u.s.e = closeaddr(cs->cap - 1);  /* ends here */-  return n;-}---/*-** add next capture value (which should be a string) to buffer 'b'-*/-static int addonestring (luaL_Buffer *b, CapState *cs, const char *what);---/*-** String capture: add result to buffer 'b' (instead of pushing-** it into the stack)-*/-static void stringcap (luaL_Buffer *b, CapState *cs) {-  StrAux cps[MAXSTRCAPS];-  int n;-  size_t len, i;-  const char *fmt;  /* format string */-  fmt = lua_tolstring(cs->L, updatecache(cs, cs->cap->idx), &len);-  n = getstrcaps(cs, cps, 0) - 1;  /* collect nested captures */-  for (i = 0; i < len; i++) {  /* traverse them */-    if (fmt[i] != '%')  /* not an escape? */-      luaL_addchar(b, fmt[i]);  /* add it to buffer */-    else if (fmt[++i] < '0' || fmt[i] > '9')  /* not followed by a digit? */-      luaL_addchar(b, fmt[i]);  /* add to buffer */-    else {-      int l = fmt[i] - '0';  /* capture index */-      if (l > n)-        luaL_error(cs->L, "invalid capture index (%d)", l);-      else if (cps[l].isstring)-        luaL_addlstring(b, cps[l].u.s.s, cps[l].u.s.e - cps[l].u.s.s);-      else {-        Capture *curr = cs->cap;-        cs->cap = cps[l].u.cp;  /* go back to evaluate that nested capture */-        if (!addonestring(b, cs, "capture"))-          luaL_error(cs->L, "no values in capture index %d", l);-        cs->cap = curr;  /* continue from where it stopped */-      }-    }-  }-}---/*-** Substitution capture: add result to buffer 'b'-*/-static void substcap (luaL_Buffer *b, CapState *cs) {-  const char *curr = cs->cap->s;-  if (isfullcap(cs->cap))  /* no nested captures? */-    luaL_addlstring(b, curr, cs->cap->siz - 1);  /* keep original text */-  else {-    cs->cap++;  /* skip open entry */-    while (!isclosecap(cs->cap)) {  /* traverse nested captures */-      const char *next = cs->cap->s;-      luaL_addlstring(b, curr, next - curr);  /* add text up to capture */-      if (addonestring(b, cs, "replacement"))-        curr = closeaddr(cs->cap - 1);  /* continue after match */-      else  /* no capture value */-        curr = next;  /* keep original text in final result */-    }-    luaL_addlstring(b, curr, cs->cap->s - curr);  /* add last piece of text */-  }-  cs->cap++;  /* go to next capture */-}---/*-** Evaluates a capture and adds its first value to buffer 'b'; returns-** whether there was a value-*/-static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) {-  switch (captype(cs->cap)) {-    case Cstring:-      stringcap(b, cs);  /* add capture directly to buffer */-      return 1;-    case Csubst:-      substcap(b, cs);  /* add capture directly to buffer */-      return 1;-    default: {-      lua_State *L = cs->L;-      int n = pushcapture(cs);-      if (n > 0) {-        if (n > 1) lua_pop(L, n - 1);  /* only one result */-        if (!lua_isstring(L, -1))-          luaL_error(L, "invalid %s value (a %s)", what, luaL_typename(L, -1));-        luaL_addvalue(b);-      }-      return n;-    }-  }-}---#if !defined(MAXRECLEVEL)-#define MAXRECLEVEL	200-#endif---/*-** Push all values of the current capture into the stack; returns-** number of values pushed-*/-static int pushcapture (CapState *cs) {-  lua_State *L = cs->L;-  int res;-  luaL_checkstack(L, 4, "too many captures");-  if (cs->reclevel++ > MAXRECLEVEL)-    return luaL_error(L, "subcapture nesting too deep");-  switch (captype(cs->cap)) {-    case Cposition: {-      lua_pushinteger(L, cs->cap->s - cs->s + 1);-      cs->cap++;-      res = 1;-      break;-    }-    case Cconst: {-      pushluaval(cs);-      cs->cap++;-      res = 1;-      break;-    }-    case Carg: {-      int arg = (cs->cap++)->idx;-      if (arg + FIXEDARGS > cs->ptop)-        return luaL_error(L, "reference to absent extra argument #%d", arg);-      lua_pushvalue(L, arg + FIXEDARGS);-      res = 1;-      break;-    }-    case Csimple: {-      int k = pushnestedvalues(cs, 1);-      lua_insert(L, -k);  /* make whole match be first result */-      res = k;-      break;-    }-    case Cruntime: {-      lua_pushvalue(L, (cs->cap++)->idx);  /* value is in the stack */-      res = 1;-      break;-    }-    case Cstring: {-      luaL_Buffer b;-      luaL_buffinit(L, &b);-      stringcap(&b, cs);-      luaL_pushresult(&b);-      res = 1;-      break;-    }-    case Csubst: {-      luaL_Buffer b;-      luaL_buffinit(L, &b);-      substcap(&b, cs);-      luaL_pushresult(&b);-      res = 1;-      break;-    }-    case Cgroup: {-      if (cs->cap->idx == 0)  /* anonymous group? */-        res = pushnestedvalues(cs, 0);  /* add all nested values */-      else {  /* named group: add no values */-        nextcap(cs);  /* skip capture */-        res = 0;-      }-      break;-    }-    case Cbackref: res = backrefcap(cs); break;-    case Ctable: res = tablecap(cs); break;-    case Cfunction: res = functioncap(cs); break;-    case Cnum: res = numcap(cs); break;-    case Cquery: res = querycap(cs); break;-    case Cfold: res = foldcap(cs); break;-    default: assert(0); res = 0;-  }-  cs->reclevel--;-  return res;-}---/*-** Prepare a CapState structure and traverse the entire list of-** captures in the stack pushing its results. 's' is the subject-** string, 'r' is the final position of the match, and 'ptop' -** the index in the stack where some useful values were pushed.-** Returns the number of results pushed. (If the list produces no-** results, push the final position of the match.)-*/-int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {-  Capture *capture = (Capture *)lua_touserdata(L, caplistidx(ptop));-  int n = 0;-  if (!isclosecap(capture)) {  /* is there any capture? */-    CapState cs;-    cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0;-    cs.s = s; cs.valuecached = 0; cs.ptop = ptop;-    do {  /* collect their values */-      n += pushcapture(&cs);-    } while (!isclosecap(cs.cap));-  }-  if (n == 0) {  /* no capture values? */-    lua_pushinteger(L, r - s + 1);  /* return only end position */-    n = 1;-  }-  return n;-}--
− cbits/lpeg-1.0.2/lpcap.h
@@ -1,57 +0,0 @@-/*-** $Id: lpcap.h $-*/--#if !defined(lpcap_h)-#define lpcap_h---#include "lptypes.h"---/* kinds of captures */-typedef enum CapKind {-  Cclose,  /* not used in trees */-  Cposition,-  Cconst,  /* ktable[key] is Lua constant */-  Cbackref,  /* ktable[key] is "name" of group to get capture */-  Carg,  /* 'key' is arg's number */-  Csimple,  /* next node is pattern */-  Ctable,  /* next node is pattern */-  Cfunction,  /* ktable[key] is function; next node is pattern */-  Cquery,  /* ktable[key] is table; next node is pattern */-  Cstring,  /* ktable[key] is string; next node is pattern */-  Cnum,  /* numbered capture; 'key' is number of value to return */-  Csubst,  /* substitution capture; next node is pattern */-  Cfold,  /* ktable[key] is function; next node is pattern */-  Cruntime,  /* not used in trees (is uses another type for tree) */-  Cgroup  /* ktable[key] is group's "name" */-} CapKind;---typedef struct Capture {-  const char *s;  /* subject position */-  unsigned short idx;  /* extra info (group name, arg index, etc.) */-  byte kind;  /* kind of capture */-  byte siz;  /* size of full capture + 1 (0 = not a full capture) */-} Capture;---typedef struct CapState {-  Capture *cap;  /* current capture */-  Capture *ocap;  /* (original) capture list */-  lua_State *L;-  int ptop;  /* index of last argument to 'match' */-  const char *s;  /* original string */-  int valuecached;  /* value stored in cache slot */-  int reclevel;  /* recursion level */-} CapState;---int runtimecap (CapState *cs, Capture *close, const char *s, int *rem);-int getcaptures (lua_State *L, const char *s, const char *r, int ptop);-int finddyncap (Capture *cap, Capture *last);--#endif--
− cbits/lpeg-1.0.2/lpcode.c
@@ -1,1014 +0,0 @@-/*-** $Id: lpcode.c $-** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-*/--#include <limits.h>---#include "lua.h"-#include "lauxlib.h"--#include "lptypes.h"-#include "lpcode.h"---/* signals a "no-instruction */-#define NOINST		-1----static const Charset fullset_ =-  {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};--static const Charset *fullset = &fullset_;--/*-** {======================================================-** Analysis and some optimizations-** =======================================================-*/--/*-** Check whether a charset is empty (returns IFail), singleton (IChar),-** full (IAny), or none of those (ISet). When singleton, '*c' returns-** which character it is. (When generic set, the set was the input,-** so there is no need to return it.)-*/-static Opcode charsettype (const byte *cs, int *c) {-  int count = 0;  /* number of characters in the set */-  int i;-  int candidate = -1;  /* candidate position for the singleton char */-  for (i = 0; i < CHARSETSIZE; i++) {  /* for each byte */-    int b = cs[i];-    if (b == 0) {  /* is byte empty? */-      if (count > 1)  /* was set neither empty nor singleton? */-        return ISet;  /* neither full nor empty nor singleton */-      /* else set is still empty or singleton */-    }-    else if (b == 0xFF) {  /* is byte full? */-      if (count < (i * BITSPERCHAR))  /* was set not full? */-        return ISet;  /* neither full nor empty nor singleton */-      else count += BITSPERCHAR;  /* set is still full */-    }-    else if ((b & (b - 1)) == 0) {  /* has byte only one bit? */-      if (count > 0)  /* was set not empty? */-        return ISet;  /* neither full nor empty nor singleton */-      else {  /* set has only one char till now; track it */-        count++;-        candidate = i;-      }-    }-    else return ISet;  /* byte is neither empty, full, nor singleton */-  }-  switch (count) {-    case 0: return IFail;  /* empty set */-    case 1: {  /* singleton; find character bit inside byte */-      int b = cs[candidate];-      *c = candidate * BITSPERCHAR;-      if ((b & 0xF0) != 0) { *c += 4; b >>= 4; }-      if ((b & 0x0C) != 0) { *c += 2; b >>= 2; }-      if ((b & 0x02) != 0) { *c += 1; }-      return IChar;-    }-    default: {-       assert(count == CHARSETSIZE * BITSPERCHAR);  /* full set */-       return IAny;-    }-  }-}---/*-** A few basic operations on Charsets-*/-static void cs_complement (Charset *cs) {-  loopset(i, cs->cs[i] = ~cs->cs[i]);-}--static int cs_equal (const byte *cs1, const byte *cs2) {-  loopset(i, if (cs1[i] != cs2[i]) return 0);-  return 1;-}--static int cs_disjoint (const Charset *cs1, const Charset *cs2) {-  loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;)-  return 1;-}---/*-** If 'tree' is a 'char' pattern (TSet, TChar, TAny), convert it into a-** charset and return 1; else return 0.-*/-int tocharset (TTree *tree, Charset *cs) {-  switch (tree->tag) {-    case TSet: {  /* copy set */-      loopset(i, cs->cs[i] = treebuffer(tree)[i]);-      return 1;-    }-    case TChar: {  /* only one char */-      assert(0 <= tree->u.n && tree->u.n <= UCHAR_MAX);-      loopset(i, cs->cs[i] = 0);  /* erase all chars */-      setchar(cs->cs, tree->u.n);  /* add that one */-      return 1;-    }-    case TAny: {-      loopset(i, cs->cs[i] = 0xFF);  /* add all characters to the set */-      return 1;-    }-    default: return 0;-  }-}---/*-** Visit a TCall node taking care to stop recursion. If node not yet-** visited, return 'f(sib2(tree))', otherwise return 'def' (default-** value)-*/-static int callrecursive (TTree *tree, int f (TTree *t), int def) {-  int key = tree->key;-  assert(tree->tag == TCall);-  assert(sib2(tree)->tag == TRule);-  if (key == 0)  /* node already visited? */-    return def;  /* return default value */-  else {  /* first visit */-    int result;-    tree->key = 0;  /* mark call as already visited */-    result = f(sib2(tree));  /* go to called rule */-    tree->key = key;  /* restore tree */-    return result;-  }-}---/*-** Check whether a pattern tree has captures-*/-int hascaptures (TTree *tree) {- tailcall:-  switch (tree->tag) {-    case TCapture: case TRunTime:-      return 1;-    case TCall:-      return callrecursive(tree, hascaptures, 0);-    case TRule:  /* do not follow siblings */-      tree = sib1(tree); goto tailcall;-    case TOpenCall: assert(0);-    default: {-      switch (numsiblings[tree->tag]) {-        case 1:  /* return hascaptures(sib1(tree)); */-          tree = sib1(tree); goto tailcall;-        case 2:-          if (hascaptures(sib1(tree)))-            return 1;-          /* else return hascaptures(sib2(tree)); */-          tree = sib2(tree); goto tailcall;-        default: assert(numsiblings[tree->tag] == 0); return 0;-      }-    }-  }-}---/*-** Checks how a pattern behaves regarding the empty string,-** in one of two different ways:-** A pattern is *nullable* if it can match without consuming any character;-** A pattern is *nofail* if it never fails for any string-** (including the empty string).-** The difference is only for predicates and run-time captures;-** for other patterns, the two properties are equivalent.-** (With predicates, &'a' is nullable but not nofail. Of course,-** nofail => nullable.)-** These functions are all convervative in the following way:-**    p is nullable => nullable(p)-**    nofail(p) => p cannot fail-** The function assumes that TOpenCall is not nullable;-** this will be checked again when the grammar is fixed.-** Run-time captures can do whatever they want, so the result-** is conservative.-*/-int checkaux (TTree *tree, int pred) {- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny:-    case TFalse: case TOpenCall:-      return 0;  /* not nullable */-    case TRep: case TTrue:-      return 1;  /* no fail */-    case TNot: case TBehind:  /* can match empty, but can fail */-      if (pred == PEnofail) return 0;-      else return 1;  /* PEnullable */-    case TAnd:  /* can match empty; fail iff body does */-      if (pred == PEnullable) return 1;-      /* else return checkaux(sib1(tree), pred); */-      tree = sib1(tree); goto tailcall;-    case TRunTime:  /* can fail; match empty iff body does */-      if (pred == PEnofail) return 0;-      /* else return checkaux(sib1(tree), pred); */-      tree = sib1(tree); goto tailcall;-    case TSeq:-      if (!checkaux(sib1(tree), pred)) return 0;-      /* else return checkaux(sib2(tree), pred); */-      tree = sib2(tree); goto tailcall;-    case TChoice:-      if (checkaux(sib2(tree), pred)) return 1;-      /* else return checkaux(sib1(tree), pred); */-      tree = sib1(tree); goto tailcall;-    case TCapture: case TGrammar: case TRule:-      /* return checkaux(sib1(tree), pred); */-      tree = sib1(tree); goto tailcall;-    case TCall:  /* return checkaux(sib2(tree), pred); */-      tree = sib2(tree); goto tailcall;-    default: assert(0); return 0;-  }-}---/*-** number of characters to match a pattern (or -1 if variable)-*/-int fixedlen (TTree *tree) {-  int len = 0;  /* to accumulate in tail calls */- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny:-      return len + 1;-    case TFalse: case TTrue: case TNot: case TAnd: case TBehind:-      return len;-    case TRep: case TRunTime: case TOpenCall:-      return -1;-    case TCapture: case TRule: case TGrammar:-      /* return fixedlen(sib1(tree)); */-      tree = sib1(tree); goto tailcall;-    case TCall: {-      int n1 = callrecursive(tree, fixedlen, -1);-      if (n1 < 0)-        return -1;-      else-        return len + n1;-    }-    case TSeq: {-      int n1 = fixedlen(sib1(tree));-      if (n1 < 0)-        return -1;-      /* else return fixedlen(sib2(tree)) + len; */-      len += n1; tree = sib2(tree); goto tailcall;-    }-    case TChoice: {-      int n1 = fixedlen(sib1(tree));-      int n2 = fixedlen(sib2(tree));-      if (n1 != n2 || n1 < 0)-        return -1;-      else-        return len + n1;-    }-    default: assert(0); return 0;-  };-}---/*-** Computes the 'first set' of a pattern.-** The result is a conservative aproximation:-**   match p ax -> x (for some x) ==> a belongs to first(p)-** or-**   a not in first(p) ==> match p ax -> fail (for all x)-**-** The set 'follow' is the first set of what follows the-** pattern (full set if nothing follows it).-**-** The function returns 0 when this resulting set can be used for-** test instructions that avoid the pattern altogether.-** A non-zero return can happen for two reasons:-** 1) match p '' -> ''            ==> return has bit 1 set-** (tests cannot be used because they would always fail for an empty input);-** 2) there is a match-time capture ==> return has bit 2 set-** (optimizations should not bypass match-time captures).-*/-static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny: {-      tocharset(tree, firstset);-      return 0;-    }-    case TTrue: {-      loopset(i, firstset->cs[i] = follow->cs[i]);-      return 1;  /* accepts the empty string */-    }-    case TFalse: {-      loopset(i, firstset->cs[i] = 0);-      return 0;-    }-    case TChoice: {-      Charset csaux;-      int e1 = getfirst(sib1(tree), follow, firstset);-      int e2 = getfirst(sib2(tree), follow, &csaux);-      loopset(i, firstset->cs[i] |= csaux.cs[i]);-      return e1 | e2;-    }-    case TSeq: {-      if (!nullable(sib1(tree))) {-        /* when p1 is not nullable, p2 has nothing to contribute;-           return getfirst(sib1(tree), fullset, firstset); */-        tree = sib1(tree); follow = fullset; goto tailcall;-      }-      else {  /* FIRST(p1 p2, fl) = FIRST(p1, FIRST(p2, fl)) */-        Charset csaux;-        int e2 = getfirst(sib2(tree), follow, &csaux);-        int e1 = getfirst(sib1(tree), &csaux, firstset);-        if (e1 == 0) return 0;  /* 'e1' ensures that first can be used */-        else if ((e1 | e2) & 2)  /* one of the children has a matchtime? */-          return 2;  /* pattern has a matchtime capture */-        else return e2;  /* else depends on 'e2' */-      }-    }-    case TRep: {-      getfirst(sib1(tree), follow, firstset);-      loopset(i, firstset->cs[i] |= follow->cs[i]);-      return 1;  /* accept the empty string */-    }-    case TCapture: case TGrammar: case TRule: {-      /* return getfirst(sib1(tree), follow, firstset); */-      tree = sib1(tree); goto tailcall;-    }-    case TRunTime: {  /* function invalidates any follow info. */-      int e = getfirst(sib1(tree), fullset, firstset);-      if (e) return 2;  /* function is not "protected"? */-      else return 0;  /* pattern inside capture ensures first can be used */-    }-    case TCall: {-      /* return getfirst(sib2(tree), follow, firstset); */-      tree = sib2(tree); goto tailcall;-    }-    case TAnd: {-      int e = getfirst(sib1(tree), follow, firstset);-      loopset(i, firstset->cs[i] &= follow->cs[i]);-      return e;-    }-    case TNot: {-      if (tocharset(sib1(tree), firstset)) {-        cs_complement(firstset);-        return 1;-      }-      /* else go through */-    }-    case TBehind: {  /* instruction gives no new information */-      /* call 'getfirst' only to check for math-time captures */-      int e = getfirst(sib1(tree), follow, firstset);-      loopset(i, firstset->cs[i] = follow->cs[i]);  /* uses follow */-      return e | 1;  /* always can accept the empty string */-    }-    default: assert(0); return 0;-  }-}---/*-** If 'headfail(tree)' true, then 'tree' can fail only depending on the-** next character of the subject.-*/-static int headfail (TTree *tree) {- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny: case TFalse:-      return 1;-    case TTrue: case TRep: case TRunTime: case TNot:-    case TBehind:-      return 0;-    case TCapture: case TGrammar: case TRule: case TAnd:-      tree = sib1(tree); goto tailcall;  /* return headfail(sib1(tree)); */-    case TCall:-      tree = sib2(tree); goto tailcall;  /* return headfail(sib2(tree)); */-    case TSeq:-      if (!nofail(sib2(tree))) return 0;-      /* else return headfail(sib1(tree)); */-      tree = sib1(tree); goto tailcall;-    case TChoice:-      if (!headfail(sib1(tree))) return 0;-      /* else return headfail(sib2(tree)); */-      tree = sib2(tree); goto tailcall;-    default: assert(0); return 0;-  }-}---/*-** Check whether the code generation for the given tree can benefit-** from a follow set (to avoid computing the follow set when it is-** not needed)-*/-static int needfollow (TTree *tree) {- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny:-    case TFalse: case TTrue: case TAnd: case TNot:-    case TRunTime: case TGrammar: case TCall: case TBehind:-      return 0;-    case TChoice: case TRep:-      return 1;-    case TCapture:-      tree = sib1(tree); goto tailcall;-    case TSeq:-      tree = sib2(tree); goto tailcall;-    default: assert(0); return 0;-  } -}--/* }====================================================== */----/*-** {======================================================-** Code generation-** =======================================================-*/---/*-** size of an instruction-*/-int sizei (const Instruction *i) {-  switch((Opcode)i->i.code) {-    case ISet: case ISpan: return CHARSETINSTSIZE;-    case ITestSet: return CHARSETINSTSIZE + 1;-    case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall:-    case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit:-      return 2;-    default: return 1;-  }-}---/*-** state for the compiler-*/-typedef struct CompileState {-  Pattern *p;  /* pattern being compiled */-  int ncode;  /* next position in p->code to be filled */-  lua_State *L;-} CompileState;---/*-** code generation is recursive; 'opt' indicates that the code is being-** generated as the last thing inside an optional pattern (so, if that-** code is optional too, it can reuse the 'IChoice' already in place for-** the outer pattern). 'tt' points to a previous test protecting this-** code (or NOINST). 'fl' is the follow set of the pattern.-*/-static void codegen (CompileState *compst, TTree *tree, int opt, int tt,-                     const Charset *fl);---void realloccode (lua_State *L, Pattern *p, int nsize) {-  void *ud;-  lua_Alloc f = lua_getallocf(L, &ud);-  void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction),-                                  nsize * sizeof(Instruction));-  if (newblock == NULL && nsize > 0)-    luaL_error(L, "not enough memory");-  p->code = (Instruction *)newblock;-  p->codesize = nsize;-}---static int nextinstruction (CompileState *compst) {-  int size = compst->p->codesize;-  if (compst->ncode >= size)-    realloccode(compst->L, compst->p, size * 2);-  return compst->ncode++;-}---#define getinstr(cs,i)		((cs)->p->code[i])---static int addinstruction (CompileState *compst, Opcode op, int aux) {-  int i = nextinstruction(compst);-  getinstr(compst, i).i.code = op;-  getinstr(compst, i).i.aux = aux;-  return i;-}---/*-** Add an instruction followed by space for an offset (to be set later)-*/-static int addoffsetinst (CompileState *compst, Opcode op) {-  int i = addinstruction(compst, op, 0);  /* instruction */-  addinstruction(compst, (Opcode)0, 0);  /* open space for offset */-  assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2);-  return i;-}---/*-** Set the offset of an instruction-*/-static void setoffset (CompileState *compst, int instruction, int offset) {-  getinstr(compst, instruction + 1).offset = offset;-}---/*-** Add a capture instruction:-** 'op' is the capture instruction; 'cap' the capture kind;-** 'key' the key into ktable; 'aux' is the optional capture offset-**-*/-static int addinstcap (CompileState *compst, Opcode op, int cap, int key,-                       int aux) {-  int i = addinstruction(compst, op, joinkindoff(cap, aux));-  getinstr(compst, i).i.key = key;-  return i;-}---#define gethere(compst) 	((compst)->ncode)--#define target(code,i)		((i) + code[i + 1].offset)---/*-** Patch 'instruction' to jump to 'target'-*/-static void jumptothere (CompileState *compst, int instruction, int target) {-  if (instruction >= 0)-    setoffset(compst, instruction, target - instruction);-}---/*-** Patch 'instruction' to jump to current position-*/-static void jumptohere (CompileState *compst, int instruction) {-  jumptothere(compst, instruction, gethere(compst));-}---/*-** Code an IChar instruction, or IAny if there is an equivalent-** test dominating it-*/-static void codechar (CompileState *compst, int c, int tt) {-  if (tt >= 0 && getinstr(compst, tt).i.code == ITestChar &&-                 getinstr(compst, tt).i.aux == c)-    addinstruction(compst, IAny, 0);-  else-    addinstruction(compst, IChar, c);-}---/*-** Add a charset posfix to an instruction-*/-static void addcharset (CompileState *compst, const byte *cs) {-  int p = gethere(compst);-  int i;-  for (i = 0; i < (int)CHARSETINSTSIZE - 1; i++)-    nextinstruction(compst);  /* space for buffer */-  /* fill buffer with charset */-  loopset(j, getinstr(compst, p).buff[j] = cs[j]);-}---/*-** code a char set, optimizing unit sets for IChar, "complete"-** sets for IAny, and empty sets for IFail; also use an IAny-** when instruction is dominated by an equivalent test.-*/-static void codecharset (CompileState *compst, const byte *cs, int tt) {-  int c = 0;  /* (=) to avoid warnings */-  Opcode op = charsettype(cs, &c);-  switch (op) {-    case IChar: codechar(compst, c, tt); break;-    case ISet: {  /* non-trivial set? */-      if (tt >= 0 && getinstr(compst, tt).i.code == ITestSet &&-          cs_equal(cs, getinstr(compst, tt + 2).buff))-        addinstruction(compst, IAny, 0);-      else {-        addinstruction(compst, ISet, 0);-        addcharset(compst, cs);-      }-      break;-    }-    default: addinstruction(compst, op, c); break;-  }-}---/*-** code a test set, optimizing unit sets for ITestChar, "complete"-** sets for ITestAny, and empty sets for IJmp (always fails).-** 'e' is true iff test should accept the empty string. (Test-** instructions in the current VM never accept the empty string.)-*/-static int codetestset (CompileState *compst, Charset *cs, int e) {-  if (e) return NOINST;  /* no test */-  else {-    int c = 0;-    Opcode op = charsettype(cs->cs, &c);-    switch (op) {-      case IFail: return addoffsetinst(compst, IJmp);  /* always jump */-      case IAny: return addoffsetinst(compst, ITestAny);-      case IChar: {-        int i = addoffsetinst(compst, ITestChar);-        getinstr(compst, i).i.aux = c;-        return i;-      }-      case ISet: {-        int i = addoffsetinst(compst, ITestSet);-        addcharset(compst, cs->cs);-        return i;-      }-      default: assert(0); return 0;-    }-  }-}---/*-** Find the final destination of a sequence of jumps-*/-static int finaltarget (Instruction *code, int i) {-  while (code[i].i.code == IJmp)-    i = target(code, i);-  return i;-}---/*-** final label (after traversing any jumps)-*/-static int finallabel (Instruction *code, int i) {-  return finaltarget(code, target(code, i));-}---/*-** <behind(p)> == behind n; <p>   (where n = fixedlen(p))-*/-static void codebehind (CompileState *compst, TTree *tree) {-  if (tree->u.n > 0)-    addinstruction(compst, IBehind, tree->u.n);-  codegen(compst, sib1(tree), 0, NOINST, fullset);-}---/*-** Choice; optimizations:-** - when p1 is headfail or-** when first(p1) and first(p2) are disjoint, than-** a character not in first(p1) cannot go to p1, and a character-** in first(p1) cannot go to p2 (at it is not in first(p2)).-** (The optimization is not valid if p1 accepts the empty string,-** as then there is no character at all...)-** - when p2 is empty and opt is true; a IPartialCommit can reuse-** the Choice already active in the stack.-*/-static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,-                        const Charset *fl) {-  int emptyp2 = (p2->tag == TTrue);-  Charset cs1, cs2;-  int e1 = getfirst(p1, fullset, &cs1);-  if (headfail(p1) ||-      (!e1 && (getfirst(p2, fl, &cs2), cs_disjoint(&cs1, &cs2)))) {-    /* <p1 / p2> == test (fail(p1)) -> L1 ; p1 ; jmp L2; L1: p2; L2: */-    int test = codetestset(compst, &cs1, 0);-    int jmp = NOINST;-    codegen(compst, p1, 0, test, fl);-    if (!emptyp2)-      jmp = addoffsetinst(compst, IJmp); -    jumptohere(compst, test);-    codegen(compst, p2, opt, NOINST, fl);-    jumptohere(compst, jmp);-  }-  else if (opt && emptyp2) {-    /* p1? == IPartialCommit; p1 */-    jumptohere(compst, addoffsetinst(compst, IPartialCommit));-    codegen(compst, p1, 1, NOINST, fullset);-  }-  else {-    /* <p1 / p2> == -        test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */-    int pcommit;-    int test = codetestset(compst, &cs1, e1);-    int pchoice = addoffsetinst(compst, IChoice);-    codegen(compst, p1, emptyp2, test, fullset);-    pcommit = addoffsetinst(compst, ICommit);-    jumptohere(compst, pchoice);-    jumptohere(compst, test);-    codegen(compst, p2, opt, NOINST, fl);-    jumptohere(compst, pcommit);-  }-}---/*-** And predicate-** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n-** (valid only when 'p' has no captures)-*/-static void codeand (CompileState *compst, TTree *tree, int tt) {-  int n = fixedlen(tree);-  if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) {-    codegen(compst, tree, 0, tt, fullset);-    if (n > 0)-      addinstruction(compst, IBehind, n);-  }-  else {  /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */-    int pcommit;-    int pchoice = addoffsetinst(compst, IChoice);-    codegen(compst, tree, 0, tt, fullset);-    pcommit = addoffsetinst(compst, IBackCommit);-    jumptohere(compst, pchoice);-    addinstruction(compst, IFail, 0);-    jumptohere(compst, pcommit);-  }-}---/*-** Captures: if pattern has fixed (and not too big) length, and it-** has no nested captures, use a single IFullCapture instruction-** after the match; otherwise, enclose the pattern with OpenCapture --** CloseCapture.-*/-static void codecapture (CompileState *compst, TTree *tree, int tt,-                         const Charset *fl) {-  int len = fixedlen(sib1(tree));-  if (len >= 0 && len <= MAXOFF && !hascaptures(sib1(tree))) {-    codegen(compst, sib1(tree), 0, tt, fl);-    addinstcap(compst, IFullCapture, tree->cap, tree->key, len);-  }-  else {-    addinstcap(compst, IOpenCapture, tree->cap, tree->key, 0);-    codegen(compst, sib1(tree), 0, tt, fl);-    addinstcap(compst, ICloseCapture, Cclose, 0, 0);-  }-}---static void coderuntime (CompileState *compst, TTree *tree, int tt) {-  addinstcap(compst, IOpenCapture, Cgroup, tree->key, 0);-  codegen(compst, sib1(tree), 0, tt, fullset);-  addinstcap(compst, ICloseRunTime, Cclose, 0, 0);-}---/*-** Repetion; optimizations:-** When pattern is a charset, can use special instruction ISpan.-** When pattern is head fail, or if it starts with characters that-** are disjoint from what follows the repetions, a simple test-** is enough (a fail inside the repetition would backtrack to fail-** again in the following pattern, so there is no need for a choice).-** When 'opt' is true, the repetion can reuse the Choice already-** active in the stack.-*/-static void coderep (CompileState *compst, TTree *tree, int opt,-                     const Charset *fl) {-  Charset st;-  if (tocharset(tree, &st)) {-    addinstruction(compst, ISpan, 0);-    addcharset(compst, st.cs);-  }-  else {-    int e1 = getfirst(tree, fullset, &st);-    if (headfail(tree) || (!e1 && cs_disjoint(&st, fl))) {-      /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */-      int jmp;-      int test = codetestset(compst, &st, 0);-      codegen(compst, tree, 0, test, fullset);-      jmp = addoffsetinst(compst, IJmp);-      jumptohere(compst, test);-      jumptothere(compst, jmp, test);-    }-    else {-      /* test(fail(p1)) -> L2; choice L2; L1: <p>; partialcommit L1; L2: */-      /* or (if 'opt'): partialcommit L1; L1: <p>; partialcommit L1; */-      int commit, l2;-      int test = codetestset(compst, &st, e1);-      int pchoice = NOINST;-      if (opt)-        jumptohere(compst, addoffsetinst(compst, IPartialCommit));-      else-        pchoice = addoffsetinst(compst, IChoice);-      l2 = gethere(compst);-      codegen(compst, tree, 0, NOINST, fullset);-      commit = addoffsetinst(compst, IPartialCommit);-      jumptothere(compst, commit, l2);-      jumptohere(compst, pchoice);-      jumptohere(compst, test);-    }-  }-}---/*-** Not predicate; optimizations:-** In any case, if first test fails, 'not' succeeds, so it can jump to-** the end. If pattern is headfail, that is all (it cannot fail-** in other parts); this case includes 'not' of simple sets. Otherwise,-** use the default code (a choice plus a failtwice).-*/-static void codenot (CompileState *compst, TTree *tree) {-  Charset st;-  int e = getfirst(tree, fullset, &st);-  int test = codetestset(compst, &st, e);-  if (headfail(tree))  /* test (fail(p1)) -> L1; fail; L1:  */-    addinstruction(compst, IFail, 0);-  else {-    /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1:  */-    int pchoice = addoffsetinst(compst, IChoice);-    codegen(compst, tree, 0, NOINST, fullset);-    addinstruction(compst, IFailTwice, 0);-    jumptohere(compst, pchoice);-  }-  jumptohere(compst, test);-}---/*-** change open calls to calls, using list 'positions' to find-** correct offsets; also optimize tail calls-*/-static void correctcalls (CompileState *compst, int *positions,-                          int from, int to) {-  int i;-  Instruction *code = compst->p->code;-  for (i = from; i < to; i += sizei(&code[i])) {-    if (code[i].i.code == IOpenCall) {-      int n = code[i].i.key;  /* rule number */-      int rule = positions[n];  /* rule position */-      assert(rule == from || code[rule - 1].i.code == IRet);-      if (code[finaltarget(code, i + 2)].i.code == IRet)  /* call; ret ? */-        code[i].i.code = IJmp;  /* tail call */-      else-        code[i].i.code = ICall;-      jumptothere(compst, i, rule);  /* call jumps to respective rule */-    }-  }-  assert(i == to);-}---/*-** Code for a grammar:-** call L1; jmp L2; L1: rule 1; ret; rule 2; ret; ...; L2:-*/-static void codegrammar (CompileState *compst, TTree *grammar) {-  int positions[MAXRULES];-  int rulenumber = 0;-  TTree *rule;-  int firstcall = addoffsetinst(compst, ICall);  /* call initial rule */-  int jumptoend = addoffsetinst(compst, IJmp);  /* jump to the end */-  int start = gethere(compst);  /* here starts the initial rule */-  jumptohere(compst, firstcall);-  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {-    positions[rulenumber++] = gethere(compst);  /* save rule position */-    codegen(compst, sib1(rule), 0, NOINST, fullset);  /* code rule */-    addinstruction(compst, IRet, 0);-  }-  assert(rule->tag == TTrue);-  jumptohere(compst, jumptoend);-  correctcalls(compst, positions, start, gethere(compst));-}---static void codecall (CompileState *compst, TTree *call) {-  int c = addoffsetinst(compst, IOpenCall);  /* to be corrected later */-  getinstr(compst, c).i.key = sib2(call)->cap;  /* rule number */-  assert(sib2(call)->tag == TRule);-}---/*-** Code first child of a sequence-** (second child is called in-place to allow tail call)-** Return 'tt' for second child-*/-static int codeseq1 (CompileState *compst, TTree *p1, TTree *p2,-                     int tt, const Charset *fl) {-  if (needfollow(p1)) {-    Charset fl1;-    getfirst(p2, fl, &fl1);  /* p1 follow is p2 first */-    codegen(compst, p1, 0, tt, &fl1);-  }-  else  /* use 'fullset' as follow */-    codegen(compst, p1, 0, tt, fullset);-  if (fixedlen(p1) != 0)  /* can 'p1' consume anything? */-    return  NOINST;  /* invalidate test */-  else return tt;  /* else 'tt' still protects sib2 */-}---/*-** Main code-generation function: dispatch to auxiliar functions-** according to kind of tree. ('needfollow' should return true-** only for consructions that use 'fl'.)-*/-static void codegen (CompileState *compst, TTree *tree, int opt, int tt,-                     const Charset *fl) {- tailcall:-  switch (tree->tag) {-    case TChar: codechar(compst, tree->u.n, tt); break;-    case TAny: addinstruction(compst, IAny, 0); break;-    case TSet: codecharset(compst, treebuffer(tree), tt); break;-    case TTrue: break;-    case TFalse: addinstruction(compst, IFail, 0); break;-    case TChoice: codechoice(compst, sib1(tree), sib2(tree), opt, fl); break;-    case TRep: coderep(compst, sib1(tree), opt, fl); break;-    case TBehind: codebehind(compst, tree); break;-    case TNot: codenot(compst, sib1(tree)); break;-    case TAnd: codeand(compst, sib1(tree), tt); break;-    case TCapture: codecapture(compst, tree, tt, fl); break;-    case TRunTime: coderuntime(compst, tree, tt); break;-    case TGrammar: codegrammar(compst, tree); break;-    case TCall: codecall(compst, tree); break;-    case TSeq: {-      tt = codeseq1(compst, sib1(tree), sib2(tree), tt, fl);  /* code 'p1' */-      /* codegen(compst, p2, opt, tt, fl); */-      tree = sib2(tree); goto tailcall;-    }-    default: assert(0);-  }-}---/*-** Optimize jumps and other jump-like instructions.-** * Update labels of instructions with labels to their final-** destinations (e.g., choice L1; ... L1: jmp L2: becomes-** choice L2)-** * Jumps to other instructions that do jumps become those-** instructions (e.g., jump to return becomes a return; jump-** to commit becomes a commit)-*/-static void peephole (CompileState *compst) {-  Instruction *code = compst->p->code;-  int i;-  for (i = 0; i < compst->ncode; i += sizei(&code[i])) {-   redo:-    switch (code[i].i.code) {-      case IChoice: case ICall: case ICommit: case IPartialCommit:-      case IBackCommit: case ITestChar: case ITestSet:-      case ITestAny: {  /* instructions with labels */-        jumptothere(compst, i, finallabel(code, i));  /* optimize label */-        break;-      }-      case IJmp: {-        int ft = finaltarget(code, i);-        switch (code[ft].i.code) {  /* jumping to what? */-          case IRet: case IFail: case IFailTwice:-          case IEnd: {  /* instructions with unconditional implicit jumps */-            code[i] = code[ft];  /* jump becomes that instruction */-            code[i + 1].i.code = IAny;  /* 'no-op' for target position */-            break;-          }-          case ICommit: case IPartialCommit:-          case IBackCommit: {  /* inst. with unconditional explicit jumps */-            int fft = finallabel(code, ft);-            code[i] = code[ft];  /* jump becomes that instruction... */-            jumptothere(compst, i, fft);  /* but must correct its offset */-            goto redo;  /* reoptimize its label */-          }-          default: {-            jumptothere(compst, i, ft);  /* optimize label */-            break;-          }-        }-        break;-      }-      default: break;-    }-  }-  assert(code[i - 1].i.code == IEnd);-}---/*-** Compile a pattern-*/-Instruction *compile (lua_State *L, Pattern *p) {-  CompileState compst;-  compst.p = p;  compst.ncode = 0;  compst.L = L;-  realloccode(L, p, 2);  /* minimum initial size */-  codegen(&compst, p->tree, 0, NOINST, fullset);-  addinstruction(&compst, IEnd, 0);-  realloccode(L, p, compst.ncode);  /* set final size */-  peephole(&compst);-  return p->code;-}---/* }====================================================== */-
− cbits/lpeg-1.0.2/lpcode.h
@@ -1,40 +0,0 @@-/*-** $Id: lpcode.h $-*/--#if !defined(lpcode_h)-#define lpcode_h--#include "lua.h"--#include "lptypes.h"-#include "lptree.h"-#include "lpvm.h"--int tocharset (TTree *tree, Charset *cs);-int checkaux (TTree *tree, int pred);-int fixedlen (TTree *tree);-int hascaptures (TTree *tree);-int lp_gc (lua_State *L);-Instruction *compile (lua_State *L, Pattern *p);-void realloccode (lua_State *L, Pattern *p, int nsize);-int sizei (const Instruction *i);---#define PEnullable      0-#define PEnofail        1--/*-** nofail(t) implies that 't' cannot fail with any input-*/-#define nofail(t)	checkaux(t, PEnofail)--/*-** (not nullable(t)) implies 't' cannot match without consuming-** something-*/-#define nullable(t)	checkaux(t, PEnullable)----#endif
− cbits/lpeg-1.0.2/lpprint.c
@@ -1,244 +0,0 @@-/*-** $Id: lpprint.c $-** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-*/--#include <ctype.h>-#include <limits.h>-#include <stdio.h>---#include "lptypes.h"-#include "lpprint.h"-#include "lpcode.h"---#if defined(LPEG_DEBUG)--/*-** {======================================================-** Printing patterns (for debugging)-** =======================================================-*/---void printcharset (const byte *st) {-  int i;-  printf("[");-  for (i = 0; i <= UCHAR_MAX; i++) {-    int first = i;-    while (testchar(st, i) && i <= UCHAR_MAX) i++;-    if (i - 1 == first)  /* unary range? */-      printf("(%02x)", first);-    else if (i - 1 > first)  /* non-empty range? */-      printf("(%02x-%02x)", first, i - 1);-  }-  printf("]");-}---static const char *capkind (int kind) {-  const char *const modes[] = {-    "close", "position", "constant", "backref",-    "argument", "simple", "table", "function",-    "query", "string", "num", "substitution", "fold",-    "runtime", "group"};-  return modes[kind];-}---static void printjmp (const Instruction *op, const Instruction *p) {-  printf("-> %d", (int)(p + (p + 1)->offset - op));-}---void printinst (const Instruction *op, const Instruction *p) {-  const char *const names[] = {-    "any", "char", "set",-    "testany", "testchar", "testset",-    "span", "behind",-    "ret", "end",-    "choice", "jmp", "call", "open_call",-    "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup",-     "fullcapture", "opencapture", "closecapture", "closeruntime"-  };-  printf("%02ld: %s ", (long)(p - op), names[p->i.code]);-  switch ((Opcode)p->i.code) {-    case IChar: {-      printf("'%c'", p->i.aux);-      break;-    }-    case ITestChar: {-      printf("'%c'", p->i.aux); printjmp(op, p);-      break;-    }-    case IFullCapture: {-      printf("%s (size = %d)  (idx = %d)",-             capkind(getkind(p)), getoff(p), p->i.key);-      break;-    }-    case IOpenCapture: {-      printf("%s (idx = %d)", capkind(getkind(p)), p->i.key);-      break;-    }-    case ISet: {-      printcharset((p+1)->buff);-      break;-    }-    case ITestSet: {-      printcharset((p+2)->buff); printjmp(op, p);-      break;-    }-    case ISpan: {-      printcharset((p+1)->buff);-      break;-    }-    case IOpenCall: {-      printf("-> %d", (p + 1)->offset);-      break;-    }-    case IBehind: {-      printf("%d", p->i.aux);-      break;-    }-    case IJmp: case ICall: case ICommit: case IChoice:-    case IPartialCommit: case IBackCommit: case ITestAny: {-      printjmp(op, p);-      break;-    }-    default: break;-  }-  printf("\n");-}---void printpatt (Instruction *p, int n) {-  Instruction *op = p;-  while (p < op + n) {-    printinst(op, p);-    p += sizei(p);-  }-}---#if defined(LPEG_DEBUG)-static void printcap (Capture *cap) {-  printf("%s (idx: %d - size: %d) -> %p\n",-         capkind(cap->kind), cap->idx, cap->siz, cap->s);-}---void printcaplist (Capture *cap, Capture *limit) {-  printf(">======\n");-  for (; cap->s && (limit == NULL || cap < limit); cap++)-    printcap(cap);-  printf("=======\n");-}-#endif--/* }====================================================== */---/*-** {======================================================-** Printing trees (for debugging)-** =======================================================-*/--static const char *tagnames[] = {-  "char", "set", "any",-  "true", "false",-  "rep",-  "seq", "choice",-  "not", "and",-  "call", "opencall", "rule", "grammar",-  "behind",-  "capture", "run-time"-};---void printtree (TTree *tree, int ident) {-  int i;-  for (i = 0; i < ident; i++) printf(" ");-  printf("%s", tagnames[tree->tag]);-  switch (tree->tag) {-    case TChar: {-      int c = tree->u.n;-      if (isprint(c))-        printf(" '%c'\n", c);-      else-        printf(" (%02X)\n", c);-      break;-    }-    case TSet: {-      printcharset(treebuffer(tree));-      printf("\n");-      break;-    }-    case TOpenCall: case TCall: {-      assert(sib2(tree)->tag == TRule);-      printf(" key: %d  (rule: %d)\n", tree->key, sib2(tree)->cap);-      break;-    }-    case TBehind: {-      printf(" %d\n", tree->u.n);-        printtree(sib1(tree), ident + 2);-      break;-    }-    case TCapture: {-      printf(" kind: '%s'  key: %d\n", capkind(tree->cap), tree->key);-      printtree(sib1(tree), ident + 2);-      break;-    }-    case TRule: {-      printf(" n: %d  key: %d\n", tree->cap, tree->key);-      printtree(sib1(tree), ident + 2);-      break;  /* do not print next rule as a sibling */-    }-    case TGrammar: {-      TTree *rule = sib1(tree);-      printf(" %d\n", tree->u.n);  /* number of rules */-      for (i = 0; i < tree->u.n; i++) {-        printtree(rule, ident + 2);-        rule = sib2(rule);-      }-      assert(rule->tag == TTrue);  /* sentinel */-      break;-    }-    default: {-      int sibs = numsiblings[tree->tag];-      printf("\n");-      if (sibs >= 1) {-        printtree(sib1(tree), ident + 2);-        if (sibs >= 2)-          printtree(sib2(tree), ident + 2);-      }-      break;-    }-  }-}---void printktable (lua_State *L, int idx) {-  int n, i;-  lua_getuservalue(L, idx);-  if (lua_isnil(L, -1))  /* no ktable? */-    return;-  n = lua_rawlen(L, -1);-  printf("[");-  for (i = 1; i <= n; i++) {-    printf("%d = ", i);-    lua_rawgeti(L, -1, i);-    if (lua_isstring(L, -1))-      printf("%s  ", lua_tostring(L, -1));-    else-      printf("%s  ", lua_typename(L, lua_type(L, -1)));-    lua_pop(L, 1);-  }-  printf("]\n");-  /* leave ktable at the stack */-}--/* }====================================================== */--#endif
− cbits/lpeg-1.0.2/lpprint.h
@@ -1,36 +0,0 @@-/*-** $Id: lpprint.h $-*/---#if !defined(lpprint_h)-#define lpprint_h---#include "lptree.h"-#include "lpvm.h"---#if defined(LPEG_DEBUG)--void printpatt (Instruction *p, int n);-void printtree (TTree *tree, int ident);-void printktable (lua_State *L, int idx);-void printcharset (const byte *st);-void printcaplist (Capture *cap, Capture *limit);-void printinst (const Instruction *op, const Instruction *p);--#else--#define printktable(L,idx)  \-	luaL_error(L, "function only implemented in debug mode")-#define printtree(tree,i)  \-	luaL_error(L, "function only implemented in debug mode")-#define printpatt(p,n)  \-	luaL_error(L, "function only implemented in debug mode")--#endif---#endif-
− cbits/lpeg-1.0.2/lptree.c
@@ -1,1305 +0,0 @@-/*-** $Id: lptree.c $-** Copyright 2013, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-*/--#include <ctype.h>-#include <limits.h>-#include <string.h>---#include "lua.h"-#include "lauxlib.h"--#include "lptypes.h"-#include "lpcap.h"-#include "lpcode.h"-#include "lpprint.h"-#include "lptree.h"---/* number of siblings for each tree */-const byte numsiblings[] = {-  0, 0, 0,	/* char, set, any */-  0, 0,		/* true, false */	-  1,		/* rep */-  2, 2,		/* seq, choice */-  1, 1,		/* not, and */-  0, 0, 2, 1,  /* call, opencall, rule, grammar */-  1,  /* behind */-  1, 1  /* capture, runtime capture */-};---static TTree *newgrammar (lua_State *L, int arg);---/*-** returns a reasonable name for value at index 'idx' on the stack-*/-static const char *val2str (lua_State *L, int idx) {-  const char *k = lua_tostring(L, idx);-  if (k != NULL)-    return lua_pushfstring(L, "%s", k);-  else-    return lua_pushfstring(L, "(a %s)", luaL_typename(L, idx));-}---/*-** Fix a TOpenCall into a TCall node, using table 'postable' to-** translate a key to its rule address in the tree. Raises an-** error if key does not exist.-*/-static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {-  int n;-  lua_rawgeti(L, -1, t->key);  /* get rule's name */-  lua_gettable(L, postable);  /* query name in position table */-  n = lua_tonumber(L, -1);  /* get (absolute) position */-  lua_pop(L, 1);  /* remove position */-  if (n == 0) {  /* no position? */-    lua_rawgeti(L, -1, t->key);  /* get rule's name again */-    luaL_error(L, "rule '%s' undefined in given grammar", val2str(L, -1));-  }-  t->tag = TCall;-  t->u.ps = n - (t - g);  /* position relative to node */-  assert(sib2(t)->tag == TRule);-  sib2(t)->key = t->key;  /* fix rule's key */-}---/*-** Transform left associative constructions into right-** associative ones, for sequence and choice; that is:-** (t11 + t12) + t2  =>  t11 + (t12 + t2)-** (t11 * t12) * t2  =>  t11 * (t12 * t2)-** (that is, Op (Op t11 t12) t2 => Op t11 (Op t12 t2))-*/-static void correctassociativity (TTree *tree) {-  TTree *t1 = sib1(tree);-  assert(tree->tag == TChoice || tree->tag == TSeq);-  while (t1->tag == tree->tag) {-    int n1size = tree->u.ps - 1;  /* t1 == Op t11 t12 */-    int n11size = t1->u.ps - 1;-    int n12size = n1size - n11size - 1;-    memmove(sib1(tree), sib1(t1), n11size * sizeof(TTree)); /* move t11 */-    tree->u.ps = n11size + 1;-    sib2(tree)->tag = tree->tag;-    sib2(tree)->u.ps = n12size + 1;-  }-}---/*-** Make final adjustments in a tree. Fix open calls in tree 't',-** making them refer to their respective rules or raising appropriate-** errors (if not inside a grammar). Correct associativity of associative-** constructions (making them right associative). Assume that tree's-** ktable is at the top of the stack (for error messages).-*/-static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {- tailcall:-  switch (t->tag) {-    case TGrammar:  /* subgrammars were already fixed */-      return;-    case TOpenCall: {-      if (g != NULL)  /* inside a grammar? */-        fixonecall(L, postable, g, t);-      else {  /* open call outside grammar */-        lua_rawgeti(L, -1, t->key);-        luaL_error(L, "rule '%s' used outside a grammar", val2str(L, -1));-      }-      break;-    }-    case TSeq: case TChoice:-      correctassociativity(t);-      break;-  }-  switch (numsiblings[t->tag]) {-    case 1: /* finalfix(L, postable, g, sib1(t)); */-      t = sib1(t); goto tailcall;-    case 2:-      finalfix(L, postable, g, sib1(t));-      t = sib2(t); goto tailcall;  /* finalfix(L, postable, g, sib2(t)); */-    default: assert(numsiblings[t->tag] == 0); break;-  }-}----/*-** {===================================================================-** KTable manipulation-**-** - The ktable of a pattern 'p' can be shared by other patterns that-** contain 'p' and no other constants. Because of this sharing, we-** should not add elements to a 'ktable' unless it was freshly created-** for the new pattern.-**-** - The maximum index in a ktable is USHRT_MAX, because trees and-** patterns use unsigned shorts to store those indices.-** ====================================================================-*/--/*-** Create a new 'ktable' to the pattern at the top of the stack.-*/-static void newktable (lua_State *L, int n) {-  lua_createtable(L, n, 0);  /* create a fresh table */-  lua_setuservalue(L, -2);  /* set it as 'ktable' for pattern */-}---/*-** Add element 'idx' to 'ktable' of pattern at the top of the stack;-** Return index of new element.-** If new element is nil, does not add it to table (as it would be-** useless) and returns 0, as ktable[0] is always nil.-*/-static int addtoktable (lua_State *L, int idx) {-  if (lua_isnil(L, idx))  /* nil value? */-    return 0;-  else {-    int n;-    lua_getuservalue(L, -1);  /* get ktable from pattern */-    n = lua_rawlen(L, -1);-    if (n >= USHRT_MAX)-      luaL_error(L, "too many Lua values in pattern");-    lua_pushvalue(L, idx);  /* element to be added */-    lua_rawseti(L, -2, ++n);-    lua_pop(L, 1);  /* remove 'ktable' */-    return n;-  }-}---/*-** Return the number of elements in the ktable at 'idx'.-** In Lua 5.2/5.3, default "environment" for patterns is nil, not-** a table. Treat it as an empty table. In Lua 5.1, assumes that-** the environment has no numeric indices (len == 0)-*/-static int ktablelen (lua_State *L, int idx) {-  if (!lua_istable(L, idx)) return 0;-  else return lua_rawlen(L, idx);-}---/*-** Concatentate the contents of table 'idx1' into table 'idx2'.-** (Assume that both indices are negative.)-** Return the original length of table 'idx2' (or 0, if no-** element was added, as there is no need to correct any index).-*/-static int concattable (lua_State *L, int idx1, int idx2) {-  int i;-  int n1 = ktablelen(L, idx1);-  int n2 = ktablelen(L, idx2);-  if (n1 + n2 > USHRT_MAX)-    luaL_error(L, "too many Lua values in pattern");-  if (n1 == 0) return 0;  /* nothing to correct */-  for (i = 1; i <= n1; i++) {-    lua_rawgeti(L, idx1, i);-    lua_rawseti(L, idx2 - 1, n2 + i);  /* correct 'idx2' */-  }-  return n2;-}---/*-** When joining 'ktables', constants from one of the subpatterns must-** be renumbered; 'correctkeys' corrects their indices (adding 'n'-** to each of them)-*/-static void correctkeys (TTree *tree, int n) {-  if (n == 0) return;  /* no correction? */- tailcall:-  switch (tree->tag) {-    case TOpenCall: case TCall: case TRunTime: case TRule: {-      if (tree->key > 0)-        tree->key += n;-      break;-    }-    case TCapture: {-      if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)-        tree->key += n;-      break;-    }-    default: break;-  }-  switch (numsiblings[tree->tag]) {-    case 1:  /* correctkeys(sib1(tree), n); */-      tree = sib1(tree); goto tailcall;-    case 2:-      correctkeys(sib1(tree), n);-      tree = sib2(tree); goto tailcall;  /* correctkeys(sib2(tree), n); */-    default: assert(numsiblings[tree->tag] == 0); break;-  }-}---/*-** Join the ktables from p1 and p2 the ktable for the new pattern at the-** top of the stack, reusing them when possible.-*/-static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {-  int n1, n2;-  lua_getuservalue(L, p1);  /* get ktables */-  lua_getuservalue(L, p2);-  n1 = ktablelen(L, -2);-  n2 = ktablelen(L, -1);-  if (n1 == 0 && n2 == 0)  /* are both tables empty? */-    lua_pop(L, 2);  /* nothing to be done; pop tables */-  else if (n2 == 0 || lp_equal(L, -2, -1)) {  /* 2nd table empty or equal? */-    lua_pop(L, 1);  /* pop 2nd table */-    lua_setuservalue(L, -2);  /* set 1st ktable into new pattern */-  }-  else if (n1 == 0) {  /* first table is empty? */-    lua_setuservalue(L, -3);  /* set 2nd table into new pattern */-    lua_pop(L, 1);  /* pop 1st table */-  }-  else {-    lua_createtable(L, n1 + n2, 0);  /* create ktable for new pattern */-    /* stack: new p; ktable p1; ktable p2; new ktable */-    concattable(L, -3, -1);  /* from p1 into new ktable */-    concattable(L, -2, -1);  /* from p2 into new ktable */-    lua_setuservalue(L, -4);  /* new ktable becomes 'p' environment */-    lua_pop(L, 2);  /* pop other ktables */-    correctkeys(t2, n1);  /* correction for indices from p2 */-  }-}---/*-** copy 'ktable' of element 'idx' to new tree (on top of stack)-*/-static void copyktable (lua_State *L, int idx) {-  lua_getuservalue(L, idx);-  lua_setuservalue(L, -2);-}---/*-** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable'-** from tree at the top of the stack, and correct corresponding-** tree.-*/-static void mergektable (lua_State *L, int idx, TTree *stree) {-  int n;-  lua_getuservalue(L, -1);  /* get ktables */-  lua_getuservalue(L, idx);-  n = concattable(L, -1, -2);-  lua_pop(L, 2);  /* remove both ktables */-  correctkeys(stree, n);-}---/*-** Create a new 'ktable' to the pattern at the top of the stack, adding-** all elements from pattern 'p' (if not 0) plus element 'idx' to it.-** Return index of new element.-*/-static int addtonewktable (lua_State *L, int p, int idx) {-  newktable(L, 1);-  if (p)-    mergektable(L, p, NULL);-  return addtoktable(L, idx);-}--/* }====================================================== */---/*-** {======================================================-** Tree generation-** =======================================================-*/--/*-** In 5.2, could use 'luaL_testudata'...-*/-static int testpattern (lua_State *L, int idx) {-  if (lua_touserdata(L, idx)) {  /* value is a userdata? */-    if (lua_getmetatable(L, idx)) {  /* does it have a metatable? */-      luaL_getmetatable(L, PATTERN_T);-      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */-        lua_pop(L, 2);  /* remove both metatables */-        return 1;-      }-    }-  }-  return 0;-}---static Pattern *getpattern (lua_State *L, int idx) {-  return (Pattern *)luaL_checkudata(L, idx, PATTERN_T);-}---static int getsize (lua_State *L, int idx) {-  return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;-}---static TTree *gettree (lua_State *L, int idx, int *len) {-  Pattern *p = getpattern(L, idx);-  if (len)-    *len = getsize(L, idx);-  return p->tree;-}---/*-** create a pattern. Set its uservalue (the 'ktable') equal to its-** metatable. (It could be any empty sequence; the metatable is at-** hand here, so we use it.)-*/-static TTree *newtree (lua_State *L, int len) {-  size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern);-  Pattern *p = (Pattern *)lua_newuserdata(L, size);-  luaL_getmetatable(L, PATTERN_T);-  lua_pushvalue(L, -1);-  lua_setuservalue(L, -3);-  lua_setmetatable(L, -2);-  p->code = NULL;  p->codesize = 0;-  return p->tree;-}---static TTree *newleaf (lua_State *L, int tag) {-  TTree *tree = newtree(L, 1);-  tree->tag = tag;-  return tree;-}---static TTree *newcharset (lua_State *L) {-  TTree *tree = newtree(L, bytes2slots(CHARSETSIZE) + 1);-  tree->tag = TSet;-  loopset(i, treebuffer(tree)[i] = 0);-  return tree;-}---/*-** add to tree a sequence where first sibling is 'sib' (with size-** 'sibsize'); returns position for second sibling-*/-static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {-  tree->tag = TSeq; tree->u.ps = sibsize + 1;-  memcpy(sib1(tree), sib, sibsize * sizeof(TTree));-  return sib2(tree);-}---/*-** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got-** from the array 's' (or 0 if array is NULL). (TSeq is binary, so it-** must build a sequence of sequence of sequence...)-*/-static void fillseq (TTree *tree, int tag, int n, const char *s) {-  int i;-  for (i = 0; i < n - 1; i++) {  /* initial n-1 copies of Seq tag; Seq ... */-    tree->tag = TSeq; tree->u.ps = 2;-    sib1(tree)->tag = tag;-    sib1(tree)->u.n = s ? (byte)s[i] : 0;-    tree = sib2(tree);-  }-  tree->tag = tag;  /* last one does not need TSeq */-  tree->u.n = s ? (byte)s[i] : 0;-}---/*-** Numbers as patterns:-** 0 == true (always match); n == TAny repeated 'n' times;-** -n == not (TAny repeated 'n' times)-*/-static TTree *numtree (lua_State *L, int n) {-  if (n == 0)-    return newleaf(L, TTrue);-  else {-    TTree *tree, *nd;-    if (n > 0)-      tree = nd = newtree(L, 2 * n - 1);-    else {  /* negative: code it as !(-n) */-      n = -n;-      tree = newtree(L, 2 * n);-      tree->tag = TNot;-      nd = sib1(tree);-    }-    fillseq(nd, TAny, n, NULL);  /* sequence of 'n' any's */-    return tree;-  }-}---/*-** Convert value at index 'idx' to a pattern-*/-static TTree *getpatt (lua_State *L, int idx, int *len) {-  TTree *tree;-  switch (lua_type(L, idx)) {-    case LUA_TSTRING: {-      size_t slen;-      const char *s = lua_tolstring(L, idx, &slen);  /* get string */-      if (slen == 0)  /* empty? */-        tree = newleaf(L, TTrue);  /* always match */-      else {-        tree = newtree(L, 2 * (slen - 1) + 1);-        fillseq(tree, TChar, slen, s);  /* sequence of 'slen' chars */-      }-      break;-    }-    case LUA_TNUMBER: {-      int n = lua_tointeger(L, idx);-      tree = numtree(L, n);-      break;-    }-    case LUA_TBOOLEAN: {-      tree = (lua_toboolean(L, idx) ? newleaf(L, TTrue) : newleaf(L, TFalse));-      break;-    }-    case LUA_TTABLE: {-      tree = newgrammar(L, idx);-      break;-    }-    case LUA_TFUNCTION: {-      tree = newtree(L, 2);-      tree->tag = TRunTime;-      tree->key = addtonewktable(L, 0, idx);-      sib1(tree)->tag = TTrue;-      break;-    }-    default: {-      return gettree(L, idx, len);-    }-  }-  lua_replace(L, idx);  /* put new tree into 'idx' slot */-  if (len)-    *len = getsize(L, idx);-  return tree;-}---/*-** create a new tree, whith a new root and one sibling.-** Sibling must be on the Lua stack, at index 1.-*/-static TTree *newroot1sib (lua_State *L, int tag) {-  int s1;-  TTree *tree1 = getpatt(L, 1, &s1);-  TTree *tree = newtree(L, 1 + s1);  /* create new tree */-  tree->tag = tag;-  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));-  copyktable(L, 1);-  return tree;-}---/*-** create a new tree, whith a new root and 2 siblings.-** Siblings must be on the Lua stack, first one at index 1.-*/-static TTree *newroot2sib (lua_State *L, int tag) {-  int s1, s2;-  TTree *tree1 = getpatt(L, 1, &s1);-  TTree *tree2 = getpatt(L, 2, &s2);-  TTree *tree = newtree(L, 1 + s1 + s2);  /* create new tree */-  tree->tag = tag;-  tree->u.ps =  1 + s1;-  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));-  memcpy(sib2(tree), tree2, s2 * sizeof(TTree));-  joinktables(L, 1, sib2(tree), 2);-  return tree;-}---static int lp_P (lua_State *L) {-  luaL_checkany(L, 1);-  getpatt(L, 1, NULL);-  lua_settop(L, 1);-  return 1;-}---/*-** sequence operator; optimizations:-** false x => false, x true => x, true x => x-** (cannot do x . false => false because x may have runtime captures)-*/-static int lp_seq (lua_State *L) {-  TTree *tree1 = getpatt(L, 1, NULL);-  TTree *tree2 = getpatt(L, 2, NULL);-  if (tree1->tag == TFalse || tree2->tag == TTrue)-    lua_pushvalue(L, 1);  /* false . x == false, x . true = x */-  else if (tree1->tag == TTrue)-    lua_pushvalue(L, 2);  /* true . x = x */-  else-    newroot2sib(L, TSeq);-  return 1;-}---/*-** choice operator; optimizations:-** charset / charset => charset-** true / x => true, x / false => x, false / x => x-** (x / true is not equivalent to true)-*/-static int lp_choice (lua_State *L) {-  Charset st1, st2;-  TTree *t1 = getpatt(L, 1, NULL);-  TTree *t2 = getpatt(L, 2, NULL);-  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {-    TTree *t = newcharset(L);-    loopset(i, treebuffer(t)[i] = st1.cs[i] | st2.cs[i]);-  }-  else if (nofail(t1) || t2->tag == TFalse)-    lua_pushvalue(L, 1);  /* true / x => true, x / false => x */-  else if (t1->tag == TFalse)-    lua_pushvalue(L, 2);  /* false / x => x */-  else-    newroot2sib(L, TChoice);-  return 1;-}---/*-** p^n-*/-static int lp_star (lua_State *L) {-  int size1;-  int n = (int)luaL_checkinteger(L, 2);-  TTree *tree1 = getpatt(L, 1, &size1);-  if (n >= 0) {  /* seq tree1 (seq tree1 ... (seq tree1 (rep tree1))) */-    TTree *tree = newtree(L, (n + 1) * (size1 + 1));-    if (nullable(tree1))-      luaL_error(L, "loop body may accept empty string");-    while (n--)  /* repeat 'n' times */-      tree = seqaux(tree, tree1, size1);-    tree->tag = TRep;-    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));-  }-  else {  /* choice (seq tree1 ... choice tree1 true ...) true */-    TTree *tree;-    n = -n;-    /* size = (choice + seq + tree1 + true) * n, but the last has no seq */-    tree = newtree(L, n * (size1 + 3) - 1);-    for (; n > 1; n--) {  /* repeat (n - 1) times */-      tree->tag = TChoice; tree->u.ps = n * (size1 + 3) - 2;-      sib2(tree)->tag = TTrue;-      tree = sib1(tree);-      tree = seqaux(tree, tree1, size1);-    }-    tree->tag = TChoice; tree->u.ps = size1 + 1;-    sib2(tree)->tag = TTrue;-    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));-  }-  copyktable(L, 1);-  return 1;-}---/*-** #p == &p-*/-static int lp_and (lua_State *L) {-  newroot1sib(L, TAnd);-  return 1;-}---/*-** -p == !p-*/-static int lp_not (lua_State *L) {-  newroot1sib(L, TNot);-  return 1;-}---/*-** [t1 - t2] == Seq (Not t2) t1-** If t1 and t2 are charsets, make their difference.-*/-static int lp_sub (lua_State *L) {-  Charset st1, st2;-  int s1, s2;-  TTree *t1 = getpatt(L, 1, &s1);-  TTree *t2 = getpatt(L, 2, &s2);-  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {-    TTree *t = newcharset(L);-    loopset(i, treebuffer(t)[i] = st1.cs[i] & ~st2.cs[i]);-  }-  else {-    TTree *tree = newtree(L, 2 + s1 + s2);-    tree->tag = TSeq;  /* sequence of... */-    tree->u.ps =  2 + s2;-    sib1(tree)->tag = TNot;  /* ...not... */-    memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree));  /* ...t2 */-    memcpy(sib2(tree), t1, s1 * sizeof(TTree));  /* ... and t1 */-    joinktables(L, 1, sib1(tree), 2);-  }-  return 1;-}---static int lp_set (lua_State *L) {-  size_t l;-  const char *s = luaL_checklstring(L, 1, &l);-  TTree *tree = newcharset(L);-  while (l--) {-    setchar(treebuffer(tree), (byte)(*s));-    s++;-  }-  return 1;-}---static int lp_range (lua_State *L) {-  int arg;-  int top = lua_gettop(L);-  TTree *tree = newcharset(L);-  for (arg = 1; arg <= top; arg++) {-    int c;-    size_t l;-    const char *r = luaL_checklstring(L, arg, &l);-    luaL_argcheck(L, l == 2, arg, "range must have two characters");-    for (c = (byte)r[0]; c <= (byte)r[1]; c++)-      setchar(treebuffer(tree), c);-  }-  return 1;-}---/*-** Look-behind predicate-*/-static int lp_behind (lua_State *L) {-  TTree *tree;-  TTree *tree1 = getpatt(L, 1, NULL);-  int n = fixedlen(tree1);-  luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");-  luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");-  luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");-  tree = newroot1sib(L, TBehind);-  tree->u.n = n;-  return 1;-}---/*-** Create a non-terminal-*/-static int lp_V (lua_State *L) {-  TTree *tree = newleaf(L, TOpenCall);-  luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");-  tree->key = addtonewktable(L, 0, 1);-  return 1;-}---/*-** Create a tree for a non-empty capture, with a body and-** optionally with an associated Lua value (at index 'labelidx' in the-** stack)-*/-static int capture_aux (lua_State *L, int cap, int labelidx) {-  TTree *tree = newroot1sib(L, TCapture);-  tree->cap = cap;-  tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);-  return 1;-}---/*-** Fill a tree with an empty capture, using an empty (TTrue) sibling.-** (The 'key' field must be filled by the caller to finish the tree.)-*/-static TTree *auxemptycap (TTree *tree, int cap) {-  tree->tag = TCapture;-  tree->cap = cap;-  sib1(tree)->tag = TTrue;-  return tree;-}---/*-** Create a tree for an empty capture.-*/-static TTree *newemptycap (lua_State *L, int cap, int key) {-  TTree *tree = auxemptycap(newtree(L, 2), cap);-  tree->key = key;-  return tree;-}---/*-** Create a tree for an empty capture with an associated Lua value.-*/-static TTree *newemptycapkey (lua_State *L, int cap, int idx) {-  TTree *tree = auxemptycap(newtree(L, 2), cap);-  tree->key = addtonewktable(L, 0, idx);-  return tree;-}---/*-** Captures with syntax p / v-** (function capture, query capture, string capture, or number capture)-*/-static int lp_divcapture (lua_State *L) {-  switch (lua_type(L, 2)) {-    case LUA_TFUNCTION: return capture_aux(L, Cfunction, 2);-    case LUA_TTABLE: return capture_aux(L, Cquery, 2);-    case LUA_TSTRING: return capture_aux(L, Cstring, 2);-    case LUA_TNUMBER: {-      int n = lua_tointeger(L, 2);-      TTree *tree = newroot1sib(L, TCapture);-      luaL_argcheck(L, 0 <= n && n <= SHRT_MAX, 1, "invalid number");-      tree->cap = Cnum;-      tree->key = n;-      return 1;-    }-    default: return luaL_argerror(L, 2, "invalid replacement value");-  }-}---static int lp_substcapture (lua_State *L) {-  return capture_aux(L, Csubst, 0);-}---static int lp_tablecapture (lua_State *L) {-  return capture_aux(L, Ctable, 0);-}---static int lp_groupcapture (lua_State *L) {-  if (lua_isnoneornil(L, 2))-    return capture_aux(L, Cgroup, 0);-  else-    return capture_aux(L, Cgroup, 2);-}---static int lp_foldcapture (lua_State *L) {-  luaL_checktype(L, 2, LUA_TFUNCTION);-  return capture_aux(L, Cfold, 2);-}---static int lp_simplecapture (lua_State *L) {-  return capture_aux(L, Csimple, 0);-}---static int lp_poscapture (lua_State *L) {-  newemptycap(L, Cposition, 0);-  return 1;-}---static int lp_argcapture (lua_State *L) {-  int n = (int)luaL_checkinteger(L, 1);-  luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");-  newemptycap(L, Carg, n);-  return 1;-}---static int lp_backref (lua_State *L) {-  luaL_checkany(L, 1);-  newemptycapkey(L, Cbackref, 1);-  return 1;-}---/*-** Constant capture-*/-static int lp_constcapture (lua_State *L) {-  int i;-  int n = lua_gettop(L);  /* number of values */-  if (n == 0)  /* no values? */-    newleaf(L, TTrue);  /* no capture */-  else if (n == 1)-    newemptycapkey(L, Cconst, 1);  /* single constant capture */-  else {  /* create a group capture with all values */-    TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2);-    newktable(L, n);  /* create a 'ktable' for new tree */-    tree->tag = TCapture;-    tree->cap = Cgroup;-    tree->key = 0;-    tree = sib1(tree);-    for (i = 1; i <= n - 1; i++) {-      tree->tag = TSeq;-      tree->u.ps = 3;  /* skip TCapture and its sibling */-      auxemptycap(sib1(tree), Cconst);-      sib1(tree)->key = addtoktable(L, i);-      tree = sib2(tree);-    }-    auxemptycap(tree, Cconst);-    tree->key = addtoktable(L, i);-  }-  return 1;-}---static int lp_matchtime (lua_State *L) {-  TTree *tree;-  luaL_checktype(L, 2, LUA_TFUNCTION);-  tree = newroot1sib(L, TRunTime);-  tree->key = addtonewktable(L, 1, 2);-  return 1;-}--/* }====================================================== */---/*-** {======================================================-** Grammar - Tree generation-** =======================================================-*/--/*-** push on the stack the index and the pattern for the-** initial rule of grammar at index 'arg' in the stack;-** also add that index into position table.-*/-static void getfirstrule (lua_State *L, int arg, int postab) {-  lua_rawgeti(L, arg, 1);  /* access first element */-  if (lua_isstring(L, -1)) {  /* is it the name of initial rule? */-    lua_pushvalue(L, -1);  /* duplicate it to use as key */-    lua_gettable(L, arg);  /* get associated rule */-  }-  else {-    lua_pushinteger(L, 1);  /* key for initial rule */-    lua_insert(L, -2);  /* put it before rule */-  }-  if (!testpattern(L, -1)) {  /* initial rule not a pattern? */-    if (lua_isnil(L, -1))-      luaL_error(L, "grammar has no initial rule");-    else-      luaL_error(L, "initial rule '%s' is not a pattern", lua_tostring(L, -2));-  }-  lua_pushvalue(L, -2);  /* push key */-  lua_pushinteger(L, 1);  /* push rule position (after TGrammar) */-  lua_settable(L, postab);  /* insert pair at position table */-}--/*-** traverse grammar at index 'arg', pushing all its keys and patterns-** into the stack. Create a new table (before all pairs key-pattern) to-** collect all keys and their associated positions in the final tree-** (the "position table").-** Return the number of rules and (in 'totalsize') the total size-** for the new tree.-*/-static int collectrules (lua_State *L, int arg, int *totalsize) {-  int n = 1;  /* to count number of rules */-  int postab = lua_gettop(L) + 1;  /* index of position table */-  int size;  /* accumulator for total size */-  lua_newtable(L);  /* create position table */-  getfirstrule(L, arg, postab);-  size = 2 + getsize(L, postab + 2);  /* TGrammar + TRule + rule */-  lua_pushnil(L);  /* prepare to traverse grammar table */-  while (lua_next(L, arg) != 0) {-    if (lua_tonumber(L, -2) == 1 ||-        lp_equal(L, -2, postab + 1)) {  /* initial rule? */-      lua_pop(L, 1);  /* remove value (keep key for lua_next) */-      continue;-    }-    if (!testpattern(L, -1))  /* value is not a pattern? */-      luaL_error(L, "rule '%s' is not a pattern", val2str(L, -2));-    luaL_checkstack(L, LUA_MINSTACK, "grammar has too many rules");-    lua_pushvalue(L, -2);  /* push key (to insert into position table) */-    lua_pushinteger(L, size);-    lua_settable(L, postab);-    size += 1 + getsize(L, -1);  /* update size */-    lua_pushvalue(L, -2);  /* push key (for next lua_next) */-    n++;-  }-  *totalsize = size + 1;  /* TTrue to finish list of rules */-  return n;-}---static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {-  int i;-  TTree *nd = sib1(grammar);  /* auxiliary pointer to traverse the tree */-  for (i = 0; i < n; i++) {  /* add each rule into new tree */-    int ridx = frule + 2*i + 1;  /* index of i-th rule */-    int rulesize;-    TTree *rn = gettree(L, ridx, &rulesize);-    nd->tag = TRule;-    nd->key = 0;  /* will be fixed when rule is used */-    nd->cap = i;  /* rule number */-    nd->u.ps = rulesize + 1;  /* point to next rule */-    memcpy(sib1(nd), rn, rulesize * sizeof(TTree));  /* copy rule */-    mergektable(L, ridx, sib1(nd));  /* merge its ktable into new one */-    nd = sib2(nd);  /* move to next rule */-  }-  nd->tag = TTrue;  /* finish list of rules */-}---/*-** Check whether a tree has potential infinite loops-*/-static int checkloops (TTree *tree) {- tailcall:-  if (tree->tag == TRep && nullable(sib1(tree)))-    return 1;-  else if (tree->tag == TGrammar)-    return 0;  /* sub-grammars already checked */-  else {-    switch (numsiblings[tree->tag]) {-      case 1:  /* return checkloops(sib1(tree)); */-        tree = sib1(tree); goto tailcall;-      case 2:-        if (checkloops(sib1(tree))) return 1;-        /* else return checkloops(sib2(tree)); */-        tree = sib2(tree); goto tailcall;-      default: assert(numsiblings[tree->tag] == 0); return 0;-    }-  }-}---/*-** Give appropriate error message for 'verifyrule'. If a rule appears-** twice in 'passed', there is path from it back to itself without-** advancing the subject.-*/-static int verifyerror (lua_State *L, int *passed, int npassed) {-  int i, j;-  for (i = npassed - 1; i >= 0; i--) {  /* search for a repetition */-    for (j = i - 1; j >= 0; j--) {-      if (passed[i] == passed[j]) {-        lua_rawgeti(L, -1, passed[i]);  /* get rule's key */-        return luaL_error(L, "rule '%s' may be left recursive", val2str(L, -1));-      }-    }-  }-  return luaL_error(L, "too many left calls in grammar");-}---/*-** Check whether a rule can be left recursive; raise an error in that-** case; otherwise return 1 iff pattern is nullable.-** The return value is used to check sequences, where the second pattern-** is only relevant if the first is nullable.-** Parameter 'nb' works as an accumulator, to allow tail calls in-** choices. ('nb' true makes function returns true.)-** Parameter 'passed' is a list of already visited rules, 'npassed'-** counts the elements in 'passed'.-** Assume ktable at the top of the stack.-*/-static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,-                       int nb) {- tailcall:-  switch (tree->tag) {-    case TChar: case TSet: case TAny:-    case TFalse:-      return nb;  /* cannot pass from here */-    case TTrue:-    case TBehind:  /* look-behind cannot have calls */-      return 1;-    case TNot: case TAnd: case TRep:-      /* return verifyrule(L, sib1(tree), passed, npassed, 1); */-      tree = sib1(tree); nb = 1; goto tailcall;-    case TCapture: case TRunTime:-      /* return verifyrule(L, sib1(tree), passed, npassed, nb); */-      tree = sib1(tree); goto tailcall;-    case TCall:-      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */-      tree = sib2(tree); goto tailcall;-    case TSeq:  /* only check 2nd child if first is nb */-      if (!verifyrule(L, sib1(tree), passed, npassed, 0))-        return nb;-      /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */-      tree = sib2(tree); goto tailcall;-    case TChoice:  /* must check both children */-      nb = verifyrule(L, sib1(tree), passed, npassed, nb);-      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */-      tree = sib2(tree); goto tailcall;-    case TRule:-      if (npassed >= MAXRULES)-        return verifyerror(L, passed, npassed);-      else {-        passed[npassed++] = tree->key;-        /* return verifyrule(L, sib1(tree), passed, npassed); */-        tree = sib1(tree); goto tailcall;-      }-    case TGrammar:-      return nullable(tree);  /* sub-grammar cannot be left recursive */-    default: assert(0); return 0;-  }-}---static void verifygrammar (lua_State *L, TTree *grammar) {-  int passed[MAXRULES];-  TTree *rule;-  /* check left-recursive rules */-  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {-    if (rule->key == 0) continue;  /* unused rule */-    verifyrule(L, sib1(rule), passed, 0, 0);-  }-  assert(rule->tag == TTrue);-  /* check infinite loops inside rules */-  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {-    if (rule->key == 0) continue;  /* unused rule */-    if (checkloops(sib1(rule))) {-      lua_rawgeti(L, -1, rule->key);  /* get rule's key */-      luaL_error(L, "empty loop in rule '%s'", val2str(L, -1));-    }-  }-  assert(rule->tag == TTrue);-}---/*-** Give a name for the initial rule if it is not referenced-*/-static void initialrulename (lua_State *L, TTree *grammar, int frule) {-  if (sib1(grammar)->key == 0) {  /* initial rule is not referenced? */-    int n = lua_rawlen(L, -1) + 1;  /* index for name */-    lua_pushvalue(L, frule);  /* rule's name */-    lua_rawseti(L, -2, n);  /* ktable was on the top of the stack */-    sib1(grammar)->key = n;-  }-}---static TTree *newgrammar (lua_State *L, int arg) {-  int treesize;-  int frule = lua_gettop(L) + 2;  /* position of first rule's key */-  int n = collectrules(L, arg, &treesize);-  TTree *g = newtree(L, treesize);-  luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");-  g->tag = TGrammar;  g->u.n = n;-  lua_newtable(L);  /* create 'ktable' */-  lua_setuservalue(L, -2);-  buildgrammar(L, g, frule, n);-  lua_getuservalue(L, -1);  /* get 'ktable' for new tree */-  finalfix(L, frule - 1, g, sib1(g));-  initialrulename(L, g, frule);-  verifygrammar(L, g);-  lua_pop(L, 1);  /* remove 'ktable' */-  lua_insert(L, -(n * 2 + 2));  /* move new table to proper position */-  lua_pop(L, n * 2 + 1);  /* remove position table + rule pairs */-  return g;  /* new table at the top of the stack */-}--/* }====================================================== */---static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {-  lua_getuservalue(L, idx);  /* push 'ktable' (may be used by 'finalfix') */-  finalfix(L, 0, NULL, p->tree);-  lua_pop(L, 1);  /* remove 'ktable' */-  return compile(L, p);-}---static int lp_printtree (lua_State *L) {-  TTree *tree = getpatt(L, 1, NULL);-  int c = lua_toboolean(L, 2);-  if (c) {-    lua_getuservalue(L, 1);  /* push 'ktable' (may be used by 'finalfix') */-    finalfix(L, 0, NULL, tree);-    lua_pop(L, 1);  /* remove 'ktable' */-  }-  printktable(L, 1);-  printtree(tree, 0);-  return 0;-}---static int lp_printcode (lua_State *L) {-  Pattern *p = getpattern(L, 1);-  printktable(L, 1);-  if (p->code == NULL)  /* not compiled yet? */-    prepcompile(L, p, 1);-  printpatt(p->code, p->codesize);-  return 0;-}---/*-** Get the initial position for the match, interpreting negative-** values from the end of the subject-*/-static size_t initposition (lua_State *L, size_t len) {-  lua_Integer ii = luaL_optinteger(L, 3, 1);-  if (ii > 0) {  /* positive index? */-    if ((size_t)ii <= len)  /* inside the string? */-      return (size_t)ii - 1;  /* return it (corrected to 0-base) */-    else return len;  /* crop at the end */-  }-  else {  /* negative index */-    if ((size_t)(-ii) <= len)  /* inside the string? */-      return len - ((size_t)(-ii));  /* return position from the end */-    else return 0;  /* crop at the beginning */-  }-}---/*-** Main match function-*/-static int lp_match (lua_State *L) {-  Capture capture[INITCAPSIZE];-  const char *r;-  size_t l;-  Pattern *p = (getpatt(L, 1, NULL), getpattern(L, 1));-  Instruction *code = (p->code != NULL) ? p->code : prepcompile(L, p, 1);-  const char *s = luaL_checklstring(L, SUBJIDX, &l);-  size_t i = initposition(L, l);-  int ptop = lua_gettop(L);-  lua_pushnil(L);  /* initialize subscache */-  lua_pushlightuserdata(L, capture);  /* initialize caplistidx */-  lua_getuservalue(L, 1);  /* initialize penvidx */-  r = match(L, s, s + i, s + l, code, capture, ptop);-  if (r == NULL) {-    lua_pushnil(L);-    return 1;-  }-  return getcaptures(L, s, r, ptop);-}----/*-** {======================================================-** Library creation and functions not related to matching-** =======================================================-*/--/* maximum limit for stack size */-#define MAXLIM		(INT_MAX / 100)--static int lp_setmax (lua_State *L) {-  lua_Integer lim = luaL_checkinteger(L, 1);-  luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");-  lua_settop(L, 1);-  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);-  return 0;-}---static int lp_version (lua_State *L) {-  lua_pushstring(L, VERSION);-  return 1;-}---static int lp_type (lua_State *L) {-  if (testpattern(L, 1))-    lua_pushliteral(L, "pattern");-  else-    lua_pushnil(L);-  return 1;-}---int lp_gc (lua_State *L) {-  Pattern *p = getpattern(L, 1);-  realloccode(L, p, 0);  /* delete code block */-  return 0;-}---static void createcat (lua_State *L, const char *catname, int (catf) (int)) {-  TTree *t = newcharset(L);-  int i;-  for (i = 0; i <= UCHAR_MAX; i++)-    if (catf(i)) setchar(treebuffer(t), i);-  lua_setfield(L, -2, catname);-}---static int lp_locale (lua_State *L) {-  if (lua_isnoneornil(L, 1)) {-    lua_settop(L, 0);-    lua_createtable(L, 0, 12);-  }-  else {-    luaL_checktype(L, 1, LUA_TTABLE);-    lua_settop(L, 1);-  }-  createcat(L, "alnum", isalnum);-  createcat(L, "alpha", isalpha);-  createcat(L, "cntrl", iscntrl);-  createcat(L, "digit", isdigit);-  createcat(L, "graph", isgraph);-  createcat(L, "lower", islower);-  createcat(L, "print", isprint);-  createcat(L, "punct", ispunct);-  createcat(L, "space", isspace);-  createcat(L, "upper", isupper);-  createcat(L, "xdigit", isxdigit);-  return 1;-}---static struct luaL_Reg pattreg[] = {-  {"ptree", lp_printtree},-  {"pcode", lp_printcode},-  {"match", lp_match},-  {"B", lp_behind},-  {"V", lp_V},-  {"C", lp_simplecapture},-  {"Cc", lp_constcapture},-  {"Cmt", lp_matchtime},-  {"Cb", lp_backref},-  {"Carg", lp_argcapture},-  {"Cp", lp_poscapture},-  {"Cs", lp_substcapture},-  {"Ct", lp_tablecapture},-  {"Cf", lp_foldcapture},-  {"Cg", lp_groupcapture},-  {"P", lp_P},-  {"S", lp_set},-  {"R", lp_range},-  {"locale", lp_locale},-  {"version", lp_version},-  {"setmaxstack", lp_setmax},-  {"type", lp_type},-  {NULL, NULL}-};---static struct luaL_Reg metareg[] = {-  {"__mul", lp_seq},-  {"__add", lp_choice},-  {"__pow", lp_star},-  {"__gc", lp_gc},-  {"__len", lp_and},-  {"__div", lp_divcapture},-  {"__unm", lp_not},-  {"__sub", lp_sub},-  {NULL, NULL}-};---int luaopen_lpeg (lua_State *L);-int luaopen_lpeg (lua_State *L) {-  luaL_newmetatable(L, PATTERN_T);-  lua_pushnumber(L, MAXBACK);  /* initialize maximum backtracking */-  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);-  luaL_setfuncs(L, metareg, 0);-  luaL_newlib(L, pattreg);-  lua_pushvalue(L, -1);-  lua_setfield(L, -3, "__index");-  return 1;-}--/* }====================================================== */
− cbits/lpeg-1.0.2/lptree.h
@@ -1,82 +0,0 @@-/*  -** $Id: lptree.h $-*/--#if !defined(lptree_h)-#define lptree_h---#include "lptypes.h" ---/*-** types of trees-*/-typedef enum TTag {-  TChar = 0,  /* 'n' = char */-  TSet,  /* the set is stored in next CHARSETSIZE bytes */-  TAny,-  TTrue,-  TFalse,-  TRep,  /* 'sib1'* */-  TSeq,  /* 'sib1' 'sib2' */-  TChoice,  /* 'sib1' / 'sib2' */-  TNot,  /* !'sib1' */-  TAnd,  /* &'sib1' */-  TCall,  /* ktable[key] is rule's key; 'sib2' is rule being called */-  TOpenCall,  /* ktable[key] is rule's key */-  TRule,  /* ktable[key] is rule's key (but key == 0 for unused rules);-             'sib1' is rule's pattern;-             'sib2' is next rule; 'cap' is rule's sequential number */-  TGrammar,  /* 'sib1' is initial (and first) rule */-  TBehind,  /* 'sib1' is pattern, 'n' is how much to go back */-  TCapture,  /* captures: 'cap' is kind of capture (enum 'CapKind');-                ktable[key] is Lua value associated with capture;-                'sib1' is capture body */-  TRunTime  /* run-time capture: 'key' is Lua function;-               'sib1' is capture body */-} TTag;---/*-** Tree trees-** The first child of a tree (if there is one) is immediately after-** the tree.  A reference to a second child (ps) is its position-** relative to the position of the tree itself.-*/-typedef struct TTree {-  byte tag;-  byte cap;  /* kind of capture (if it is a capture) */-  unsigned short key;  /* key in ktable for Lua data (0 if no key) */-  union {-    int ps;  /* occasional second child */-    int n;  /* occasional counter */-  } u;-} TTree;---/*-** A complete pattern has its tree plus, if already compiled,-** its corresponding code-*/-typedef struct Pattern {-  union Instruction *code;-  int codesize;-  TTree tree[1];-} Pattern;---/* number of children for each tree */-extern const byte numsiblings[];--/* access to children */-#define sib1(t)         ((t) + 1)-#define sib2(t)         ((t) + (t)->u.ps)-------#endif-
− cbits/lpeg-1.0.2/lptypes.h
@@ -1,145 +0,0 @@-/*-** $Id: lptypes.h $-** LPeg - PEG pattern matching for Lua-** Copyright 2007-2019, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-** written by Roberto Ierusalimschy-*/--#if !defined(lptypes_h)-#define lptypes_h---#include <assert.h>-#include <limits.h>--#include "lua.h"---#define VERSION         "1.0.2"---#define PATTERN_T	"lpeg-pattern"-#define MAXSTACKIDX	"lpeg-maxstack"---/*-** compatibility with Lua 5.1-*/-#if (LUA_VERSION_NUM == 501)--#define lp_equal	lua_equal--#define lua_getuservalue	lua_getfenv-#define lua_setuservalue	lua_setfenv--#define lua_rawlen		lua_objlen--#define luaL_setfuncs(L,f,n)	luaL_register(L,NULL,f)-#define luaL_newlib(L,f)	luaL_register(L,"lpeg",f)--#endif---#if !defined(lp_equal)-#define lp_equal(L,idx1,idx2)  lua_compare(L,(idx1),(idx2),LUA_OPEQ)-#endif---/* default maximum size for call/backtrack stack */-#if !defined(MAXBACK)-#define MAXBACK         400-#endif---/* maximum number of rules in a grammar (limited by 'unsigned char') */-#if !defined(MAXRULES)-#define MAXRULES        250-#endif----/* initial size for capture's list */-#define INITCAPSIZE	32---/* index, on Lua stack, for subject */-#define SUBJIDX		2--/* number of fixed arguments to 'match' (before capture arguments) */-#define FIXEDARGS	3--/* index, on Lua stack, for capture list */-#define caplistidx(ptop)	((ptop) + 2)--/* index, on Lua stack, for pattern's ktable */-#define ktableidx(ptop)		((ptop) + 3)--/* index, on Lua stack, for backtracking stack */-#define stackidx(ptop)	((ptop) + 4)----typedef unsigned char byte;---#define BITSPERCHAR		8--#define CHARSETSIZE		((UCHAR_MAX/BITSPERCHAR) + 1)----typedef struct Charset {-  byte cs[CHARSETSIZE];-} Charset;----#define loopset(v,b)    { int v; for (v = 0; v < CHARSETSIZE; v++) {b;} }--/* access to charset */-#define treebuffer(t)      ((byte *)((t) + 1))--/* number of slots needed for 'n' bytes */-#define bytes2slots(n)  (((n) - 1) / sizeof(TTree) + 1)--/* set 'b' bit in charset 'cs' */-#define setchar(cs,b)   ((cs)[(b) >> 3] |= (1 << ((b) & 7)))---/*-** in capture instructions, 'kind' of capture and its offset are-** packed in field 'aux', 4 bits for each-*/-#define getkind(op)		((op)->i.aux & 0xF)-#define getoff(op)		(((op)->i.aux >> 4) & 0xF)-#define joinkindoff(k,o)	((k) | ((o) << 4))--#define MAXOFF		0xF-#define MAXAUX		0xFF---/* maximum number of bytes to look behind */-#define MAXBEHIND	MAXAUX---/* maximum size (in elements) for a pattern */-#define MAXPATTSIZE	(SHRT_MAX - 10)---/* size (in elements) for an instruction plus extra l bytes */-#define instsize(l)  (((l) + sizeof(Instruction) - 1)/sizeof(Instruction) + 1)---/* size (in elements) for a ISet instruction */-#define CHARSETINSTSIZE		instsize(CHARSETSIZE)--/* size (in elements) for a IFunc instruction */-#define funcinstsize(p)		((p)->i.aux + 2)----#define testchar(st,c)	(((int)(st)[((c) >> 3)] & (1 << ((c) & 7))))---#endif-
− cbits/lpeg-1.0.2/lpvm.c
@@ -1,374 +0,0 @@-/*-** $Id: lpvm.c $-** Copyright 2007, Lua.org & PUC-Rio  (see 'lpeg.html' for license)-*/--#include <limits.h>-#include <string.h>---#include "lua.h"-#include "lauxlib.h"--#include "lpcap.h"-#include "lptypes.h"-#include "lpvm.h"-#include "lpprint.h"---/* initial size for call/backtrack stack */-#if !defined(INITBACK)-#define INITBACK	MAXBACK-#endif---#define getoffset(p)	(((p) + 1)->offset)--static const Instruction giveup = {{IGiveup, 0, 0}};---/*-** {======================================================-** Virtual Machine-** =======================================================-*/---typedef struct Stack {-  const char *s;  /* saved position (or NULL for calls) */-  const Instruction *p;  /* next instruction */-  int caplevel;-} Stack;---#define getstackbase(L, ptop)	((Stack *)lua_touserdata(L, stackidx(ptop)))---/*-** Ensures the size of array 'capture' (with size '*capsize' and-** 'captop' elements being used) is enough to accomodate 'n' extra-** elements plus one.  (Because several opcodes add stuff to the capture-** array, it is simpler to ensure the array always has at least one free-** slot upfront and check its size later.)-*/-static Capture *growcap (lua_State *L, Capture *capture, int *capsize,-                                       int captop, int n, int ptop) {-  if (*capsize - captop > n)-    return capture;  /* no need to grow array */-  else {  /* must grow */-    Capture *newc;-    int newsize = captop + n + 1;  /* minimum size needed */-    if (newsize < INT_MAX/((int)sizeof(Capture) * 2))-      newsize *= 2;  /* twice that size, if not too big */-    else if (newsize >= INT_MAX/((int)sizeof(Capture)))-      luaL_error(L, "too many captures");-    newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));-    memcpy(newc, capture, captop * sizeof(Capture));-    *capsize = newsize;-    lua_replace(L, caplistidx(ptop));-    return newc;-  }-}---/*-** Double the size of the stack-*/-static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {-  Stack *stack = getstackbase(L, ptop);-  Stack *newstack;-  int n = *stacklimit - stack;  /* current stack size */-  int max, newn;-  lua_getfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);-  max = lua_tointeger(L, -1);  /* maximum allowed size */-  lua_pop(L, 1);-  if (n >= max)  /* already at maximum size? */-    luaL_error(L, "backtrack stack overflow (current limit is %d)", max);-  newn = 2 * n;  /* new size */-  if (newn > max) newn = max;-  newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));-  memcpy(newstack, stack, n * sizeof(Stack));-  lua_replace(L, stackidx(ptop));-  *stacklimit = newstack + newn;-  return newstack + n;  /* return next position */-}---/*-** Interpret the result of a dynamic capture: false -> fail;-** true -> keep current position; number -> next position.-** Return new subject position. 'fr' is stack index where-** is the result; 'curr' is current subject position; 'limit'-** is subject's size.-*/-static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {-  lua_Integer res;-  if (!lua_toboolean(L, fr)) {  /* false value? */-    lua_settop(L, fr - 1);  /* remove results */-    return -1;  /* and fail */-  }-  else if (lua_isboolean(L, fr))  /* true? */-    res = curr;  /* keep current position */-  else {-    res = lua_tointeger(L, fr) - 1;  /* new position */-    if (res < curr || res > limit)-      luaL_error(L, "invalid position returned by match-time capture");-  }-  lua_remove(L, fr);  /* remove first result (offset) */-  return res;-}---/*-** Add capture values returned by a dynamic capture to the list-** 'capture', nested inside a group. 'fd' indexes the first capture-** value, 'n' is the number of values (at least 1). The open group-** capture is already in 'capture', before the place for the new entries.-*/-static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {-  int i;-  assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);-  capture[-1].idx = 0;  /* make group capture an anonymous group */-  for (i = 0; i < n; i++) {  /* add runtime captures */-    capture[i].kind = Cruntime;-    capture[i].siz = 1;  /* mark it as closed */-    capture[i].idx = fd + i;  /* stack index of capture value */-    capture[i].s = s;-  }-  capture[n].kind = Cclose;  /* close group */-  capture[n].siz = 1;-  capture[n].s = s;-}---/*-** Remove dynamic captures from the Lua stack (called in case of failure)-*/-static int removedyncap (lua_State *L, Capture *capture,-                         int level, int last) {-  int id = finddyncap(capture + level, capture + last);  /* index of 1st cap. */-  int top = lua_gettop(L);-  if (id == 0) return 0;  /* no dynamic captures? */-  lua_settop(L, id - 1);  /* remove captures */-  return top - id + 1;  /* number of values removed */-}---/*-** Opcode interpreter-*/-const char *match (lua_State *L, const char *o, const char *s, const char *e,-                   Instruction *op, Capture *capture, int ptop) {-  Stack stackbase[INITBACK];-  Stack *stacklimit = stackbase + INITBACK;-  Stack *stack = stackbase;  /* point to first empty slot in stack */-  int capsize = INITCAPSIZE;-  int captop = 0;  /* point to first empty slot in captures */-  int ndyncap = 0;  /* number of dynamic captures (in Lua stack) */-  const Instruction *p = op;  /* current instruction */-  stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;-  lua_pushlightuserdata(L, stackbase);-  for (;;) {-#if defined(DEBUG)-      printf("-------------------------------------\n");-      printcaplist(capture, capture + captop);-      printf("s: |%s| stck:%d, dyncaps:%d, caps:%d  ",-             s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop);-      printinst(op, p);-#endif-    assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);-    switch ((Opcode)p->i.code) {-      case IEnd: {-        assert(stack == getstackbase(L, ptop) + 1);-        capture[captop].kind = Cclose;-        capture[captop].s = NULL;-        return s;-      }-      case IGiveup: {-        assert(stack == getstackbase(L, ptop));-        return NULL;-      }-      case IRet: {-        assert(stack > getstackbase(L, ptop) && (stack - 1)->s == NULL);-        p = (--stack)->p;-        continue;-      }-      case IAny: {-        if (s < e) { p++; s++; }-        else goto fail;-        continue;-      }-      case ITestAny: {-        if (s < e) p += 2;-        else p += getoffset(p);-        continue;-      }-      case IChar: {-        if ((byte)*s == p->i.aux && s < e) { p++; s++; }-        else goto fail;-        continue;-      }-      case ITestChar: {-        if ((byte)*s == p->i.aux && s < e) p += 2;-        else p += getoffset(p);-        continue;-      }-      case ISet: {-        int c = (byte)*s;-        if (testchar((p+1)->buff, c) && s < e)-          { p += CHARSETINSTSIZE; s++; }-        else goto fail;-        continue;-      }-      case ITestSet: {-        int c = (byte)*s;-        if (testchar((p + 2)->buff, c) && s < e)-          p += 1 + CHARSETINSTSIZE;-        else p += getoffset(p);-        continue;-      }-      case IBehind: {-        int n = p->i.aux;-        if (n > s - o) goto fail;-        s -= n; p++;-        continue;-      }-      case ISpan: {-        for (; s < e; s++) {-          int c = (byte)*s;-          if (!testchar((p+1)->buff, c)) break;-        }-        p += CHARSETINSTSIZE;-        continue;-      }-      case IJmp: {-        p += getoffset(p);-        continue;-      }-      case IChoice: {-        if (stack == stacklimit)-          stack = doublestack(L, &stacklimit, ptop);-        stack->p = p + getoffset(p);-        stack->s = s;-        stack->caplevel = captop;-        stack++;-        p += 2;-        continue;-      }-      case ICall: {-        if (stack == stacklimit)-          stack = doublestack(L, &stacklimit, ptop);-        stack->s = NULL;-        stack->p = p + 2;  /* save return address */-        stack++;-        p += getoffset(p);-        continue;-      }-      case ICommit: {-        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);-        stack--;-        p += getoffset(p);-        continue;-      }-      case IPartialCommit: {-        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);-        (stack - 1)->s = s;-        (stack - 1)->caplevel = captop;-        p += getoffset(p);-        continue;-      }-      case IBackCommit: {-        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);-        s = (--stack)->s;-        captop = stack->caplevel;-        p += getoffset(p);-        continue;-      }-      case IFailTwice:-        assert(stack > getstackbase(L, ptop));-        stack--;-        /* go through */-      case IFail:-      fail: { /* pattern failed: try to backtrack */-        do {  /* remove pending calls */-          assert(stack > getstackbase(L, ptop));-          s = (--stack)->s;-        } while (s == NULL);-        if (ndyncap > 0)  /* is there matchtime captures? */-          ndyncap -= removedyncap(L, capture, stack->caplevel, captop);-        captop = stack->caplevel;-        p = stack->p;-#if defined(DEBUG)-        printf("**FAIL**\n");-#endif-        continue;-      }-      case ICloseRunTime: {-        CapState cs;-        int rem, res, n;-        int fr = lua_gettop(L) + 1;  /* stack index of first result */-        cs.reclevel = 0; cs.L = L;-        cs.s = o; cs.ocap = capture; cs.ptop = ptop;-        n = runtimecap(&cs, capture + captop, s, &rem);  /* call function */-        captop -= n;  /* remove nested captures */-        ndyncap -= rem;  /* update number of dynamic captures */-        fr -= rem;  /* 'rem' items were popped from Lua stack */-        res = resdyncaptures(L, fr, s - o, e - o);  /* get result */-        if (res == -1)  /* fail? */-          goto fail;-        s = o + res;  /* else update current position */-        n = lua_gettop(L) - fr + 1;  /* number of new captures */-        ndyncap += n;  /* update number of dynamic captures */-        if (n == 0)  /* no new captures? */-          captop--;  /* remove open group */-        else {  /* new captures; keep original open group */-          if (fr + n >= SHRT_MAX)-            luaL_error(L, "too many results in match-time capture");-          /* add new captures + close group to 'capture' list */-          capture = growcap(L, capture, &capsize, captop, n + 1, ptop);-          adddyncaptures(s, capture + captop, n, fr);-          captop += n + 1;  /* new captures + close group */-        }-        p++;-        continue;-      }-      case ICloseCapture: {-        const char *s1 = s;-        assert(captop > 0);-        /* if possible, turn capture into a full capture */-        if (capture[captop - 1].siz == 0 &&-            s1 - capture[captop - 1].s < UCHAR_MAX) {-          capture[captop - 1].siz = s1 - capture[captop - 1].s + 1;-          p++;-          continue;-        }-        else {-          capture[captop].siz = 1;  /* mark entry as closed */-          capture[captop].s = s;-          goto pushcapture;-        }-      }-      case IOpenCapture:-        capture[captop].siz = 0;  /* mark entry as open */-        capture[captop].s = s;-        goto pushcapture;-      case IFullCapture:-        capture[captop].siz = getoff(p) + 1;  /* save capture size */-        capture[captop].s = s - getoff(p);-        /* goto pushcapture; */-      pushcapture: {-        capture[captop].idx = p->i.key;-        capture[captop].kind = getkind(p);-        captop++;-        capture = growcap(L, capture, &capsize, captop, 0, ptop);-        p++;-        continue;-      }-      default: assert(0); return NULL;-    }-  }-}--/* }====================================================== */--
− cbits/lpeg-1.0.2/lpvm.h
@@ -1,58 +0,0 @@-/*-** $Id: lpvm.h $-*/--#if !defined(lpvm_h)-#define lpvm_h--#include "lpcap.h"---/* Virtual Machine's instructions */-typedef enum Opcode {-  IAny, /* if no char, fail */-  IChar,  /* if char != aux, fail */-  ISet,  /* if char not in buff, fail */-  ITestAny,  /* in no char, jump to 'offset' */-  ITestChar,  /* if char != aux, jump to 'offset' */-  ITestSet,  /* if char not in buff, jump to 'offset' */-  ISpan,  /* read a span of chars in buff */-  IBehind,  /* walk back 'aux' characters (fail if not possible) */-  IRet,  /* return from a rule */-  IEnd,  /* end of pattern */-  IChoice,  /* stack a choice; next fail will jump to 'offset' */-  IJmp,  /* jump to 'offset' */-  ICall,  /* call rule at 'offset' */-  IOpenCall,  /* call rule number 'key' (must be closed to a ICall) */-  ICommit,  /* pop choice and jump to 'offset' */-  IPartialCommit,  /* update top choice to current position and jump */-  IBackCommit,  /* "fails" but jump to its own 'offset' */-  IFailTwice,  /* pop one choice and then fail */-  IFail,  /* go back to saved state on choice and jump to saved offset */-  IGiveup,  /* internal use */-  IFullCapture,  /* complete capture of last 'off' chars */-  IOpenCapture,  /* start a capture */-  ICloseCapture,-  ICloseRunTime-} Opcode;----typedef union Instruction {-  struct Inst {-    byte code;-    byte aux;-    short key;-  } i;-  int offset;-  byte buff[1];-} Instruction;---void printpatt (Instruction *p, int n);-const char *match (lua_State *L, const char *o, const char *s, const char *e,-                   Instruction *op, Capture *capture, int ptop);---#endif-
+ cbits/lpeg-1.1.0/lpcap.c view
@@ -0,0 +1,612 @@++#include "lua.h"+#include "lauxlib.h"++#include "lpcap.h"+#include "lpprint.h"+#include "lptypes.h"+++#define getfromktable(cs,v)	lua_rawgeti((cs)->L, ktableidx((cs)->ptop), v)++#define pushluaval(cs)		getfromktable(cs, (cs)->cap->idx)++++#define skipclose(cs,head)  \+	if (isopencap(head)) { assert(isclosecap(cs->cap)); cs->cap++; }+++/*+** Return the size of capture 'cap'. If it is an open capture, 'close'+** must be its corresponding close.+*/+static Index_t capsize (Capture *cap, Capture *close) {+  if (isopencap(cap)) {+    assert(isclosecap(close));+    return close->index - cap->index;+  }+  else+    return cap->siz - 1;+}+++static Index_t closesize (CapState *cs, Capture *head) {+  return capsize(head, cs->cap);+}+++/*+** Put at the cache for Lua values the value indexed by 'v' in ktable+** of the running pattern (if it is not there yet); returns its index.+*/+static int updatecache (CapState *cs, int v) {+  int idx = cs->ptop + 1;  /* stack index of cache for Lua values */+  if (v != cs->valuecached) {  /* not there? */+    getfromktable(cs, v);  /* get value from 'ktable' */+    lua_replace(cs->L, idx);  /* put it at reserved stack position */+    cs->valuecached = v;  /* keep track of what is there */+  }+  return idx;+}+++static int pushcapture (CapState *cs);+++/*+** Goes back in a list of captures looking for an open capture+** corresponding to a close one.+*/+static Capture *findopen (Capture *cap) {+  int n = 0;  /* number of closes waiting an open */+  for (;;) {+    cap--;+    if (isclosecap(cap)) n++;  /* one more open to skip */+    else if (isopencap(cap))+      if (n-- == 0) return cap;+  }+}+++/*+** Go to the next capture at the same level.+*/+static void nextcap (CapState *cs) {+  Capture *cap = cs->cap;+  if (isopencap(cap)) {  /* must look for a close? */+    int n = 0;  /* number of opens waiting a close */+    for (;;) {  /* look for corresponding close */+      cap++;+      if (isopencap(cap)) n++;+      else if (isclosecap(cap))+        if (n-- == 0) break;+    }+    cs->cap = cap + 1;  /* + 1 to skip last close */+  }+  else {+    Capture *next;+    for (next = cap + 1; capinside(cap, next); next++)+      ;  /* skip captures inside current one */+    cs->cap = next;+  }+}+++/*+** Push on the Lua stack all values generated by nested captures inside+** the current capture. Returns number of values pushed. 'addextra'+** makes it push the entire match after all captured values. The+** entire match is pushed also if there are no other nested values,+** so the function never returns zero.+*/+static int pushnestedvalues (CapState *cs, int addextra) {+  Capture *head = cs->cap++;  /* original capture */+  int n = 0;  /* number of pushed subvalues */+  /* repeat for all nested patterns */+  while (capinside(head, cs->cap))+    n += pushcapture(cs);+  if (addextra || n == 0) {  /* need extra? */+    lua_pushlstring(cs->L, cs->s + head->index, closesize(cs, head));+    n++;+  }+  skipclose(cs, head);+  return n;+}+++/*+** Push only the first value generated by nested captures+*/+static void pushonenestedvalue (CapState *cs) {+  int n = pushnestedvalues(cs, 0);+  if (n > 1)+    lua_pop(cs->L, n - 1);  /* pop extra values */+}+++/*+** Checks whether group 'grp' is visible to 'ref', that is, 'grp' is+** not nested inside a full capture that does not contain 'ref'.  (We+** only need to care for full captures because the search at 'findback'+** skips open-end blocks; so, if 'grp' is nested in a non-full capture,+** 'ref' is also inside it.)  To check this, we search backward for the+** inner full capture enclosing 'grp'.  A full capture cannot contain+** non-full captures, so a close capture means we cannot be inside a+** full capture anymore.+*/+static int capvisible (CapState *cs, Capture *grp, Capture *ref) {+  Capture *cap = grp;+  int i = MAXLOP;  /* maximum distance for an 'open' */+  while (i-- > 0 && cap-- > cs->ocap) {+    if (isclosecap(cap))+      return 1;  /* can stop the search */+    else if (grp->index - cap->index >= UCHAR_MAX)+      return 1;  /* can stop the search */+    else if (capinside(cap, grp))  /* is 'grp' inside cap? */+      return capinside(cap, ref);  /* ok iff cap also contains 'ref' */+  }+  return 1;  /* 'grp' is not inside any capture */+}+++/*+** Try to find a named group capture with the name given at the top of+** the stack; goes backward from 'ref'.+*/+static Capture *findback (CapState *cs, Capture *ref) {+  lua_State *L = cs->L;+  Capture *cap = ref;+  while (cap-- > cs->ocap) {  /* repeat until end of list */+    if (isclosecap(cap))+      cap = findopen(cap);  /* skip nested captures */+    else if (capinside(cap, ref))+      continue;  /* enclosing captures are not visible to 'ref' */+    if (captype(cap) == Cgroup && capvisible(cs, cap, ref)) {+      getfromktable(cs, cap->idx);  /* get group name */+      if (lp_equal(L, -2, -1)) {  /* right group? */+        lua_pop(L, 2);  /* remove reference name and group name */+        return cap;+      }+      else lua_pop(L, 1);  /* remove group name */+    }+  }+  luaL_error(L, "back reference '%s' not found", lua_tostring(L, -1));+  return NULL;  /* to avoid warnings */+}+++/*+** Back-reference capture. Return number of values pushed.+*/+static int backrefcap (CapState *cs) {+  int n;+  Capture *curr = cs->cap;+  pushluaval(cs);  /* reference name */+  cs->cap = findback(cs, curr);  /* find corresponding group */+  n = pushnestedvalues(cs, 0);  /* push group's values */+  cs->cap = curr + 1;+  return n;+}+++/*+** Table capture: creates a new table and populates it with nested+** captures.+*/+static int tablecap (CapState *cs) {+  lua_State *L = cs->L;+  Capture *head = cs->cap++;+  int n = 0;+  lua_newtable(L);+  while (capinside(head, cs->cap)) {+    if (captype(cs->cap) == Cgroup && cs->cap->idx != 0) {  /* named group? */+      pushluaval(cs);  /* push group name */+      pushonenestedvalue(cs);+      lua_settable(L, -3);+    }+    else {  /* not a named group */+      int i;+      int k = pushcapture(cs);+      for (i = k; i > 0; i--)  /* store all values into table */+        lua_rawseti(L, -(i + 1), n + i);+      n += k;+    }+  }+  skipclose(cs, head);+  return 1;  /* number of values pushed (only the table) */+}+++/*+** Table-query capture+*/+static int querycap (CapState *cs) {+  int idx = cs->cap->idx;+  pushonenestedvalue(cs);  /* get nested capture */+  lua_gettable(cs->L, updatecache(cs, idx));  /* query cap. value at table */+  if (!lua_isnil(cs->L, -1))+    return 1;+  else {  /* no value */+    lua_pop(cs->L, 1);  /* remove nil */+    return 0;+  }+}+++/*+** Fold capture+*/+static int foldcap (CapState *cs) {+  int n;+  lua_State *L = cs->L;+  Capture *head = cs->cap++;+  int idx = head->idx;+  if (isclosecap(cs->cap) ||  /* no nested captures (large subject)? */+      (n = pushcapture(cs)) == 0)  /* nested captures with no values? */+    return luaL_error(L, "no initial value for fold capture");+  if (n > 1)+    lua_pop(L, n - 1);  /* leave only one result for accumulator */+  while (capinside(head, cs->cap)) {+    lua_pushvalue(L, updatecache(cs, idx));  /* get folding function */+    lua_insert(L, -2);  /* put it before accumulator */+    n = pushcapture(cs);  /* get next capture's values */+    lua_call(L, n + 1, 1);  /* call folding function */+  }+  skipclose(cs, head);+  return 1;  /* only accumulator left on the stack */+}+++/*+** Function capture+*/+static int functioncap (CapState *cs) {+  int n;+  int top = lua_gettop(cs->L);+  pushluaval(cs);  /* push function */+  n = pushnestedvalues(cs, 0);  /* push nested captures */+  lua_call(cs->L, n, LUA_MULTRET);  /* call function */+  return lua_gettop(cs->L) - top;  /* return function's results */+}+++/*+** Accumulator capture+*/+static int accumulatorcap (CapState *cs) {+  lua_State *L = cs->L;+  int n;+  if (lua_gettop(L) < cs->firstcap)+    luaL_error(L, "no previous value for accumulator capture");+  pushluaval(cs);  /* push function */+  lua_insert(L, -2);  /* previous value becomes first argument */+  n = pushnestedvalues(cs, 0);  /* push nested captures */+  lua_call(L, n + 1, 1);  /* call function */+  return 0;  /* did not add any extra value */+}+++/*+** Select capture+*/+static int numcap (CapState *cs) {+  int idx = cs->cap->idx;  /* value to select */+  if (idx == 0) {  /* no values? */+    nextcap(cs);  /* skip entire capture */+    return 0;  /* no value produced */+  }+  else {+    int n = pushnestedvalues(cs, 0);+    if (n < idx)  /* invalid index? */+      return luaL_error(cs->L, "no capture '%d'", idx);+    else {+      lua_pushvalue(cs->L, -(n - idx + 1));  /* get selected capture */+      lua_replace(cs->L, -(n + 1));  /* put it in place of 1st capture */+      lua_pop(cs->L, n - 1);  /* remove other captures */+      return 1;+    }+  }+}+++/*+** Return the stack index of the first runtime capture in the given+** list of captures (or zero if no runtime captures)+*/+int finddyncap (Capture *cap, Capture *last) {+  for (; cap < last; cap++) {+    if (cap->kind == Cruntime)+      return cap->idx;  /* stack position of first capture */+  }+  return 0;  /* no dynamic captures in this segment */+}+++/*+** Calls a runtime capture. Returns number of captures "removed" by the+** call, that is, those inside the group capture. Captures to be added+** are on the Lua stack.+*/+int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {+  int n, id;+  lua_State *L = cs->L;+  int otop = lua_gettop(L);+  Capture *open = findopen(close);  /* get open group capture */+  assert(captype(open) == Cgroup);+  id = finddyncap(open, close);  /* get first dynamic capture argument */+  close->kind = Cclose;  /* closes the group */+  close->index = s - cs->s;+  cs->cap = open; cs->valuecached = 0;  /* prepare capture state */+  luaL_checkstack(L, 4, "too many runtime captures");+  pushluaval(cs);  /* push function to be called */+  lua_pushvalue(L, SUBJIDX);  /* push original subject */+  lua_pushinteger(L, s - cs->s + 1);  /* push current position */+  n = pushnestedvalues(cs, 0);  /* push nested captures */+  lua_call(L, n + 2, LUA_MULTRET);  /* call dynamic function */+  if (id > 0) {  /* are there old dynamic captures to be removed? */+    int i;+    for (i = id; i <= otop; i++)+      lua_remove(L, id);  /* remove old dynamic captures */+    *rem = otop - id + 1;  /* total number of dynamic captures removed */+  }+  else+    *rem = 0;  /* no dynamic captures removed */+  return close - open - 1;  /* number of captures to be removed */+}+++/*+** Auxiliary structure for substitution and string captures: keep+** information about nested captures for future use, avoiding to push+** string results into Lua+*/+typedef struct StrAux {+  int isstring;  /* whether capture is a string */+  union {+    Capture *cp;  /* if not a string, respective capture */+    struct {  /* if it is a string... */+      Index_t idx;  /* starts here */+      Index_t siz;  /* with this size */+    } s;+  } u;+} StrAux;++#define MAXSTRCAPS	10++/*+** Collect values from current capture into array 'cps'. Current+** capture must be Cstring (first call) or Csimple (recursive calls).+** (In first call, fills %0 with whole match for Cstring.)+** Returns number of elements in the array that were filled.+*/+static int getstrcaps (CapState *cs, StrAux *cps, int n) {+  int k = n++;+  Capture *head = cs->cap++;+  cps[k].isstring = 1;  /* get string value */+  cps[k].u.s.idx = head->index;  /* starts here */+  while (capinside(head, cs->cap)) {+    if (n >= MAXSTRCAPS)  /* too many captures? */+      nextcap(cs);  /* skip extra captures (will not need them) */+    else if (captype(cs->cap) == Csimple)  /* string? */+      n = getstrcaps(cs, cps, n);  /* put info. into array */+    else {+      cps[n].isstring = 0;  /* not a string */+      cps[n].u.cp = cs->cap;  /* keep original capture */+      nextcap(cs);+      n++;+    }+  }+  cps[k].u.s.siz = closesize(cs, head);+  skipclose(cs, head);+  return n;+}+++/*+** add next capture value (which should be a string) to buffer 'b'+*/+static int addonestring (luaL_Buffer *b, CapState *cs, const char *what);+++/*+** String capture: add result to buffer 'b' (instead of pushing+** it into the stack)+*/+static void stringcap (luaL_Buffer *b, CapState *cs) {+  StrAux cps[MAXSTRCAPS];+  int n;+  size_t len, i;+  const char *fmt;  /* format string */+  fmt = lua_tolstring(cs->L, updatecache(cs, cs->cap->idx), &len);+  n = getstrcaps(cs, cps, 0) - 1;  /* collect nested captures */+  for (i = 0; i < len; i++) {  /* traverse format string */+    if (fmt[i] != '%')  /* not an escape? */+      luaL_addchar(b, fmt[i]);  /* add it to buffer */+    else if (fmt[++i] < '0' || fmt[i] > '9')  /* not followed by a digit? */+      luaL_addchar(b, fmt[i]);  /* add to buffer */+    else {+      int l = fmt[i] - '0';  /* capture index */+      if (l > n)+        luaL_error(cs->L, "invalid capture index (%d)", l);+      else if (cps[l].isstring)+        luaL_addlstring(b, cs->s + cps[l].u.s.idx, cps[l].u.s.siz);+      else {+        Capture *curr = cs->cap;+        cs->cap = cps[l].u.cp;  /* go back to evaluate that nested capture */+        if (!addonestring(b, cs, "capture"))+          luaL_error(cs->L, "no values in capture index %d", l);+        cs->cap = curr;  /* continue from where it stopped */+      }+    }+  }+}+++/*+** Substitution capture: add result to buffer 'b'+*/+static void substcap (luaL_Buffer *b, CapState *cs) {+  const char *curr = cs->s + cs->cap->index;+  Capture *head = cs->cap++;+  while (capinside(head, cs->cap)) {+    Capture *cap = cs->cap;+    const char *caps = cs->s + cap->index;+    luaL_addlstring(b, curr, caps - curr);  /* add text up to capture */+    if (addonestring(b, cs, "replacement"))+      curr = caps + capsize(cap, cs->cap - 1);  /* continue after match */+    else  /* no capture value */+      curr = caps;  /* keep original text in final result */+  }+  /* add last piece of text */+  luaL_addlstring(b, curr, cs->s + head->index + closesize(cs, head) - curr);+  skipclose(cs, head);+}+++/*+** Evaluates a capture and adds its first value to buffer 'b'; returns+** whether there was a value+*/+static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) {+  switch (captype(cs->cap)) {+    case Cstring:+      stringcap(b, cs);  /* add capture directly to buffer */+      return 1;+    case Csubst:+      substcap(b, cs);  /* add capture directly to buffer */+      return 1;+    case Cacc:  /* accumulator capture? */+      return luaL_error(cs->L, "invalid context for an accumulator capture");+    default: {+      lua_State *L = cs->L;+      int n = pushcapture(cs);+      if (n > 0) {+        if (n > 1) lua_pop(L, n - 1);  /* only one result */+        if (!lua_isstring(L, -1))+          return luaL_error(L, "invalid %s value (a %s)",+                               what, luaL_typename(L, -1));+        luaL_addvalue(b);+      }+      return n;+    }+  }+}+++#if !defined(MAXRECLEVEL)+#define MAXRECLEVEL	200+#endif+++/*+** Push all values of the current capture into the stack; returns+** number of values pushed+*/+static int pushcapture (CapState *cs) {+  lua_State *L = cs->L;+  int res;+  luaL_checkstack(L, 4, "too many captures");+  if (cs->reclevel++ > MAXRECLEVEL)+    return luaL_error(L, "subcapture nesting too deep");+  switch (captype(cs->cap)) {+    case Cposition: {+      lua_pushinteger(L, cs->cap->index + 1);+      cs->cap++;+      res = 1;+      break;+    }+    case Cconst: {+      pushluaval(cs);+      cs->cap++;+      res = 1;+      break;+    }+    case Carg: {+      int arg = (cs->cap++)->idx;+      if (arg + FIXEDARGS > cs->ptop)+        return luaL_error(L, "reference to absent extra argument #%d", arg);+      lua_pushvalue(L, arg + FIXEDARGS);+      res = 1;+      break;+    }+    case Csimple: {+      int k = pushnestedvalues(cs, 1);+      lua_insert(L, -k);  /* make whole match be first result */+      res = k;+      break;+    }+    case Cruntime: {+      lua_pushvalue(L, (cs->cap++)->idx);  /* value is in the stack */+      res = 1;+      break;+    }+    case Cstring: {+      luaL_Buffer b;+      luaL_buffinit(L, &b);+      stringcap(&b, cs);+      luaL_pushresult(&b);+      res = 1;+      break;+    }+    case Csubst: {+      luaL_Buffer b;+      luaL_buffinit(L, &b);+      substcap(&b, cs);+      luaL_pushresult(&b);+      res = 1;+      break;+    }+    case Cgroup: {+      if (cs->cap->idx == 0)  /* anonymous group? */+        res = pushnestedvalues(cs, 0);  /* add all nested values */+      else {  /* named group: add no values */+        nextcap(cs);  /* skip capture */+        res = 0;+      }+      break;+    }+    case Cbackref: res = backrefcap(cs); break;+    case Ctable: res = tablecap(cs); break;+    case Cfunction: res = functioncap(cs); break;+    case Cacc: res = accumulatorcap(cs); break;+    case Cnum: res = numcap(cs); break;+    case Cquery: res = querycap(cs); break;+    case Cfold: res = foldcap(cs); break;+    default: assert(0); res = 0;+  }+  cs->reclevel--;+  return res;+}+++/*+** Prepare a CapState structure and traverse the entire list of+** captures in the stack pushing its results. 's' is the subject+** string, 'r' is the final position of the match, and 'ptop'+** the index in the stack where some useful values were pushed.+** Returns the number of results pushed. (If the list produces no+** results, push the final position of the match.)+*/+int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {+  Capture *capture = (Capture *)lua_touserdata(L, caplistidx(ptop));+  int n = 0;+  /* printcaplist(capture); */+  if (!isclosecap(capture)) {  /* is there any capture? */+    CapState cs;+    cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0;+    cs.s = s; cs.valuecached = 0; cs.ptop = ptop;+    cs.firstcap = lua_gettop(L) + 1;  /* where first value (if any) will go */+    do {  /* collect their values */+      n += pushcapture(&cs);+    } while (!isclosecap(cs.cap));+    assert(lua_gettop(L) - cs.firstcap == n - 1);+  }+  if (n == 0) {  /* no capture values? */+    lua_pushinteger(L, r - s + 1);  /* return only end position */+    n = 1;+  }+  return n;+}++
+ cbits/lpeg-1.1.0/lpcap.h view
@@ -0,0 +1,86 @@++#if !defined(lpcap_h)+#define lpcap_h+++#include "lptypes.h"+++/* kinds of captures */+typedef enum CapKind {+  Cclose,  /* not used in trees */+  Cposition,+  Cconst,  /* ktable[key] is Lua constant */+  Cbackref,  /* ktable[key] is "name" of group to get capture */+  Carg,  /* 'key' is arg's number */+  Csimple,  /* next node is pattern */+  Ctable,  /* next node is pattern */+  Cfunction,  /* ktable[key] is function; next node is pattern */+  Cacc,  /* ktable[key] is function; next node is pattern */+  Cquery,  /* ktable[key] is table; next node is pattern */+  Cstring,  /* ktable[key] is string; next node is pattern */+  Cnum,  /* numbered capture; 'key' is number of value to return */+  Csubst,  /* substitution capture; next node is pattern */+  Cfold,  /* ktable[key] is function; next node is pattern */+  Cruntime,  /* not used in trees (is uses another type for tree) */+  Cgroup  /* ktable[key] is group's "name" */+} CapKind;+++/*+** An unsigned integer large enough to index any subject entirely.+** It can be size_t, but that will double the size of the array+** of captures in a 64-bit machine.+*/+#if !defined(Index_t)+typedef uint Index_t;+#endif++#define MAXINDT		(~(Index_t)0)+++typedef struct Capture {+  Index_t index;  /* subject position */+  unsigned short idx;  /* extra info (group name, arg index, etc.) */+  byte kind;  /* kind of capture */+  byte siz;  /* size of full capture + 1 (0 = not a full capture) */+} Capture;+++typedef struct CapState {+  Capture *cap;  /* current capture */+  Capture *ocap;  /* (original) capture list */+  lua_State *L;+  int ptop;  /* stack index of last argument to 'match' */+  int firstcap;  /* stack index of first capture pushed in the stack */+  const char *s;  /* original string */+  int valuecached;  /* value stored in cache slot */+  int reclevel;  /* recursion level */+} CapState;+++#define captype(cap)    ((cap)->kind)++#define isclosecap(cap) (captype(cap) == Cclose)+#define isopencap(cap)  ((cap)->siz == 0)++/* true if c2 is (any number of levels) inside c1 */+#define capinside(c1,c2)  \+	(isopencap(c1) ? !isclosecap(c2) \+                       : (c2)->index < (c1)->index + (c1)->siz - 1)+++/**+** Maximum number of captures to visit when looking for an 'open'.+*/+#define MAXLOP		20++++int runtimecap (CapState *cs, Capture *close, const char *s, int *rem);+int getcaptures (lua_State *L, const char *s, const char *r, int ptop);+int finddyncap (Capture *cap, Capture *last);++#endif++
+ cbits/lpeg-1.1.0/lpcode.c view
@@ -0,0 +1,1051 @@++#include <limits.h>+++#include "lua.h"+#include "lauxlib.h"++#include "lptypes.h"+#include "lpcode.h"+#include "lpcset.h"+++/* signals a "no-instruction */+#define NOINST		-1++++static const Charset fullset_ =+  {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};++static const Charset *fullset = &fullset_;+++/*+** {======================================================+** Analysis and some optimizations+** =======================================================+*/+++/*+** A few basic operations on Charsets+*/+static void cs_complement (Charset *cs) {+  loopset(i, cs->cs[i] = ~cs->cs[i]);+}++static int cs_disjoint (const Charset *cs1, const Charset *cs2) {+  loopset(i, if ((cs1->cs[i] & cs2->cs[i]) != 0) return 0;)+  return 1;+}+++/*+** Visit a TCall node taking care to stop recursion. If node not yet+** visited, return 'f(sib2(tree))', otherwise return 'def' (default+** value)+*/+static int callrecursive (TTree *tree, int f (TTree *t), int def) {+  int key = tree->key;+  assert(tree->tag == TCall);+  assert(sib2(tree)->tag == TRule);+  if (key == 0)  /* node already visited? */+    return def;  /* return default value */+  else {  /* first visit */+    int result;+    tree->key = 0;  /* mark call as already visited */+    result = f(sib2(tree));  /* go to called rule */+    tree->key = key;  /* restore tree */+    return result;+  }+}+++/*+** Check whether a pattern tree has captures+*/+int hascaptures (TTree *tree) {+ tailcall:+  switch (tree->tag) {+    case TCapture: case TRunTime:+      return 1;+    case TCall:+      return callrecursive(tree, hascaptures, 0);+    case TRule:  /* do not follow siblings */+      tree = sib1(tree); goto tailcall;+    case TOpenCall: assert(0);+    default: {+      switch (numsiblings[tree->tag]) {+        case 1:  /* return hascaptures(sib1(tree)); */+          tree = sib1(tree); goto tailcall;+        case 2:+          if (hascaptures(sib1(tree)))+            return 1;+          /* else return hascaptures(sib2(tree)); */+          tree = sib2(tree); goto tailcall;+        default: assert(numsiblings[tree->tag] == 0); return 0;+      }+    }+  }+}+++/*+** Checks how a pattern behaves regarding the empty string,+** in one of two different ways:+** A pattern is *nullable* if it can match without consuming any character;+** A pattern is *nofail* if it never fails for any string+** (including the empty string).+** The difference is only for predicates and run-time captures;+** for other patterns, the two properties are equivalent.+** (With predicates, &'a' is nullable but not nofail. Of course,+** nofail => nullable.)+** These functions are all convervative in the following way:+**    p is nullable => nullable(p)+**    nofail(p) => p cannot fail+** The function assumes that TOpenCall is not nullable;+** this will be checked again when the grammar is fixed.+** Run-time captures can do whatever they want, so the result+** is conservative.+*/+int checkaux (TTree *tree, int pred) {+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny: case TUTFR:+    case TFalse: case TOpenCall:+      return 0;  /* not nullable */+    case TRep: case TTrue:+      return 1;  /* no fail */+    case TNot: case TBehind:  /* can match empty, but can fail */+      if (pred == PEnofail) return 0;+      else return 1;  /* PEnullable */+    case TAnd:  /* can match empty; fail iff body does */+      if (pred == PEnullable) return 1;+      /* else return checkaux(sib1(tree), pred); */+      tree = sib1(tree); goto tailcall;+    case TRunTime:  /* can fail; match empty iff body does */+      if (pred == PEnofail) return 0;+      /* else return checkaux(sib1(tree), pred); */+      tree = sib1(tree); goto tailcall;+    case TSeq:+      if (!checkaux(sib1(tree), pred)) return 0;+      /* else return checkaux(sib2(tree), pred); */+      tree = sib2(tree); goto tailcall;+    case TChoice:+      if (checkaux(sib2(tree), pred)) return 1;+      /* else return checkaux(sib1(tree), pred); */+      tree = sib1(tree); goto tailcall;+    case TCapture: case TGrammar: case TRule: case TXInfo:+      /* return checkaux(sib1(tree), pred); */+      tree = sib1(tree); goto tailcall;+    case TCall:  /* return checkaux(sib2(tree), pred); */+      tree = sib2(tree); goto tailcall;+    default: assert(0); return 0;+  }+}+++/*+** number of characters to match a pattern (or -1 if variable)+*/+int fixedlen (TTree *tree) {+  int len = 0;  /* to accumulate in tail calls */+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny:+      return len + 1;+    case TUTFR:+      return (tree->cap == sib1(tree)->cap) ? len + tree->cap : -1;+    case TFalse: case TTrue: case TNot: case TAnd: case TBehind:+      return len;+    case TRep: case TRunTime: case TOpenCall:+      return -1;+    case TCapture: case TRule: case TGrammar: case TXInfo:+      /* return fixedlen(sib1(tree)); */+      tree = sib1(tree); goto tailcall;+    case TCall: {+      int n1 = callrecursive(tree, fixedlen, -1);+      if (n1 < 0)+        return -1;+      else+        return len + n1;+    }+    case TSeq: {+      int n1 = fixedlen(sib1(tree));+      if (n1 < 0)+        return -1;+      /* else return fixedlen(sib2(tree)) + len; */+      len += n1; tree = sib2(tree); goto tailcall;+    }+    case TChoice: {+      int n1 = fixedlen(sib1(tree));+      int n2 = fixedlen(sib2(tree));+      if (n1 != n2 || n1 < 0)+        return -1;+      else+        return len + n1;+    }+    default: assert(0); return 0;+  };+}+++/*+** Computes the 'first set' of a pattern.+** The result is a conservative aproximation:+**   match p ax -> x (for some x) ==> a belongs to first(p)+** or+**   a not in first(p) ==> match p ax -> fail (for all x)+**+** The set 'follow' is the first set of what follows the+** pattern (full set if nothing follows it).+**+** The function returns 0 when this resulting set can be used for+** test instructions that avoid the pattern altogether.+** A non-zero return can happen for two reasons:+** 1) match p '' -> ''            ==> return has bit 1 set+** (tests cannot be used because they would always fail for an empty input);+** 2) there is a match-time capture ==> return has bit 2 set+** (optimizations should not bypass match-time captures).+*/+static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny: case TFalse: {+      tocharset(tree, firstset);+      return 0;+    }+    case TUTFR: {+      int c;+      clearset(firstset->cs);  /* erase all chars */+      for (c = tree->key; c <= sib1(tree)->key; c++)+        setchar(firstset->cs, c);+      return 0;+    }+    case TTrue: {+      loopset(i, firstset->cs[i] = follow->cs[i]);+      return 1;  /* accepts the empty string */+    }+    case TChoice: {+      Charset csaux;+      int e1 = getfirst(sib1(tree), follow, firstset);+      int e2 = getfirst(sib2(tree), follow, &csaux);+      loopset(i, firstset->cs[i] |= csaux.cs[i]);+      return e1 | e2;+    }+    case TSeq: {+      if (!nullable(sib1(tree))) {+        /* when p1 is not nullable, p2 has nothing to contribute;+           return getfirst(sib1(tree), fullset, firstset); */+        tree = sib1(tree); follow = fullset; goto tailcall;+      }+      else {  /* FIRST(p1 p2, fl) = FIRST(p1, FIRST(p2, fl)) */+        Charset csaux;+        int e2 = getfirst(sib2(tree), follow, &csaux);+        int e1 = getfirst(sib1(tree), &csaux, firstset);+        if (e1 == 0) return 0;  /* 'e1' ensures that first can be used */+        else if ((e1 | e2) & 2)  /* one of the children has a matchtime? */+          return 2;  /* pattern has a matchtime capture */+        else return e2;  /* else depends on 'e2' */+      }+    }+    case TRep: {+      getfirst(sib1(tree), follow, firstset);+      loopset(i, firstset->cs[i] |= follow->cs[i]);+      return 1;  /* accept the empty string */+    }+    case TCapture: case TGrammar: case TRule: case TXInfo: {+      /* return getfirst(sib1(tree), follow, firstset); */+      tree = sib1(tree); goto tailcall;+    }+    case TRunTime: {  /* function invalidates any follow info. */+      int e = getfirst(sib1(tree), fullset, firstset);+      if (e) return 2;  /* function is not "protected"? */+      else return 0;  /* pattern inside capture ensures first can be used */+    }+    case TCall: {+      /* return getfirst(sib2(tree), follow, firstset); */+      tree = sib2(tree); goto tailcall;+    }+    case TAnd: {+      int e = getfirst(sib1(tree), follow, firstset);+      loopset(i, firstset->cs[i] &= follow->cs[i]);+      return e;+    }+    case TNot: {+      if (tocharset(sib1(tree), firstset)) {+        cs_complement(firstset);+        return 1;+      }  /* else */+    }    /* FALLTHROUGH */+    case TBehind: {  /* instruction gives no new information */+      /* call 'getfirst' only to check for math-time captures */+      int e = getfirst(sib1(tree), follow, firstset);+      loopset(i, firstset->cs[i] = follow->cs[i]);  /* uses follow */+      return e | 1;  /* always can accept the empty string */+    }+    default: assert(0); return 0;+  }+}+++/*+** If 'headfail(tree)' true, then 'tree' can fail only depending on the+** next character of the subject.+*/+static int headfail (TTree *tree) {+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny: case TFalse:+      return 1;+    case TTrue: case TRep: case TRunTime: case TNot:+    case TBehind: case TUTFR:+      return 0;+    case TCapture: case TGrammar: case TRule: case TXInfo: case TAnd:+      tree = sib1(tree); goto tailcall;  /* return headfail(sib1(tree)); */+    case TCall:+      tree = sib2(tree); goto tailcall;  /* return headfail(sib2(tree)); */+    case TSeq:+      if (!nofail(sib2(tree))) return 0;+      /* else return headfail(sib1(tree)); */+      tree = sib1(tree); goto tailcall;+    case TChoice:+      if (!headfail(sib1(tree))) return 0;+      /* else return headfail(sib2(tree)); */+      tree = sib2(tree); goto tailcall;+    default: assert(0); return 0;+  }+}+++/*+** Check whether the code generation for the given tree can benefit+** from a follow set (to avoid computing the follow set when it is+** not needed)+*/+static int needfollow (TTree *tree) {+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny: case TUTFR:+    case TFalse: case TTrue: case TAnd: case TNot:+    case TRunTime: case TGrammar: case TCall: case TBehind:+      return 0;+    case TChoice: case TRep:+      return 1;+    case TCapture:+      tree = sib1(tree); goto tailcall;+    case TSeq:+      tree = sib2(tree); goto tailcall;+    default: assert(0); return 0;+  }+}++/* }====================================================== */++++/*+** {======================================================+** Code generation+** =======================================================+*/+++/*+** size of an instruction+*/+int sizei (const Instruction *i) {+  switch((Opcode)i->i.code) {+    case ISet: case ISpan: return 1 + i->i.aux2.set.size;+    case ITestSet: return 2 + i->i.aux2.set.size;+    case ITestChar: case ITestAny: case IChoice: case IJmp: case ICall:+    case IOpenCall: case ICommit: case IPartialCommit: case IBackCommit:+    case IUTFR:+      return 2;+    default: return 1;+  }+}+++/*+** state for the compiler+*/+typedef struct CompileState {+  Pattern *p;  /* pattern being compiled */+  int ncode;  /* next position in p->code to be filled */+  lua_State *L;+} CompileState;+++/*+** code generation is recursive; 'opt' indicates that the code is being+** generated as the last thing inside an optional pattern (so, if that+** code is optional too, it can reuse the 'IChoice' already in place for+** the outer pattern). 'tt' points to a previous test protecting this+** code (or NOINST). 'fl' is the follow set of the pattern.+*/+static void codegen (CompileState *compst, TTree *tree, int opt, int tt,+                     const Charset *fl);+++static void finishrelcode (lua_State *L, Pattern *p, Instruction *block,+                                         int size) {+  if (block == NULL)+    luaL_error(L, "not enough memory");+  block->codesize = size;+  p->code = (Instruction *)block + 1;+}+++/*+** Initialize array 'p->code'+*/+static void newcode (lua_State *L, Pattern *p, int size) {+  void *ud;+  Instruction *block;+  lua_Alloc f = lua_getallocf(L, &ud);+  size++;  /* slot for 'codesize' */+  block = (Instruction*) f(ud, NULL, 0, size * sizeof(Instruction));+  finishrelcode(L, p, block, size);+}+++void freecode (lua_State *L, Pattern *p) {+  if (p->code != NULL) {+    void *ud;+    lua_Alloc f = lua_getallocf(L, &ud);+    uint osize = p->code[-1].codesize;+    f(ud, p->code - 1, osize * sizeof(Instruction), 0);  /* free block */+  }+}+++/*+** Assume that 'nsize' is not zero and that 'p->code' already exists.+*/+static void realloccode (lua_State *L, Pattern *p, int nsize) {+  void *ud;+  lua_Alloc f = lua_getallocf(L, &ud);+  Instruction *block = p->code - 1;+  uint osize = block->codesize;+  nsize++;  /* add the 'codesize' slot to size */+  block = (Instruction*) f(ud, block, osize * sizeof(Instruction),+                                      nsize * sizeof(Instruction));+  finishrelcode(L, p, block, nsize);+}+++/*+** Add space for an instruction with 'n' slots and return its index.+*/+static int nextinstruction (CompileState *compst, int n) {+  int size = compst->p->code[-1].codesize - 1;+  int ncode = compst->ncode;+  if (ncode > size - n) {+    uint nsize = size + (size >> 1) + n;+    if (nsize >= INT_MAX)+      luaL_error(compst->L, "pattern code too large");+    realloccode(compst->L, compst->p, nsize);+  }+  compst->ncode = ncode + n;+  return ncode;+}+++#define getinstr(cs,i)		((cs)->p->code[i])+++static int addinstruction (CompileState *compst, Opcode op, int aux) {+  int i = nextinstruction(compst, 1);+  getinstr(compst, i).i.code = op;+  getinstr(compst, i).i.aux1 = aux;+  return i;+}+++/*+** Add an instruction followed by space for an offset (to be set later)+*/+static int addoffsetinst (CompileState *compst, Opcode op) {+  int i = addinstruction(compst, op, 0);  /* instruction */+  addinstruction(compst, (Opcode)0, 0);  /* open space for offset */+  assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2);+  return i;+}+++/*+** Set the offset of an instruction+*/+static void setoffset (CompileState *compst, int instruction, int offset) {+  getinstr(compst, instruction + 1).offset = offset;+}+++static void codeutfr (CompileState *compst, TTree *tree) {+  int i = addoffsetinst(compst, IUTFR);+  int to = sib1(tree)->u.n;+  assert(sib1(tree)->tag == TXInfo);+  getinstr(compst, i + 1).offset = tree->u.n;+  getinstr(compst, i).i.aux1 = to & 0xff;+  getinstr(compst, i).i.aux2.key = to >> 8;+}+++/*+** Add a capture instruction:+** 'op' is the capture instruction; 'cap' the capture kind;+** 'key' the key into ktable; 'aux' is the optional capture offset+**+*/+static int addinstcap (CompileState *compst, Opcode op, int cap, int key,+                       int aux) {+  int i = addinstruction(compst, op, joinkindoff(cap, aux));+  getinstr(compst, i).i.aux2.key = key;+  return i;+}+++#define gethere(compst) 	((compst)->ncode)++#define target(code,i)		((i) + code[i + 1].offset)+++/*+** Patch 'instruction' to jump to 'target'+*/+static void jumptothere (CompileState *compst, int instruction, int target) {+  if (instruction >= 0)+    setoffset(compst, instruction, target - instruction);+}+++/*+** Patch 'instruction' to jump to current position+*/+static void jumptohere (CompileState *compst, int instruction) {+  jumptothere(compst, instruction, gethere(compst));+}+++/*+** Code an IChar instruction, or IAny if there is an equivalent+** test dominating it+*/+static void codechar (CompileState *compst, int c, int tt) {+  if (tt >= 0 && getinstr(compst, tt).i.code == ITestChar &&+                 getinstr(compst, tt).i.aux1 == c)+    addinstruction(compst, IAny, 0);+  else+    addinstruction(compst, IChar, c);+}+++/*+** Add a charset posfix to an instruction.+*/+static void addcharset (CompileState *compst, int inst, charsetinfo *info) {+  int p;+  Instruction *I = &getinstr(compst, inst);+  byte *charset;+  int isize = instsize(info->size);  /* size in instructions */+  int i;+  I->i.aux2.set.offset = info->offset * 8;  /* offset in bits */+  I->i.aux2.set.size = isize;+  I->i.aux1 = info->deflt;+  p = nextinstruction(compst, isize);  /* space for charset */+  charset = getinstr(compst, p).buff;  /* charset buffer */+  for (i = 0; i < isize * (int)sizeof(Instruction); i++)+    charset[i] = getbytefromcharset(info, i);  /* copy the buffer */+}+++/*+** Check whether charset 'info' is dominated by instruction 'p'+*/+static int cs_equal (Instruction *p, charsetinfo *info) {+  if (p->i.code != ITestSet)+    return 0;+  else if (p->i.aux2.set.offset != info->offset * 8 ||+           p->i.aux2.set.size != instsize(info->size) ||+           p->i.aux1 != info->deflt)+    return 0;+  else {+    int i;+    for (i = 0; i < instsize(info->size) * (int)sizeof(Instruction); i++) {+      if ((p + 2)->buff[i] != getbytefromcharset(info, i))+        return 0;+    }+  }+  return 1;+}+++/*+** Code a char set, using IAny when instruction is dominated by an+** equivalent test.+*/+static void codecharset (CompileState *compst, TTree *tree, int tt) {+  charsetinfo info;+  tree2cset(tree, &info);+  if (tt >= 0 && cs_equal(&getinstr(compst, tt), &info))+    addinstruction(compst, IAny, 0);+  else {+    int i = addinstruction(compst, ISet, 0);+    addcharset(compst, i, &info);+  }+}+++/*+** Code a test set, optimizing unit sets for ITestChar, "complete"+** sets for ITestAny, and empty sets for IJmp (always fails).+** 'e' is true iff test should accept the empty string. (Test+** instructions in the current VM never accept the empty string.)+*/+static int codetestset (CompileState *compst, Charset *cs, int e) {+  if (e) return NOINST;  /* no test */+  else {+    charsetinfo info;+    Opcode op = charsettype(cs->cs, &info);+    switch (op) {+      case IFail: return addoffsetinst(compst, IJmp);  /* always jump */+      case IAny: return addoffsetinst(compst, ITestAny);+      case IChar: {+        int i = addoffsetinst(compst, ITestChar);+        getinstr(compst, i).i.aux1 = info.offset;+        return i;+      }+      default: {  /* regular set */+        int i = addoffsetinst(compst, ITestSet);+        addcharset(compst, i, &info);+        assert(op == ISet);+        return i;+      }+    }+  }+}+++/*+** Find the final destination of a sequence of jumps+*/+static int finaltarget (Instruction *code, int i) {+  while (code[i].i.code == IJmp)+    i = target(code, i);+  return i;+}+++/*+** final label (after traversing any jumps)+*/+static int finallabel (Instruction *code, int i) {+  return finaltarget(code, target(code, i));+}+++/*+** <behind(p)> == behind n; <p>   (where n = fixedlen(p))+*/+static void codebehind (CompileState *compst, TTree *tree) {+  if (tree->u.n > 0)+    addinstruction(compst, IBehind, tree->u.n);+  codegen(compst, sib1(tree), 0, NOINST, fullset);+}+++/*+** Choice; optimizations:+** - when p1 is headfail or when first(p1) and first(p2) are disjoint,+** than a character not in first(p1) cannot go to p1 and a character+** in first(p1) cannot go to p2, either because p1 will accept+** (headfail) or because it is not in first(p2) (disjoint).+** (The second case is not valid if p1 accepts the empty string,+** as then there is no character at all...)+** - when p2 is empty and opt is true; a IPartialCommit can reuse+** the Choice already active in the stack.+*/+static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,+                        const Charset *fl) {+  int emptyp2 = (p2->tag == TTrue);+  Charset cs1, cs2;+  int e1 = getfirst(p1, fullset, &cs1);+  if (headfail(p1) ||+      (!e1 && (getfirst(p2, fl, &cs2), cs_disjoint(&cs1, &cs2)))) {+    /* <p1 / p2> == test (fail(p1)) -> L1 ; p1 ; jmp L2; L1: p2; L2: */+    int test = codetestset(compst, &cs1, 0);+    int jmp = NOINST;+    codegen(compst, p1, 0, test, fl);+    if (!emptyp2)+      jmp = addoffsetinst(compst, IJmp);+    jumptohere(compst, test);+    codegen(compst, p2, opt, NOINST, fl);+    jumptohere(compst, jmp);+  }+  else if (opt && emptyp2) {+    /* p1? == IPartialCommit; p1 */+    jumptohere(compst, addoffsetinst(compst, IPartialCommit));+    codegen(compst, p1, 1, NOINST, fullset);+  }+  else {+    /* <p1 / p2> ==+        test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */+    int pcommit;+    int test = codetestset(compst, &cs1, e1);+    int pchoice = addoffsetinst(compst, IChoice);+    codegen(compst, p1, emptyp2, test, fullset);+    pcommit = addoffsetinst(compst, ICommit);+    jumptohere(compst, pchoice);+    jumptohere(compst, test);+    codegen(compst, p2, opt, NOINST, fl);+    jumptohere(compst, pcommit);+  }+}+++/*+** And predicate+** optimization: fixedlen(p) = n ==> <&p> == <p>; behind n+** (valid only when 'p' has no captures)+*/+static void codeand (CompileState *compst, TTree *tree, int tt) {+  int n = fixedlen(tree);+  if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) {+    codegen(compst, tree, 0, tt, fullset);+    if (n > 0)+      addinstruction(compst, IBehind, n);+  }+  else {  /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */+    int pcommit;+    int pchoice = addoffsetinst(compst, IChoice);+    codegen(compst, tree, 0, tt, fullset);+    pcommit = addoffsetinst(compst, IBackCommit);+    jumptohere(compst, pchoice);+    addinstruction(compst, IFail, 0);+    jumptohere(compst, pcommit);+  }+}+++/*+** Captures: if pattern has fixed (and not too big) length, and it+** has no nested captures, use a single IFullCapture instruction+** after the match; otherwise, enclose the pattern with OpenCapture -+** CloseCapture.+*/+static void codecapture (CompileState *compst, TTree *tree, int tt,+                         const Charset *fl) {+  int len = fixedlen(sib1(tree));+  if (len >= 0 && len <= MAXOFF && !hascaptures(sib1(tree))) {+    codegen(compst, sib1(tree), 0, tt, fl);+    addinstcap(compst, IFullCapture, tree->cap, tree->key, len);+  }+  else {+    addinstcap(compst, IOpenCapture, tree->cap, tree->key, 0);+    codegen(compst, sib1(tree), 0, tt, fl);+    addinstcap(compst, ICloseCapture, Cclose, 0, 0);+  }+}+++static void coderuntime (CompileState *compst, TTree *tree, int tt) {+  addinstcap(compst, IOpenCapture, Cgroup, tree->key, 0);+  codegen(compst, sib1(tree), 0, tt, fullset);+  addinstcap(compst, ICloseRunTime, Cclose, 0, 0);+}+++/*+** Create a jump to 'test' and fix 'test' to jump to next instruction+*/+static void closeloop (CompileState *compst, int test) {+  int jmp = addoffsetinst(compst, IJmp);+  jumptohere(compst, test);+  jumptothere(compst, jmp, test);+}+++/*+** Try repetition of charsets:+** For an empty set, repetition of fail is a no-op;+** For any or char, code a tight loop;+** For generic charset, use a span instruction.+*/+static int coderepcharset (CompileState *compst, TTree *tree) {+  switch (tree->tag) {+    case TFalse: return 1;  /* 'fail*' is a no-op */+    case TAny: {  /* L1: testany -> L2; any; jmp L1; L2: */+      int test = addoffsetinst(compst, ITestAny);+      addinstruction(compst, IAny, 0);+      closeloop(compst, test);+      return 1;+    }+    case TChar: {  /* L1: testchar c -> L2; any; jmp L1; L2: */+      int test = addoffsetinst(compst, ITestChar);+      getinstr(compst, test).i.aux1 = tree->u.n;+      addinstruction(compst, IAny, 0);+      closeloop(compst, test);+      return 1;+    }+    case TSet: {  /* regular set */+      charsetinfo info;+      int i = addinstruction(compst, ISpan, 0);+      tree2cset(tree, &info);+      addcharset(compst, i, &info);+      return 1;+    }+    default: return 0;  /* not a charset */+  }+}+++/*+** Repetion; optimizations:+** When pattern is a charset, use special code.+** When pattern is head fail, or if it starts with characters that+** are disjoint from what follows the repetions, a simple test+** is enough (a fail inside the repetition would backtrack to fail+** again in the following pattern, so there is no need for a choice).+** When 'opt' is true, the repetion can reuse the Choice already+** active in the stack.+*/+static void coderep (CompileState *compst, TTree *tree, int opt,+                     const Charset *fl) {+  if (!coderepcharset(compst, tree)) {+    Charset st;+    int e1 = getfirst(tree, fullset, &st);+    if (headfail(tree) || (!e1 && cs_disjoint(&st, fl))) {+      /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */+      int test = codetestset(compst, &st, 0);+      codegen(compst, tree, 0, test, fullset);+      closeloop(compst, test);+    }+    else {+      /* test(fail(p1)) -> L2; choice L2; L1: <p>; partialcommit L1; L2: */+      /* or (if 'opt'): partialcommit L1; L1: <p>; partialcommit L1; */+      int commit, l2;+      int test = codetestset(compst, &st, e1);+      int pchoice = NOINST;+      if (opt)+        jumptohere(compst, addoffsetinst(compst, IPartialCommit));+      else+        pchoice = addoffsetinst(compst, IChoice);+      l2 = gethere(compst);+      codegen(compst, tree, 0, NOINST, fullset);+      commit = addoffsetinst(compst, IPartialCommit);+      jumptothere(compst, commit, l2);+      jumptohere(compst, pchoice);+      jumptohere(compst, test);+    }+  }+}+++/*+** Not predicate; optimizations:+** In any case, if first test fails, 'not' succeeds, so it can jump to+** the end. If pattern is headfail, that is all (it cannot fail+** in other parts); this case includes 'not' of simple sets. Otherwise,+** use the default code (a choice plus a failtwice).+*/+static void codenot (CompileState *compst, TTree *tree) {+  Charset st;+  int e = getfirst(tree, fullset, &st);+  int test = codetestset(compst, &st, e);+  if (headfail(tree))  /* test (fail(p1)) -> L1; fail; L1:  */+    addinstruction(compst, IFail, 0);+  else {+    /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1:  */+    int pchoice = addoffsetinst(compst, IChoice);+    codegen(compst, tree, 0, NOINST, fullset);+    addinstruction(compst, IFailTwice, 0);+    jumptohere(compst, pchoice);+  }+  jumptohere(compst, test);+}+++/*+** change open calls to calls, using list 'positions' to find+** correct offsets; also optimize tail calls+*/+static void correctcalls (CompileState *compst, int *positions,+                          int from, int to) {+  int i;+  Instruction *code = compst->p->code;+  for (i = from; i < to; i += sizei(&code[i])) {+    if (code[i].i.code == IOpenCall) {+      int n = code[i].i.aux2.key;  /* rule number */+      int rule = positions[n];  /* rule position */+      assert(rule == from || code[rule - 1].i.code == IRet);+      if (code[finaltarget(code, i + 2)].i.code == IRet)  /* call; ret ? */+        code[i].i.code = IJmp;  /* tail call */+      else+        code[i].i.code = ICall;+      jumptothere(compst, i, rule);  /* call jumps to respective rule */+    }+  }+  assert(i == to);+}+++/*+** Code for a grammar:+** call L1; jmp L2; L1: rule 1; ret; rule 2; ret; ...; L2:+*/+static void codegrammar (CompileState *compst, TTree *grammar) {+  int positions[MAXRULES];+  int rulenumber = 0;+  TTree *rule;+  int firstcall = addoffsetinst(compst, ICall);  /* call initial rule */+  int jumptoend = addoffsetinst(compst, IJmp);  /* jump to the end */+  int start = gethere(compst);  /* here starts the initial rule */+  jumptohere(compst, firstcall);+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {+    TTree *r = sib1(rule);+    assert(r->tag == TXInfo);+    positions[rulenumber++] = gethere(compst);  /* save rule position */+    codegen(compst, sib1(r), 0, NOINST, fullset);  /* code rule */+    addinstruction(compst, IRet, 0);+  }+  assert(rule->tag == TTrue);+  jumptohere(compst, jumptoend);+  correctcalls(compst, positions, start, gethere(compst));+}+++static void codecall (CompileState *compst, TTree *call) {+  int c = addoffsetinst(compst, IOpenCall);  /* to be corrected later */+  assert(sib1(sib2(call))->tag == TXInfo);+  getinstr(compst, c).i.aux2.key = sib1(sib2(call))->u.n;  /* rule number */+}+++/*+** Code first child of a sequence+** (second child is called in-place to allow tail call)+** Return 'tt' for second child+*/+static int codeseq1 (CompileState *compst, TTree *p1, TTree *p2,+                     int tt, const Charset *fl) {+  if (needfollow(p1)) {+    Charset fl1;+    getfirst(p2, fl, &fl1);  /* p1 follow is p2 first */+    codegen(compst, p1, 0, tt, &fl1);+  }+  else  /* use 'fullset' as follow */+    codegen(compst, p1, 0, tt, fullset);+  if (fixedlen(p1) != 0)  /* can 'p1' consume anything? */+    return  NOINST;  /* invalidate test */+  else return tt;  /* else 'tt' still protects sib2 */+}+++/*+** Main code-generation function: dispatch to auxiliar functions+** according to kind of tree. ('needfollow' should return true+** only for consructions that use 'fl'.)+*/+static void codegen (CompileState *compst, TTree *tree, int opt, int tt,+                     const Charset *fl) {+ tailcall:+  switch (tree->tag) {+    case TChar: codechar(compst, tree->u.n, tt); break;+    case TAny: addinstruction(compst, IAny, 0); break;+    case TSet: codecharset(compst, tree, tt); break;+    case TTrue: break;+    case TFalse: addinstruction(compst, IFail, 0); break;+    case TUTFR: codeutfr(compst, tree); break;+    case TChoice: codechoice(compst, sib1(tree), sib2(tree), opt, fl); break;+    case TRep: coderep(compst, sib1(tree), opt, fl); break;+    case TBehind: codebehind(compst, tree); break;+    case TNot: codenot(compst, sib1(tree)); break;+    case TAnd: codeand(compst, sib1(tree), tt); break;+    case TCapture: codecapture(compst, tree, tt, fl); break;+    case TRunTime: coderuntime(compst, tree, tt); break;+    case TGrammar: codegrammar(compst, tree); break;+    case TCall: codecall(compst, tree); break;+    case TSeq: {+      tt = codeseq1(compst, sib1(tree), sib2(tree), tt, fl);  /* code 'p1' */+      /* codegen(compst, p2, opt, tt, fl); */+      tree = sib2(tree); goto tailcall;+    }+    default: assert(0);+  }+}+++/*+** Optimize jumps and other jump-like instructions.+** * Update labels of instructions with labels to their final+** destinations (e.g., choice L1; ... L1: jmp L2: becomes+** choice L2)+** * Jumps to other instructions that do jumps become those+** instructions (e.g., jump to return becomes a return; jump+** to commit becomes a commit)+*/+static void peephole (CompileState *compst) {+  Instruction *code = compst->p->code;+  int i;+  for (i = 0; i < compst->ncode; i += sizei(&code[i])) {+   redo:+    switch (code[i].i.code) {+      case IChoice: case ICall: case ICommit: case IPartialCommit:+      case IBackCommit: case ITestChar: case ITestSet:+      case ITestAny: {  /* instructions with labels */+        jumptothere(compst, i, finallabel(code, i));  /* optimize label */+        break;+      }+      case IJmp: {+        int ft = finaltarget(code, i);+        switch (code[ft].i.code) {  /* jumping to what? */+          case IRet: case IFail: case IFailTwice:+          case IEnd: {  /* instructions with unconditional implicit jumps */+            code[i] = code[ft];  /* jump becomes that instruction */+            code[i + 1].i.code = IEmpty;  /* 'no-op' for target position */+            break;+          }+          case ICommit: case IPartialCommit:+          case IBackCommit: {  /* inst. with unconditional explicit jumps */+            int fft = finallabel(code, ft);+            code[i] = code[ft];  /* jump becomes that instruction... */+            jumptothere(compst, i, fft);  /* but must correct its offset */+            goto redo;  /* reoptimize its label */+          }+          default: {+            jumptothere(compst, i, ft);  /* optimize label */+            break;+          }+        }+        break;+      }+      default: break;+    }+  }+  assert(code[i - 1].i.code == IEnd);+}+++/*+** Compile a pattern. 'size' is the size of the pattern's tree,+** which gives a hint for the size of the final code.+*/+Instruction *compile (lua_State *L, Pattern *p, uint size) {+  CompileState compst;+  compst.p = p;  compst.ncode = 0;  compst.L = L;+  newcode(L, p, size/2u + 2);  /* set initial size */+  codegen(&compst, p->tree, 0, NOINST, fullset);+  addinstruction(&compst, IEnd, 0);+  realloccode(L, p, compst.ncode);  /* set final size */+  peephole(&compst);+  return p->code;+}+++/* }====================================================== */+
+ cbits/lpeg-1.1.0/lpcode.h view
@@ -0,0 +1,36 @@++#if !defined(lpcode_h)+#define lpcode_h++#include "lua.h"++#include "lptypes.h"+#include "lptree.h"+#include "lpvm.h"++int checkaux (TTree *tree, int pred);+int fixedlen (TTree *tree);+int hascaptures (TTree *tree);+int lp_gc (lua_State *L);+Instruction *compile (lua_State *L, Pattern *p, uint size);+void freecode (lua_State *L, Pattern *p);+int sizei (const Instruction *i);+++#define PEnullable      0+#define PEnofail        1++/*+** nofail(t) implies that 't' cannot fail with any input+*/+#define nofail(t)	checkaux(t, PEnofail)++/*+** (not nullable(t)) implies 't' cannot match without consuming+** something+*/+#define nullable(t)	checkaux(t, PEnullable)++++#endif
+ cbits/lpeg-1.1.0/lpcset.c view
@@ -0,0 +1,110 @@++#include "lptypes.h"+#include "lpcset.h"+++/*+** Add to 'c' the index of the (only) bit set in byte 'b'+*/+static int onlybit (int c, int b) {+  if ((b & 0xF0) != 0) { c += 4; b >>= 4; }+  if ((b & 0x0C) != 0) { c += 2; b >>= 2; }+  if ((b & 0x02) != 0) { c += 1; }+  return c;+}+++/*+** Check whether a charset is empty (returns IFail), singleton (IChar),+** full (IAny), or none of those (ISet). When singleton, 'info.offset'+** returns which character it is. When generic set, 'info' returns+** information about its range.+*/+Opcode charsettype (const byte *cs, charsetinfo *info) {+  int low0, low1, high0, high1;+  for (low1 = 0; low1 < CHARSETSIZE && cs[low1] == 0; low1++)+    /* find lowest byte with a 1-bit */;+  if (low1 == CHARSETSIZE)+    return IFail;  /* no characters in set */+  for (high1 = CHARSETSIZE - 1; cs[high1] == 0; high1--)+    /* find highest byte with a 1-bit; low1 is a sentinel */;+  if (low1 == high1) {  /* only one byte with 1-bits? */+    int b = cs[low1];+    if ((b & (b - 1)) == 0) {  /* does byte has only one 1-bit? */+      info->offset = onlybit(low1 * BITSPERCHAR, b);  /* get that bit */+      return IChar;  /* single character */+    }+  }+  for (low0 = 0; low0 < CHARSETSIZE && cs[low0] == 0xFF; low0++)+    /* find lowest byte with a 0-bit */;+  if (low0 == CHARSETSIZE)+    return IAny;  /* set has all bits set */+  for (high0 = CHARSETSIZE - 1; cs[high0] == 0xFF; high0--)+    /* find highest byte with a 0-bit; low0 is a sentinel */;+  if (high1 - low1 <= high0 - low0) {  /* range of 1s smaller than of 0s? */+    info->offset = low1;+    info->size = high1 - low1 + 1;+    info->deflt = 0;  /* all discharged bits were 0 */+  }+  else {+    info->offset = low0;+    info->size = high0 - low0 + 1;+    info->deflt = 0xFF;  /* all discharged bits were 1 */+  }+  info->cs = cs + info->offset;+  return ISet;+}+++/*+** Get a byte from a compact charset. If index is inside the charset+** range, get the byte from the supporting charset (correcting it+** by the offset). Otherwise, return the default for the set.+*/+byte getbytefromcharset (const charsetinfo *info, int index) {+  if (index < info->size)+    return info->cs[index];+  else return info->deflt;+}+++/*+** If 'tree' is a 'char' pattern (TSet, TChar, TAny, TFalse), convert it+** into a charset and return 1; else return 0.+*/+int tocharset (TTree *tree, Charset *cs) {+  switch (tree->tag) {+    case TChar: {  /* only one char */+      assert(0 <= tree->u.n && tree->u.n <= UCHAR_MAX);+      clearset(cs->cs);  /* erase all chars */+      setchar(cs->cs, tree->u.n);  /* add that one */+      return 1;+    }+    case TAny: {+      fillset(cs->cs, 0xFF);  /* add all characters to the set */+      return 1;+    }+    case TFalse: {+      clearset(cs->cs);  /* empty set */+      return 1;+    }+    case TSet: {  /* fill set */+      int i;+      fillset(cs->cs, tree->u.set.deflt);+      for (i = 0; i < tree->u.set.size; i++)+        cs->cs[tree->u.set.offset + i] = treebuffer(tree)[i];+      return 1;+    }+    default: return 0;+  }+}+++void tree2cset (TTree *tree, charsetinfo *info) {+  assert(tree->tag == TSet);+  info->offset = tree->u.set.offset;+  info->size = tree->u.set.size;+  info->deflt = tree->u.set.deflt;+  info->cs = treebuffer(tree);+}+
+ cbits/lpeg-1.1.0/lpcset.h view
@@ -0,0 +1,30 @@++#if !defined(lpset_h)+#define lpset_h++#include "lpcset.h"+#include "lpcode.h"+#include "lptree.h"+++/*+** Extra information for the result of 'charsettype'.  When result is+** IChar, 'offset' is the character.  When result is ISet, 'cs' is the+** supporting bit array (with offset included), 'offset' is the offset+** (in bytes), 'size' is the size (in bytes), and 'delt' is the default+** value for bytes outside the set.+*/+typedef struct {+  const byte *cs;+  int offset;+  int size;+  int deflt;+} charsetinfo;+++int tocharset (TTree *tree, Charset *cs);+Opcode charsettype (const byte *cs, charsetinfo *info);+byte getbytefromcharset (const charsetinfo *info, int index);+void tree2cset (TTree *tree, charsetinfo *info);++#endif
+ cbits/lpeg-1.1.0/lpprint.c view
@@ -0,0 +1,298 @@++#include <ctype.h>+#include <limits.h>+#include <stdio.h>+++#include "lptypes.h"+#include "lpprint.h"+#include "lpcode.h"+++#if defined(LPEG_DEBUG)++/*+** {======================================================+** Printing patterns (for debugging)+** =======================================================+*/+++void printcharset (const byte *st) {+  int i;+  printf("[");+  for (i = 0; i <= UCHAR_MAX; i++) {+    int first = i;+    while (i <= UCHAR_MAX && testchar(st, i)) i++;+    if (i - 1 == first)  /* unary range? */+      printf("(%02x)", first);+    else if (i - 1 > first)  /* non-empty range? */+      printf("(%02x-%02x)", first, i - 1);+  }+  printf("]");+}+++static void printIcharset (const Instruction *inst, const byte *buff) {+  byte cs[CHARSETSIZE];+  int i;+  printf("(%02x-%d) ", inst->i.aux2.set.offset, inst->i.aux2.set.size);+  clearset(cs);+  for (i = 0; i < CHARSETSIZE * 8; i++) {+    if (charinset(inst, buff, i))+      setchar(cs, i);+  }+  printcharset(cs);+}+++static void printTcharset (TTree *tree) {+  byte cs[CHARSETSIZE];+  int i;+  printf("(%02x-%d) ", tree->u.set.offset, tree->u.set.size);+  fillset(cs, tree->u.set.deflt);+  for (i = 0; i < tree->u.set.size; i++)+    cs[tree->u.set.offset + i] = treebuffer(tree)[i];+  printcharset(cs);+}+++static const char *capkind (int kind) {+  const char *const modes[] = {+    "close", "position", "constant", "backref",+    "argument", "simple", "table", "function", "accumulator",+    "query", "string", "num", "substitution", "fold",+    "runtime", "group"};+  return modes[kind];+}+++static void printjmp (const Instruction *op, const Instruction *p) {+  printf("-> %d", (int)(p + (p + 1)->offset - op));+}+++void printinst (const Instruction *op, const Instruction *p) {+  const char *const names[] = {+    "any", "char", "set",+    "testany", "testchar", "testset",+    "span", "utf-range", "behind",+    "ret", "end",+    "choice", "jmp", "call", "open_call",+    "commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup",+     "fullcapture", "opencapture", "closecapture", "closeruntime",+     "--"+  };+  printf("%02ld: %s ", (long)(p - op), names[p->i.code]);+  switch ((Opcode)p->i.code) {+    case IChar: {+      printf("'%c' (%02x)", p->i.aux1, p->i.aux1);+      break;+    }+    case ITestChar: {+      printf("'%c' (%02x)", p->i.aux1, p->i.aux1); printjmp(op, p);+      break;+    }+    case IUTFR: {+      printf("%d - %d", p[1].offset, utf_to(p));+      break;+    }+    case IFullCapture: {+      printf("%s (size = %d)  (idx = %d)",+             capkind(getkind(p)), getoff(p), p->i.aux2.key);+      break;+    }+    case IOpenCapture: {+      printf("%s (idx = %d)", capkind(getkind(p)), p->i.aux2.key);+      break;+    }+    case ISet: {+      printIcharset(p, (p+1)->buff);+      break;+    }+    case ITestSet: {+      printIcharset(p, (p+2)->buff); printjmp(op, p);+      break;+    }+    case ISpan: {+      printIcharset(p, (p+1)->buff);+      break;+    }+    case IOpenCall: {+      printf("-> %d", (p + 1)->offset);+      break;+    }+    case IBehind: {+      printf("%d", p->i.aux1);+      break;+    }+    case IJmp: case ICall: case ICommit: case IChoice:+    case IPartialCommit: case IBackCommit: case ITestAny: {+      printjmp(op, p);+      break;+    }+    default: break;+  }+  printf("\n");+}+++void printpatt (Instruction *p) {+  Instruction *op = p;+  uint n = op[-1].codesize - 1;+  while (p < op + n) {+    printinst(op, p);+    p += sizei(p);+  }+}+++static void printcap (Capture *cap, int ident) {+  while (ident--) printf(" ");+  printf("%s (idx: %d - size: %d) -> %lu  (%p)\n",+         capkind(cap->kind), cap->idx, cap->siz, (long)cap->index, (void*)cap);+}+++/*+** Print a capture and its nested captures+*/+static Capture *printcap2close (Capture *cap, int ident) {+  Capture *head = cap++;+  printcap(head, ident);  /* print head capture */+  while (capinside(head, cap))+    cap = printcap2close(cap, ident + 2);  /* print nested captures */+  if (isopencap(head)) {+    assert(isclosecap(cap));+    printcap(cap++, ident);  /* print and skip close capture */+  }+  return cap;+}+++void printcaplist (Capture *cap) {+  {  /* for debugging, print first a raw list of captures */+    Capture *c = cap;+    while (c->index != MAXINDT) { printcap(c, 0); c++; }+  }+  printf(">======\n");+  while (!isclosecap(cap))+    cap = printcap2close(cap, 0);+  printf("=======\n");+}++/* }====================================================== */+++/*+** {======================================================+** Printing trees (for debugging)+** =======================================================+*/++static const char *tagnames[] = {+  "char", "set", "any",+  "true", "false", "utf8.range",+  "rep",+  "seq", "choice",+  "not", "and",+  "call", "opencall", "rule", "xinfo", "grammar",+  "behind",+  "capture", "run-time"+};+++void printtree (TTree *tree, int ident) {+  int i;+  int sibs = numsiblings[tree->tag];+  for (i = 0; i < ident; i++) printf(" ");+  printf("%s", tagnames[tree->tag]);+  switch (tree->tag) {+    case TChar: {+      int c = tree->u.n;+      if (isprint(c))+        printf(" '%c'\n", c);+      else+        printf(" (%02X)\n", c);+      break;+    }+    case TSet: {+      printTcharset(tree);+      printf("\n");+      break;+    }+    case TUTFR: {+      assert(sib1(tree)->tag == TXInfo);+      printf(" %d (%02x %d) - %d (%02x %d) \n",+        tree->u.n, tree->key, tree->cap,+        sib1(tree)->u.n, sib1(tree)->key, sib1(tree)->cap);+      break;+    }+    case TOpenCall: case TCall: {+      assert(sib1(sib2(tree))->tag == TXInfo);+      printf(" key: %d  (rule: %d)\n", tree->key, sib1(sib2(tree))->u.n);+      break;+    }+    case TBehind: {+      printf(" %d\n", tree->u.n);+      break;+    }+    case TCapture: {+      printf(" kind: '%s'  key: %d\n", capkind(tree->cap), tree->key);+      break;+    }+    case TRule: {+      printf(" key: %d\n", tree->key);+      sibs = 1;  /* do not print 'sib2' (next rule) as a sibling */+      break;+    }+    case TXInfo: {+      printf(" n: %d\n", tree->u.n);+      break;+    }+    case TGrammar: {+      TTree *rule = sib1(tree);+      printf(" %d\n", tree->u.n);  /* number of rules */+      for (i = 0; i < tree->u.n; i++) {+        printtree(rule, ident + 2);+        rule = sib2(rule);+      }+      assert(rule->tag == TTrue);  /* sentinel */+      sibs = 0;  /* siblings already handled */+      break;+    }+    default:+      printf("\n");+      break;+  }+  if (sibs >= 1) {+    printtree(sib1(tree), ident + 2);+    if (sibs >= 2)+      printtree(sib2(tree), ident + 2);+  }+}+++void printktable (lua_State *L, int idx) {+  int n, i;+  lua_getuservalue(L, idx);+  if (lua_isnil(L, -1))  /* no ktable? */+    return;+  n = lua_rawlen(L, -1);+  printf("[");+  for (i = 1; i <= n; i++) {+    printf("%d = ", i);+    lua_rawgeti(L, -1, i);+    if (lua_isstring(L, -1))+      printf("%s  ", lua_tostring(L, -1));+    else+      printf("%s  ", lua_typename(L, lua_type(L, -1)));+    lua_pop(L, 1);+  }+  printf("]\n");+  /* leave ktable at the stack */+}++/* }====================================================== */++#endif
+ cbits/lpeg-1.1.0/lpprint.h view
@@ -0,0 +1,32 @@++#if !defined(lpprint_h)+#define lpprint_h+++#include "lptree.h"+#include "lpvm.h"+++#if defined(LPEG_DEBUG)++void printpatt (Instruction *p);+void printtree (TTree *tree, int ident);+void printktable (lua_State *L, int idx);+void printcharset (const byte *st);+void printcaplist (Capture *cap);+void printinst (const Instruction *op, const Instruction *p);++#else++#define printktable(L,idx)  \+	luaL_error(L, "function only implemented in debug mode")+#define printtree(tree,i)  \+	luaL_error(L, "function only implemented in debug mode")+#define printpatt(p)  \+	luaL_error(L, "function only implemented in debug mode")++#endif+++#endif+
+ cbits/lpeg-1.1.0/lptree.c view
@@ -0,0 +1,1399 @@++#include <ctype.h>+#include <limits.h>+#include <string.h>+++#include "lua.h"+#include "lauxlib.h"++#include "lptypes.h"+#include "lpcap.h"+#include "lpcode.h"+#include "lpprint.h"+#include "lptree.h"+#include "lpcset.h"+++/* number of siblings for each tree */+const byte numsiblings[] = {+  0, 0, 0,	/* char, set, any */+  0, 0, 0,	/* true, false, utf-range */+  1,		/* acc */+  2, 2,		/* seq, choice */+  1, 1,		/* not, and */+  0, 0, 2, 1, 1,  /* call, opencall, rule, prerule, grammar */+  1,  /* behind */+  1, 1  /* capture, runtime capture */+};+++static TTree *newgrammar (lua_State *L, int arg);+++/*+** returns a reasonable name for value at index 'idx' on the stack+*/+static const char *val2str (lua_State *L, int idx) {+  const char *k = lua_tostring(L, idx);+  if (k != NULL)+    return lua_pushfstring(L, "%s", k);+  else+    return lua_pushfstring(L, "(a %s)", luaL_typename(L, idx));+}+++/*+** Fix a TOpenCall into a TCall node, using table 'postable' to+** translate a key to its rule address in the tree. Raises an+** error if key does not exist.+*/+static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {+  int n;+  lua_rawgeti(L, -1, t->key);  /* get rule's name */+  lua_gettable(L, postable);  /* query name in position table */+  n = lua_tonumber(L, -1);  /* get (absolute) position */+  lua_pop(L, 1);  /* remove position */+  if (n == 0) {  /* no position? */+    lua_rawgeti(L, -1, t->key);  /* get rule's name again */+    luaL_error(L, "rule '%s' undefined in given grammar", val2str(L, -1));+  }+  t->tag = TCall;+  t->u.ps = n - (t - g);  /* position relative to node */+  assert(sib2(t)->tag == TRule);+  sib2(t)->key = t->key;  /* fix rule's key */+}+++/*+** Transform left associative constructions into right+** associative ones, for sequence and choice; that is:+** (t11 + t12) + t2  =>  t11 + (t12 + t2)+** (t11 * t12) * t2  =>  t11 * (t12 * t2)+** (that is, Op (Op t11 t12) t2 => Op t11 (Op t12 t2))+*/+static void correctassociativity (TTree *tree) {+  TTree *t1 = sib1(tree);+  assert(tree->tag == TChoice || tree->tag == TSeq);+  while (t1->tag == tree->tag) {+    int n1size = tree->u.ps - 1;  /* t1 == Op t11 t12 */+    int n11size = t1->u.ps - 1;+    int n12size = n1size - n11size - 1;+    memmove(sib1(tree), sib1(t1), n11size * sizeof(TTree)); /* move t11 */+    tree->u.ps = n11size + 1;+    sib2(tree)->tag = tree->tag;+    sib2(tree)->u.ps = n12size + 1;+  }+}+++/*+** Make final adjustments in a tree. Fix open calls in tree 't',+** making them refer to their respective rules or raising appropriate+** errors (if not inside a grammar). Correct associativity of associative+** constructions (making them right associative). Assume that tree's+** ktable is at the top of the stack (for error messages).+*/+static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {+ tailcall:+  switch (t->tag) {+    case TGrammar:  /* subgrammars were already fixed */+      return;+    case TOpenCall: {+      if (g != NULL)  /* inside a grammar? */+        fixonecall(L, postable, g, t);+      else {  /* open call outside grammar */+        lua_rawgeti(L, -1, t->key);+        luaL_error(L, "rule '%s' used outside a grammar", val2str(L, -1));+      }+      break;+    }+    case TSeq: case TChoice:+      correctassociativity(t);+      break;+  }+  switch (numsiblings[t->tag]) {+    case 1: /* finalfix(L, postable, g, sib1(t)); */+      t = sib1(t); goto tailcall;+    case 2:+      finalfix(L, postable, g, sib1(t));+      t = sib2(t); goto tailcall;  /* finalfix(L, postable, g, sib2(t)); */+    default: assert(numsiblings[t->tag] == 0); break;+  }+}++++/*+** {===================================================================+** KTable manipulation+**+** - The ktable of a pattern 'p' can be shared by other patterns that+** contain 'p' and no other constants. Because of this sharing, we+** should not add elements to a 'ktable' unless it was freshly created+** for the new pattern.+**+** - The maximum index in a ktable is USHRT_MAX, because trees and+** patterns use unsigned shorts to store those indices.+** ====================================================================+*/++/*+** Create a new 'ktable' to the pattern at the top of the stack.+*/+static void newktable (lua_State *L, int n) {+  lua_createtable(L, n, 0);  /* create a fresh table */+  lua_setuservalue(L, -2);  /* set it as 'ktable' for pattern */+}+++/*+** Add element 'idx' to 'ktable' of pattern at the top of the stack;+** Return index of new element.+** If new element is nil, does not add it to table (as it would be+** useless) and returns 0, as ktable[0] is always nil.+*/+static int addtoktable (lua_State *L, int idx) {+  if (lua_isnil(L, idx))  /* nil value? */+    return 0;+  else {+    int n;+    lua_getuservalue(L, -1);  /* get ktable from pattern */+    n = lua_rawlen(L, -1);+    if (n >= USHRT_MAX)+      luaL_error(L, "too many Lua values in pattern");+    lua_pushvalue(L, idx);  /* element to be added */+    lua_rawseti(L, -2, ++n);+    lua_pop(L, 1);  /* remove 'ktable' */+    return n;+  }+}+++/*+** Return the number of elements in the ktable at 'idx'.+** In Lua 5.2/5.3, default "environment" for patterns is nil, not+** a table. Treat it as an empty table. In Lua 5.1, assumes that+** the environment has no numeric indices (len == 0)+*/+static int ktablelen (lua_State *L, int idx) {+  if (!lua_istable(L, idx)) return 0;+  else return lua_rawlen(L, idx);+}+++/*+** Concatentate the contents of table 'idx1' into table 'idx2'.+** (Assume that both indices are negative.)+** Return the original length of table 'idx2' (or 0, if no+** element was added, as there is no need to correct any index).+*/+static int concattable (lua_State *L, int idx1, int idx2) {+  int i;+  int n1 = ktablelen(L, idx1);+  int n2 = ktablelen(L, idx2);+  if (n1 + n2 > USHRT_MAX)+    luaL_error(L, "too many Lua values in pattern");+  if (n1 == 0) return 0;  /* nothing to correct */+  for (i = 1; i <= n1; i++) {+    lua_rawgeti(L, idx1, i);+    lua_rawseti(L, idx2 - 1, n2 + i);  /* correct 'idx2' */+  }+  return n2;+}+++/*+** When joining 'ktables', constants from one of the subpatterns must+** be renumbered; 'correctkeys' corrects their indices (adding 'n'+** to each of them)+*/+static void correctkeys (TTree *tree, int n) {+  if (n == 0) return;  /* no correction? */+ tailcall:+  switch (tree->tag) {+    case TOpenCall: case TCall: case TRunTime: case TRule: {+      if (tree->key > 0)+        tree->key += n;+      break;+    }+    case TCapture: {+      if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)+        tree->key += n;+      break;+    }+    default: break;+  }+  switch (numsiblings[tree->tag]) {+    case 1:  /* correctkeys(sib1(tree), n); */+      tree = sib1(tree); goto tailcall;+    case 2:+      correctkeys(sib1(tree), n);+      tree = sib2(tree); goto tailcall;  /* correctkeys(sib2(tree), n); */+    default: assert(numsiblings[tree->tag] == 0); break;+  }+}+++/*+** Join the ktables from p1 and p2 the ktable for the new pattern at the+** top of the stack, reusing them when possible.+*/+static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {+  int n1, n2;+  lua_getuservalue(L, p1);  /* get ktables */+  lua_getuservalue(L, p2);+  n1 = ktablelen(L, -2);+  n2 = ktablelen(L, -1);+  if (n1 == 0 && n2 == 0)  /* are both tables empty? */+    lua_pop(L, 2);  /* nothing to be done; pop tables */+  else if (n2 == 0 || lp_equal(L, -2, -1)) {  /* 2nd table empty or equal? */+    lua_pop(L, 1);  /* pop 2nd table */+    lua_setuservalue(L, -2);  /* set 1st ktable into new pattern */+  }+  else if (n1 == 0) {  /* first table is empty? */+    lua_setuservalue(L, -3);  /* set 2nd table into new pattern */+    lua_pop(L, 1);  /* pop 1st table */+  }+  else {+    lua_createtable(L, n1 + n2, 0);  /* create ktable for new pattern */+    /* stack: new p; ktable p1; ktable p2; new ktable */+    concattable(L, -3, -1);  /* from p1 into new ktable */+    concattable(L, -2, -1);  /* from p2 into new ktable */+    lua_setuservalue(L, -4);  /* new ktable becomes 'p' environment */+    lua_pop(L, 2);  /* pop other ktables */+    correctkeys(t2, n1);  /* correction for indices from p2 */+  }+}+++/*+** copy 'ktable' of element 'idx' to new tree (on top of stack)+*/+static void copyktable (lua_State *L, int idx) {+  lua_getuservalue(L, idx);+  lua_setuservalue(L, -2);+}+++/*+** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable'+** from tree at the top of the stack, and correct corresponding+** tree.+*/+static void mergektable (lua_State *L, int idx, TTree *stree) {+  int n;+  lua_getuservalue(L, -1);  /* get ktables */+  lua_getuservalue(L, idx);+  n = concattable(L, -1, -2);+  lua_pop(L, 2);  /* remove both ktables */+  correctkeys(stree, n);+}+++/*+** Create a new 'ktable' to the pattern at the top of the stack, adding+** all elements from pattern 'p' (if not 0) plus element 'idx' to it.+** Return index of new element.+*/+static int addtonewktable (lua_State *L, int p, int idx) {+  newktable(L, 1);+  if (p)+    mergektable(L, p, NULL);+  return addtoktable(L, idx);+}++/* }====================================================== */+++/*+** {======================================================+** Tree generation+** =======================================================+*/++/*+** In 5.2, could use 'luaL_testudata'...+*/+static int testpattern (lua_State *L, int idx) {+  if (lua_touserdata(L, idx)) {  /* value is a userdata? */+    if (lua_getmetatable(L, idx)) {  /* does it have a metatable? */+      luaL_getmetatable(L, PATTERN_T);+      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */+        lua_pop(L, 2);  /* remove both metatables */+        return 1;+      }+    }+  }+  return 0;+}+++static Pattern *getpattern (lua_State *L, int idx) {+  return (Pattern *)luaL_checkudata(L, idx, PATTERN_T);+}+++static int getsize (lua_State *L, int idx) {+  return (lua_rawlen(L, idx) - offsetof(Pattern, tree)) / sizeof(TTree);+}+++static TTree *gettree (lua_State *L, int idx, int *len) {+  Pattern *p = getpattern(L, idx);+  if (len)+    *len = getsize(L, idx);+  return p->tree;+}+++/*+** create a pattern followed by a tree with 'len' nodes. Set its+** uservalue (the 'ktable') equal to its metatable. (It could be any+** empty sequence; the metatable is at hand here, so we use it.)+*/+static TTree *newtree (lua_State *L, int len) {+  size_t size = offsetof(Pattern, tree) + len * sizeof(TTree);+  Pattern *p = (Pattern *)lua_newuserdata(L, size);+  luaL_getmetatable(L, PATTERN_T);+  lua_pushvalue(L, -1);+  lua_setuservalue(L, -3);+  lua_setmetatable(L, -2);+  p->code = NULL;+  return p->tree;+}+++static TTree *newleaf (lua_State *L, int tag) {+  TTree *tree = newtree(L, 1);+  tree->tag = tag;+  return tree;+}+++/*+** Create a tree for a charset, optimizing for special cases: empty set,+** full set, and singleton set.+*/+static TTree *newcharset (lua_State *L, byte *cs) {+  charsetinfo info;+  Opcode op = charsettype(cs, &info);+  switch (op) {+    case IFail: return newleaf(L, TFalse);  /* empty set */+    case IAny: return newleaf(L, TAny);  /* full set */+    case IChar: {  /* singleton set */+      TTree *tree =newleaf(L, TChar);+      tree->u.n = info.offset;+      return tree;+    }+    default: {  /* regular set */+      int i;+      int bsize =  /* tree size in bytes */+                  (int)offsetof(TTree, u.set.bitmap) + info.size;+      TTree *tree = newtree(L, bytes2slots(bsize));+      assert(op == ISet);+      tree->tag = TSet;+      tree->u.set.offset = info.offset;+      tree->u.set.size = info.size;+      tree->u.set.deflt = info.deflt;+      for (i = 0; i < info.size; i++) {+        assert(&treebuffer(tree)[i] < (byte*)tree + bsize);+        treebuffer(tree)[i] = cs[info.offset + i];+      }+      return tree;+    }+  }+}+++/*+** Add to tree a sequence where first sibling is 'sib' (with size+** 'sibsize'); return position for second sibling.+*/+static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {+  tree->tag = TSeq; tree->u.ps = sibsize + 1;+  memcpy(sib1(tree), sib, sibsize * sizeof(TTree));+  return sib2(tree);+}+++/*+** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got+** from the array 's' (or 0 if array is NULL). (TSeq is binary, so it+** must build a sequence of sequence of sequence...)+*/+static void fillseq (TTree *tree, int tag, int n, const char *s) {+  int i;+  for (i = 0; i < n - 1; i++) {  /* initial n-1 copies of Seq tag; Seq ... */+    tree->tag = TSeq; tree->u.ps = 2;+    sib1(tree)->tag = tag;+    sib1(tree)->u.n = s ? (byte)s[i] : 0;+    tree = sib2(tree);+  }+  tree->tag = tag;  /* last one does not need TSeq */+  tree->u.n = s ? (byte)s[i] : 0;+}+++/*+** Numbers as patterns:+** 0 == true (always match); n == TAny repeated 'n' times;+** -n == not (TAny repeated 'n' times)+*/+static TTree *numtree (lua_State *L, int n) {+  if (n == 0)+    return newleaf(L, TTrue);+  else {+    TTree *tree, *nd;+    if (n > 0)+      tree = nd = newtree(L, 2 * n - 1);+    else {  /* negative: code it as !(-n) */+      n = -n;+      tree = newtree(L, 2 * n);+      tree->tag = TNot;+      nd = sib1(tree);+    }+    fillseq(nd, TAny, n, NULL);  /* sequence of 'n' any's */+    return tree;+  }+}+++/*+** Convert value at index 'idx' to a pattern+*/+static TTree *getpatt (lua_State *L, int idx, int *len) {+  TTree *tree;+  switch (lua_type(L, idx)) {+    case LUA_TSTRING: {+      size_t slen;+      const char *s = lua_tolstring(L, idx, &slen);  /* get string */+      if (slen == 0)  /* empty? */+        tree = newleaf(L, TTrue);  /* always match */+      else {+        tree = newtree(L, 2 * (slen - 1) + 1);+        fillseq(tree, TChar, slen, s);  /* sequence of 'slen' chars */+      }+      break;+    }+    case LUA_TNUMBER: {+      int n = lua_tointeger(L, idx);+      tree = numtree(L, n);+      break;+    }+    case LUA_TBOOLEAN: {+      tree = (lua_toboolean(L, idx) ? newleaf(L, TTrue) : newleaf(L, TFalse));+      break;+    }+    case LUA_TTABLE: {+      tree = newgrammar(L, idx);+      break;+    }+    case LUA_TFUNCTION: {+      tree = newtree(L, 2);+      tree->tag = TRunTime;+      tree->key = addtonewktable(L, 0, idx);+      sib1(tree)->tag = TTrue;+      break;+    }+    default: {+      return gettree(L, idx, len);+    }+  }+  lua_replace(L, idx);  /* put new tree into 'idx' slot */+  if (len)+    *len = getsize(L, idx);+  return tree;+}+++/*+** create a new tree, whith a new root and one sibling.+** Sibling must be on the Lua stack, at index 1.+*/+static TTree *newroot1sib (lua_State *L, int tag) {+  int s1;+  TTree *tree1 = getpatt(L, 1, &s1);+  TTree *tree = newtree(L, 1 + s1);  /* create new tree */+  tree->tag = tag;+  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));+  copyktable(L, 1);+  return tree;+}+++/*+** create a new tree, whith a new root and 2 siblings.+** Siblings must be on the Lua stack, first one at index 1.+*/+static TTree *newroot2sib (lua_State *L, int tag) {+  int s1, s2;+  TTree *tree1 = getpatt(L, 1, &s1);+  TTree *tree2 = getpatt(L, 2, &s2);+  TTree *tree = newtree(L, 1 + s1 + s2);  /* create new tree */+  tree->tag = tag;+  tree->u.ps =  1 + s1;+  memcpy(sib1(tree), tree1, s1 * sizeof(TTree));+  memcpy(sib2(tree), tree2, s2 * sizeof(TTree));+  joinktables(L, 1, sib2(tree), 2);+  return tree;+}+++static int lp_P (lua_State *L) {+  luaL_checkany(L, 1);+  getpatt(L, 1, NULL);+  lua_settop(L, 1);+  return 1;+}+++/*+** sequence operator; optimizations:+** false x => false, x true => x, true x => x+** (cannot do x . false => false because x may have runtime captures)+*/+static int lp_seq (lua_State *L) {+  TTree *tree1 = getpatt(L, 1, NULL);+  TTree *tree2 = getpatt(L, 2, NULL);+  if (tree1->tag == TFalse || tree2->tag == TTrue)+    lua_pushvalue(L, 1);  /* false . x == false, x . true = x */+  else if (tree1->tag == TTrue)+    lua_pushvalue(L, 2);  /* true . x = x */+  else+    newroot2sib(L, TSeq);+  return 1;+}+++/*+** choice operator; optimizations:+** charset / charset => charset+** true / x => true, x / false => x, false / x => x+** (x / true is not equivalent to true)+*/+static int lp_choice (lua_State *L) {+  Charset st1, st2;+  TTree *t1 = getpatt(L, 1, NULL);+  TTree *t2 = getpatt(L, 2, NULL);+  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {+    loopset(i, st1.cs[i] |= st2.cs[i]);+    newcharset(L, st1.cs);+  }+  else if (nofail(t1) || t2->tag == TFalse)+    lua_pushvalue(L, 1);  /* true / x => true, x / false => x */+  else if (t1->tag == TFalse)+    lua_pushvalue(L, 2);  /* false / x => x */+  else+    newroot2sib(L, TChoice);+  return 1;+}+++/*+** p^n+*/+static int lp_star (lua_State *L) {+  int size1;+  int n = (int)luaL_checkinteger(L, 2);+  TTree *tree1 = getpatt(L, 1, &size1);+  if (n >= 0) {  /* seq tree1 (seq tree1 ... (seq tree1 (rep tree1))) */+    TTree *tree = newtree(L, (n + 1) * (size1 + 1));+    if (nullable(tree1))+      luaL_error(L, "loop body may accept empty string");+    while (n--)  /* repeat 'n' times */+      tree = seqaux(tree, tree1, size1);+    tree->tag = TRep;+    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));+  }+  else {  /* choice (seq tree1 ... choice tree1 true ...) true */+    TTree *tree;+    n = -n;+    /* size = (choice + seq + tree1 + true) * n, but the last has no seq */+    tree = newtree(L, n * (size1 + 3) - 1);+    for (; n > 1; n--) {  /* repeat (n - 1) times */+      tree->tag = TChoice; tree->u.ps = n * (size1 + 3) - 2;+      sib2(tree)->tag = TTrue;+      tree = sib1(tree);+      tree = seqaux(tree, tree1, size1);+    }+    tree->tag = TChoice; tree->u.ps = size1 + 1;+    sib2(tree)->tag = TTrue;+    memcpy(sib1(tree), tree1, size1 * sizeof(TTree));+  }+  copyktable(L, 1);+  return 1;+}+++/*+** #p == &p+*/+static int lp_and (lua_State *L) {+  newroot1sib(L, TAnd);+  return 1;+}+++/*+** -p == !p+*/+static int lp_not (lua_State *L) {+  newroot1sib(L, TNot);+  return 1;+}+++/*+** [t1 - t2] == Seq (Not t2) t1+** If t1 and t2 are charsets, make their difference.+*/+static int lp_sub (lua_State *L) {+  Charset st1, st2;+  int s1, s2;+  TTree *t1 = getpatt(L, 1, &s1);+  TTree *t2 = getpatt(L, 2, &s2);+  if (tocharset(t1, &st1) && tocharset(t2, &st2)) {+    loopset(i, st1.cs[i] &= ~st2.cs[i]);+    newcharset(L, st1.cs);+  }+  else {+    TTree *tree = newtree(L, 2 + s1 + s2);+    tree->tag = TSeq;  /* sequence of... */+    tree->u.ps =  2 + s2;+    sib1(tree)->tag = TNot;  /* ...not... */+    memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree));  /* ...t2 */+    memcpy(sib2(tree), t1, s1 * sizeof(TTree));  /* ... and t1 */+    joinktables(L, 1, sib1(tree), 2);+  }+  return 1;+}+++static int lp_set (lua_State *L) {+  size_t l;+  const char *s = luaL_checklstring(L, 1, &l);+  byte buff[CHARSETSIZE];+  clearset(buff);+  while (l--) {+    setchar(buff, (byte)(*s));+    s++;+  }+  newcharset(L, buff);+  return 1;+}+++static int lp_range (lua_State *L) {+  int arg;+  int top = lua_gettop(L);+  byte buff[CHARSETSIZE];+  clearset(buff);+  for (arg = 1; arg <= top; arg++) {+    int c;+    size_t l;+    const char *r = luaL_checklstring(L, arg, &l);+    luaL_argcheck(L, l == 2, arg, "range must have two characters");+    for (c = (byte)r[0]; c <= (byte)r[1]; c++)+      setchar(buff, c);+  }+  newcharset(L, buff);+  return 1;+}+++/*+** Fills a tree node with basic information about the UTF-8 code point+** 'cpu': its value in 'n', its length in 'cap', and its first byte in+** 'key'+*/+static void codeutftree (lua_State *L, TTree *t, lua_Unsigned cpu, int arg) {+  int len, fb, cp;+  cp = (int)cpu;+  if (cp <= 0x7f) {  /* one byte? */+    len = 1;+    fb = cp;+  } else if (cp <= 0x7ff) {+    len = 2;+    fb = 0xC0 | (cp >> 6);+  } else if (cp <= 0xffff) {+    len = 3;+    fb = 0xE0 | (cp >> 12);+  }+  else {+    luaL_argcheck(L, cpu <= 0x10ffffu, arg, "invalid code point");+    len = 4;+    fb = 0xF0 | (cp >> 18);+  }+  t->u.n = cp;+  t->cap = len;+  t->key = fb;+}+++static int lp_utfr (lua_State *L) {+  lua_Unsigned from = (lua_Unsigned)luaL_checkinteger(L, 1);+  lua_Unsigned to = (lua_Unsigned)luaL_checkinteger(L, 2);+  luaL_argcheck(L, from <= to, 2, "empty range");+  if (to <= 0x7f) {  /* ascii range? */+    uint f;+    byte buff[CHARSETSIZE];  /* code it as a regular charset */+    clearset(buff);+    for (f = (int)from; f <= to; f++)+      setchar(buff, f);+    newcharset(L, buff);+  }+  else {  /* multi-byte utf-8 range */+    TTree *tree = newtree(L, 2);+    tree->tag = TUTFR;+    codeutftree(L, tree, from, 1);+    sib1(tree)->tag = TXInfo;+    codeutftree(L, sib1(tree), to, 2);+  }+  return 1;+}+++/*+** Look-behind predicate+*/+static int lp_behind (lua_State *L) {+  TTree *tree;+  TTree *tree1 = getpatt(L, 1, NULL);+  int n = fixedlen(tree1);+  luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");+  luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");+  luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");+  tree = newroot1sib(L, TBehind);+  tree->u.n = n;+  return 1;+}+++/*+** Create a non-terminal+*/+static int lp_V (lua_State *L) {+  TTree *tree = newleaf(L, TOpenCall);+  luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");+  tree->key = addtonewktable(L, 0, 1);+  return 1;+}+++/*+** Create a tree for a non-empty capture, with a body and+** optionally with an associated Lua value (at index 'labelidx' in the+** stack)+*/+static int capture_aux (lua_State *L, int cap, int labelidx) {+  TTree *tree = newroot1sib(L, TCapture);+  tree->cap = cap;+  tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);+  return 1;+}+++/*+** Fill a tree with an empty capture, using an empty (TTrue) sibling.+** (The 'key' field must be filled by the caller to finish the tree.)+*/+static TTree *auxemptycap (TTree *tree, int cap) {+  tree->tag = TCapture;+  tree->cap = cap;+  sib1(tree)->tag = TTrue;+  return tree;+}+++/*+** Create a tree for an empty capture.+*/+static TTree *newemptycap (lua_State *L, int cap, int key) {+  TTree *tree = auxemptycap(newtree(L, 2), cap);+  tree->key = key;+  return tree;+}+++/*+** Create a tree for an empty capture with an associated Lua value.+*/+static TTree *newemptycapkey (lua_State *L, int cap, int idx) {+  TTree *tree = auxemptycap(newtree(L, 2), cap);+  tree->key = addtonewktable(L, 0, idx);+  return tree;+}+++/*+** Captures with syntax p / v+** (function capture, query capture, string capture, or number capture)+*/+static int lp_divcapture (lua_State *L) {+  switch (lua_type(L, 2)) {+    case LUA_TFUNCTION: return capture_aux(L, Cfunction, 2);+    case LUA_TTABLE: return capture_aux(L, Cquery, 2);+    case LUA_TSTRING: return capture_aux(L, Cstring, 2);+    case LUA_TNUMBER: {+      int n = lua_tointeger(L, 2);+      TTree *tree = newroot1sib(L, TCapture);+      luaL_argcheck(L, 0 <= n && n <= SHRT_MAX, 1, "invalid number");+      tree->cap = Cnum;+      tree->key = n;+      return 1;+    }+    default:+      return luaL_error(L, "unexpected %s as 2nd operand to LPeg '/'",+                           luaL_typename(L, 2));+  }+}+++static int lp_acccapture (lua_State *L) {+  return capture_aux(L, Cacc, 2);+}+++static int lp_substcapture (lua_State *L) {+  return capture_aux(L, Csubst, 0);+}+++static int lp_tablecapture (lua_State *L) {+  return capture_aux(L, Ctable, 0);+}+++static int lp_groupcapture (lua_State *L) {+  if (lua_isnoneornil(L, 2))+    return capture_aux(L, Cgroup, 0);+  else+    return capture_aux(L, Cgroup, 2);+}+++static int lp_foldcapture (lua_State *L) {+  luaL_checktype(L, 2, LUA_TFUNCTION);+  return capture_aux(L, Cfold, 2);+}+++static int lp_simplecapture (lua_State *L) {+  return capture_aux(L, Csimple, 0);+}+++static int lp_poscapture (lua_State *L) {+  newemptycap(L, Cposition, 0);+  return 1;+}+++static int lp_argcapture (lua_State *L) {+  int n = (int)luaL_checkinteger(L, 1);+  luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");+  newemptycap(L, Carg, n);+  return 1;+}+++static int lp_backref (lua_State *L) {+  luaL_checkany(L, 1);+  newemptycapkey(L, Cbackref, 1);+  return 1;+}+++/*+** Constant capture+*/+static int lp_constcapture (lua_State *L) {+  int i;+  int n = lua_gettop(L);  /* number of values */+  if (n == 0)  /* no values? */+    newleaf(L, TTrue);  /* no capture */+  else if (n == 1)+    newemptycapkey(L, Cconst, 1);  /* single constant capture */+  else {  /* create a group capture with all values */+    TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2);+    newktable(L, n);  /* create a 'ktable' for new tree */+    tree->tag = TCapture;+    tree->cap = Cgroup;+    tree->key = 0;+    tree = sib1(tree);+    for (i = 1; i <= n - 1; i++) {+      tree->tag = TSeq;+      tree->u.ps = 3;  /* skip TCapture and its sibling */+      auxemptycap(sib1(tree), Cconst);+      sib1(tree)->key = addtoktable(L, i);+      tree = sib2(tree);+    }+    auxemptycap(tree, Cconst);+    tree->key = addtoktable(L, i);+  }+  return 1;+}+++static int lp_matchtime (lua_State *L) {+  TTree *tree;+  luaL_checktype(L, 2, LUA_TFUNCTION);+  tree = newroot1sib(L, TRunTime);+  tree->key = addtonewktable(L, 1, 2);+  return 1;+}++/* }====================================================== */+++/*+** {======================================================+** Grammar - Tree generation+** =======================================================+*/++/*+** push on the stack the index and the pattern for the+** initial rule of grammar at index 'arg' in the stack;+** also add that index into position table.+*/+static void getfirstrule (lua_State *L, int arg, int postab) {+  lua_rawgeti(L, arg, 1);  /* access first element */+  if (lua_isstring(L, -1)) {  /* is it the name of initial rule? */+    lua_pushvalue(L, -1);  /* duplicate it to use as key */+    lua_gettable(L, arg);  /* get associated rule */+  }+  else {+    lua_pushinteger(L, 1);  /* key for initial rule */+    lua_insert(L, -2);  /* put it before rule */+  }+  if (!testpattern(L, -1)) {  /* initial rule not a pattern? */+    if (lua_isnil(L, -1))+      luaL_error(L, "grammar has no initial rule");+    else+      luaL_error(L, "initial rule '%s' is not a pattern", lua_tostring(L, -2));+  }+  lua_pushvalue(L, -2);  /* push key */+  lua_pushinteger(L, 1);  /* push rule position (after TGrammar) */+  lua_settable(L, postab);  /* insert pair at position table */+}++/*+** traverse grammar at index 'arg', pushing all its keys and patterns+** into the stack. Create a new table (before all pairs key-pattern) to+** collect all keys and their associated positions in the final tree+** (the "position table").+** Return the number of rules and (in 'totalsize') the total size+** for the new tree.+*/+static int collectrules (lua_State *L, int arg, int *totalsize) {+  int n = 1;  /* to count number of rules */+  int postab = lua_gettop(L) + 1;  /* index of position table */+  int size;  /* accumulator for total size */+  lua_newtable(L);  /* create position table */+  getfirstrule(L, arg, postab);+  size = 3 + getsize(L, postab + 2);  /* TGrammar + TRule + TXInfo + rule */+  lua_pushnil(L);  /* prepare to traverse grammar table */+  while (lua_next(L, arg) != 0) {+    if (lua_tonumber(L, -2) == 1 ||+        lp_equal(L, -2, postab + 1)) {  /* initial rule? */+      lua_pop(L, 1);  /* remove value (keep key for lua_next) */+      continue;+    }+    if (!testpattern(L, -1))  /* value is not a pattern? */+      luaL_error(L, "rule '%s' is not a pattern", val2str(L, -2));+    luaL_checkstack(L, LUA_MINSTACK, "grammar has too many rules");+    lua_pushvalue(L, -2);  /* push key (to insert into position table) */+    lua_pushinteger(L, size);+    lua_settable(L, postab);+    size += 2 + getsize(L, -1);  /* add 'TRule + TXInfo + rule' to size */+    lua_pushvalue(L, -2);  /* push key (for next lua_next) */+    n++;+  }+  *totalsize = size + 1;  /* space for 'TTrue' finishing list of rules */+  return n;+}+++static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {+  int i;+  TTree *nd = sib1(grammar);  /* auxiliary pointer to traverse the tree */+  for (i = 0; i < n; i++) {  /* add each rule into new tree */+    int ridx = frule + 2*i + 1;  /* index of i-th rule */+    int rulesize;+    TTree *rn = gettree(L, ridx, &rulesize);+    TTree *pr = sib1(nd);  /* points to rule's prerule */+    nd->tag = TRule;+    nd->key = 0;  /* will be fixed when rule is used */+    pr->tag = TXInfo;+    pr->u.n = i;  /* rule number */+    nd->u.ps = rulesize + 2;  /* point to next rule */+    memcpy(sib1(pr), rn, rulesize * sizeof(TTree));  /* copy rule */+    mergektable(L, ridx, sib1(nd));  /* merge its ktable into new one */+    nd = sib2(nd);  /* move to next rule */+  }+  nd->tag = TTrue;  /* finish list of rules */+}+++/*+** Check whether a tree has potential infinite loops+*/+static int checkloops (TTree *tree) {+ tailcall:+  if (tree->tag == TRep && nullable(sib1(tree)))+    return 1;+  else if (tree->tag == TGrammar)+    return 0;  /* sub-grammars already checked */+  else {+    switch (numsiblings[tree->tag]) {+      case 1:  /* return checkloops(sib1(tree)); */+        tree = sib1(tree); goto tailcall;+      case 2:+        if (checkloops(sib1(tree))) return 1;+        /* else return checkloops(sib2(tree)); */+        tree = sib2(tree); goto tailcall;+      default: assert(numsiblings[tree->tag] == 0); return 0;+    }+  }+}+++/*+** Give appropriate error message for 'verifyrule'. If a rule appears+** twice in 'passed', there is path from it back to itself without+** advancing the subject.+*/+static int verifyerror (lua_State *L, unsigned short *passed, int npassed) {+  int i, j;+  for (i = npassed - 1; i >= 0; i--) {  /* search for a repetition */+    for (j = i - 1; j >= 0; j--) {+      if (passed[i] == passed[j]) {+        lua_rawgeti(L, -1, passed[i]);  /* get rule's key */+        return luaL_error(L, "rule '%s' may be left recursive", val2str(L, -1));+      }+    }+  }+  return luaL_error(L, "too many left calls in grammar");+}+++/*+** Check whether a rule can be left recursive; raise an error in that+** case; otherwise return 1 iff pattern is nullable.+** The return value is used to check sequences, where the second pattern+** is only relevant if the first is nullable.+** Parameter 'nb' works as an accumulator, to allow tail calls in+** choices. ('nb' true makes function returns true.)+** Parameter 'passed' is a list of already visited rules, 'npassed'+** counts the elements in 'passed'.+** Assume ktable at the top of the stack.+*/+static int verifyrule (lua_State *L, TTree *tree, unsigned short *passed,+                                     int npassed, int nb) {+ tailcall:+  switch (tree->tag) {+    case TChar: case TSet: case TAny:+    case TFalse: case TUTFR:+      return nb;  /* cannot pass from here */+    case TTrue:+    case TBehind:  /* look-behind cannot have calls */+      return 1;+    case TNot: case TAnd: case TRep:+      /* return verifyrule(L, sib1(tree), passed, npassed, 1); */+      tree = sib1(tree); nb = 1; goto tailcall;+    case TCapture: case TRunTime: case TXInfo:+      /* return verifyrule(L, sib1(tree), passed, npassed, nb); */+      tree = sib1(tree); goto tailcall;+    case TCall:+      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */+      tree = sib2(tree); goto tailcall;+    case TSeq:  /* only check 2nd child if first is nb */+      if (!verifyrule(L, sib1(tree), passed, npassed, 0))+        return nb;+      /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */+      tree = sib2(tree); goto tailcall;+    case TChoice:  /* must check both children */+      nb = verifyrule(L, sib1(tree), passed, npassed, nb);+      /* return verifyrule(L, sib2(tree), passed, npassed, nb); */+      tree = sib2(tree); goto tailcall;+    case TRule:+      if (npassed >= MAXRULES)  /* too many steps? */+        return verifyerror(L, passed, npassed);  /* error */+      else {+        passed[npassed++] = tree->key;  /* add rule to path */+        /* return verifyrule(L, sib1(tree), passed, npassed); */+        tree = sib1(tree); goto tailcall;+      }+    case TGrammar:+      return nullable(tree);  /* sub-grammar cannot be left recursive */+    default: assert(0); return 0;+  }+}+++static void verifygrammar (lua_State *L, TTree *grammar) {+  unsigned short passed[MAXRULES];+  TTree *rule;+  /* check left-recursive rules */+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {+    if (rule->key == 0) continue;  /* unused rule */+    verifyrule(L, sib1(rule), passed, 0, 0);+  }+  assert(rule->tag == TTrue);+  /* check infinite loops inside rules */+  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {+    if (rule->key == 0) continue;  /* unused rule */+    if (checkloops(sib1(rule))) {+      lua_rawgeti(L, -1, rule->key);  /* get rule's key */+      luaL_error(L, "empty loop in rule '%s'", val2str(L, -1));+    }+  }+  assert(rule->tag == TTrue);+}+++/*+** Give a name for the initial rule if it is not referenced+*/+static void initialrulename (lua_State *L, TTree *grammar, int frule) {+  if (sib1(grammar)->key == 0) {  /* initial rule is not referenced? */+    int n = lua_rawlen(L, -1) + 1;  /* index for name */+    lua_pushvalue(L, frule);  /* rule's name */+    lua_rawseti(L, -2, n);  /* ktable was on the top of the stack */+    sib1(grammar)->key = n;+  }+}+++static TTree *newgrammar (lua_State *L, int arg) {+  int treesize;+  int frule = lua_gettop(L) + 2;  /* position of first rule's key */+  int n = collectrules(L, arg, &treesize);+  TTree *g = newtree(L, treesize);+  luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");+  g->tag = TGrammar;  g->u.n = n;+  lua_newtable(L);  /* create 'ktable' */+  lua_setuservalue(L, -2);+  buildgrammar(L, g, frule, n);+  lua_getuservalue(L, -1);  /* get 'ktable' for new tree */+  finalfix(L, frule - 1, g, sib1(g));+  initialrulename(L, g, frule);+  verifygrammar(L, g);+  lua_pop(L, 1);  /* remove 'ktable' */+  lua_insert(L, -(n * 2 + 2));  /* move new table to proper position */+  lua_pop(L, n * 2 + 1);  /* remove position table + rule pairs */+  return g;  /* new table at the top of the stack */+}++/* }====================================================== */+++static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {+  lua_getuservalue(L, idx);  /* push 'ktable' (may be used by 'finalfix') */+  finalfix(L, 0, NULL, p->tree);+  lua_pop(L, 1);  /* remove 'ktable' */+  return compile(L, p, getsize(L, idx));+}+++static int lp_printtree (lua_State *L) {+  TTree *tree = getpatt(L, 1, NULL);+  int c = lua_toboolean(L, 2);+  if (c) {+    lua_getuservalue(L, 1);  /* push 'ktable' (may be used by 'finalfix') */+    finalfix(L, 0, NULL, tree);+    lua_pop(L, 1);  /* remove 'ktable' */+  }+  printktable(L, 1);+  printtree(tree, 0);+  return 0;+}+++static int lp_printcode (lua_State *L) {+  Pattern *p = getpattern(L, 1);+  printktable(L, 1);+  if (p->code == NULL)  /* not compiled yet? */+    prepcompile(L, p, 1);+  printpatt(p->code);+  return 0;+}+++/*+** Get the initial position for the match, interpreting negative+** values from the end of the subject+*/+static size_t initposition (lua_State *L, size_t len) {+  lua_Integer ii = luaL_optinteger(L, 3, 1);+  if (ii > 0) {  /* positive index? */+    if ((size_t)ii <= len)  /* inside the string? */+      return (size_t)ii - 1;  /* return it (corrected to 0-base) */+    else return len;  /* crop at the end */+  }+  else {  /* negative index */+    if ((size_t)(-ii) <= len)  /* inside the string? */+      return len - ((size_t)(-ii));  /* return position from the end */+    else return 0;  /* crop at the beginning */+  }+}+++/*+** Main match function+*/+static int lp_match (lua_State *L) {+  Capture capture[INITCAPSIZE];+  const char *r;+  size_t l;+  Pattern *p = (getpatt(L, 1, NULL), getpattern(L, 1));+  Instruction *code = (p->code != NULL) ? p->code : prepcompile(L, p, 1);+  const char *s = luaL_checklstring(L, SUBJIDX, &l);+  size_t i = initposition(L, l);+  int ptop = lua_gettop(L);+  luaL_argcheck(L, l < MAXINDT, SUBJIDX, "subject too long");+  lua_pushnil(L);  /* initialize subscache */+  lua_pushlightuserdata(L, capture);  /* initialize caplistidx */+  lua_getuservalue(L, 1);  /* initialize ktableidx */+  r = match(L, s, s + i, s + l, code, capture, ptop);+  if (r == NULL) {+    lua_pushnil(L);+    return 1;+  }+  return getcaptures(L, s, r, ptop);+}++++/*+** {======================================================+** Library creation and functions not related to matching+** =======================================================+*/++/* maximum limit for stack size */+#define MAXLIM		(INT_MAX / 100)++static int lp_setmax (lua_State *L) {+  lua_Integer lim = luaL_checkinteger(L, 1);+  luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");+  lua_settop(L, 1);+  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);+  return 0;+}+++static int lp_type (lua_State *L) {+  if (testpattern(L, 1))+    lua_pushliteral(L, "pattern");+  else+    lua_pushnil(L);+  return 1;+}+++int lp_gc (lua_State *L) {+  Pattern *p = getpattern(L, 1);+  freecode(L, p);  /* delete code block */+  return 0;+}+++/*+** Create a charset representing a category of characters, given by+** the predicate 'catf'.+*/+static void createcat (lua_State *L, const char *catname, int (catf) (int)) {+  int c;+  byte buff[CHARSETSIZE];+  clearset(buff);+  for (c = 0; c <= UCHAR_MAX; c++)+    if (catf(c)) setchar(buff, c);+  newcharset(L, buff);+  lua_setfield(L, -2, catname);+}+++static int lp_locale (lua_State *L) {+  if (lua_isnoneornil(L, 1)) {+    lua_settop(L, 0);+    lua_createtable(L, 0, 12);+  }+  else {+    luaL_checktype(L, 1, LUA_TTABLE);+    lua_settop(L, 1);+  }+  createcat(L, "alnum", isalnum);+  createcat(L, "alpha", isalpha);+  createcat(L, "cntrl", iscntrl);+  createcat(L, "digit", isdigit);+  createcat(L, "graph", isgraph);+  createcat(L, "lower", islower);+  createcat(L, "print", isprint);+  createcat(L, "punct", ispunct);+  createcat(L, "space", isspace);+  createcat(L, "upper", isupper);+  createcat(L, "xdigit", isxdigit);+  return 1;+}+++static struct luaL_Reg pattreg[] = {+  {"ptree", lp_printtree},+  {"pcode", lp_printcode},+  {"match", lp_match},+  {"B", lp_behind},+  {"V", lp_V},+  {"C", lp_simplecapture},+  {"Cc", lp_constcapture},+  {"Cmt", lp_matchtime},+  {"Cb", lp_backref},+  {"Carg", lp_argcapture},+  {"Cp", lp_poscapture},+  {"Cs", lp_substcapture},+  {"Ct", lp_tablecapture},+  {"Cf", lp_foldcapture},+  {"Cg", lp_groupcapture},+  {"P", lp_P},+  {"S", lp_set},+  {"R", lp_range},+  {"utfR", lp_utfr},+  {"locale", lp_locale},+  {"version", NULL},+  {"setmaxstack", lp_setmax},+  {"type", lp_type},+  {NULL, NULL}+};+++static struct luaL_Reg metareg[] = {+  {"__mul", lp_seq},+  {"__add", lp_choice},+  {"__pow", lp_star},+  {"__gc", lp_gc},+  {"__len", lp_and},+  {"__div", lp_divcapture},+  {"__mod", lp_acccapture},+  {"__unm", lp_not},+  {"__sub", lp_sub},+  {NULL, NULL}+};+++int luaopen_lpeg (lua_State *L);+int luaopen_lpeg (lua_State *L) {+  luaL_newmetatable(L, PATTERN_T);+  lua_pushnumber(L, MAXBACK);  /* initialize maximum backtracking */+  lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);+  luaL_setfuncs(L, metareg, 0);+  luaL_newlib(L, pattreg);+  lua_pushvalue(L, -1);+  lua_setfield(L, -3, "__index");+  lua_pushliteral(L, "LPeg " VERSION);+  lua_setfield(L, -2, "version");+  return 1;+}++/* }====================================================== */
+ cbits/lpeg-1.1.0/lptree.h view
@@ -0,0 +1,92 @@++#if !defined(lptree_h)+#define lptree_h+++#include "lptypes.h"+++/*+** types of trees+*/+typedef enum TTag {+  TChar = 0,  /* 'n' = char */+  TSet,  /* the set is encoded in 'u.set' and the next 'u.set.size' bytes */+  TAny,+  TTrue,+  TFalse,+  TUTFR,  /* range of UTF-8 codepoints; 'n' has initial codepoint;+             'cap' has length; 'key' has first byte;+             extra info is similar for end codepoint */+  TRep,  /* 'sib1'* */+  TSeq,  /* 'sib1' 'sib2' */+  TChoice,  /* 'sib1' / 'sib2' */+  TNot,  /* !'sib1' */+  TAnd,  /* &'sib1' */+  TCall,  /* ktable[key] is rule's key; 'sib2' is rule being called */+  TOpenCall,  /* ktable[key] is rule's key */+  TRule,  /* ktable[key] is rule's key (but key == 0 for unused rules);+             'sib1' is rule's pattern pre-rule; 'sib2' is next rule;+             extra info 'n' is rule's sequential number */+  TXInfo,  /* extra info */+  TGrammar,  /* 'sib1' is initial (and first) rule */+  TBehind,  /* 'sib1' is pattern, 'n' is how much to go back */+  TCapture,  /* captures: 'cap' is kind of capture (enum 'CapKind');+                ktable[key] is Lua value associated with capture;+                'sib1' is capture body */+  TRunTime  /* run-time capture: 'key' is Lua function;+               'sib1' is capture body */+} TTag;+++/*+** Tree trees+** The first child of a tree (if there is one) is immediately after+** the tree.  A reference to a second child (ps) is its position+** relative to the position of the tree itself.+*/+typedef struct TTree {+  byte tag;+  byte cap;  /* kind of capture (if it is a capture) */+  unsigned short key;  /* key in ktable for Lua data (0 if no key) */+  union {+    int ps;  /* occasional second child */+    int n;  /* occasional counter */+    struct {+      byte offset;  /* compact set offset (in bytes) */+      byte size;  /* compact set size (in bytes) */+      byte deflt;  /* default value */+      byte bitmap[1];  /* bitmap (open array) */+    } set;  /* for compact sets */+  } u;+} TTree;+++/* access to charset */+#define treebuffer(t)      ((t)->u.set.bitmap)+++/*+** A complete pattern has its tree plus, if already compiled,+** its corresponding code+*/+typedef struct Pattern {+  union Instruction *code;+  TTree tree[1];+} Pattern;+++/* number of children for each tree */+extern const byte numsiblings[];++/* access to children */+#define sib1(t)         ((t) + 1)+#define sib2(t)         ((t) + (t)->u.ps)+++++++#endif+
+ cbits/lpeg-1.1.0/lptypes.h view
@@ -0,0 +1,150 @@+/*+** LPeg - PEG pattern matching for Lua+** Copyright 2007-2023, Lua.org & PUC-Rio  (see 'lpeg.html' for license)+** written by Roberto Ierusalimschy+*/++#if !defined(lptypes_h)+#define lptypes_h+++#include <assert.h>+#include <limits.h>+#include <string.h>++#include "lua.h"+++#define VERSION         "1.1.0"+++#define PATTERN_T	"lpeg-pattern"+#define MAXSTACKIDX	"lpeg-maxstack"+++/*+** compatibility with Lua 5.1+*/+#if (LUA_VERSION_NUM == 501)++#define lp_equal	lua_equal++#define lua_getuservalue	lua_getfenv+#define lua_setuservalue	lua_setfenv++#define lua_rawlen		lua_objlen++#define luaL_setfuncs(L,f,n)	luaL_register(L,NULL,f)+#define luaL_newlib(L,f)	luaL_register(L,"lpeg",f)++typedef size_t lua_Unsigned;++#endif+++#if !defined(lp_equal)+#define lp_equal(L,idx1,idx2)  lua_compare(L,(idx1),(idx2),LUA_OPEQ)+#endif+++/* default maximum size for call/backtrack stack */+#if !defined(MAXBACK)+#define MAXBACK         400+#endif+++/* maximum number of rules in a grammar (limited by 'unsigned short') */+#if !defined(MAXRULES)+#define MAXRULES        1000+#endif++++/* initial size for capture's list */+#define INITCAPSIZE	32+++/* index, on Lua stack, for subject */+#define SUBJIDX		2++/* number of fixed arguments to 'match' (before capture arguments) */+#define FIXEDARGS	3++/* index, on Lua stack, for capture list */+#define caplistidx(ptop)	((ptop) + 2)++/* index, on Lua stack, for pattern's ktable */+#define ktableidx(ptop)		((ptop) + 3)++/* index, on Lua stack, for backtracking stack */+#define stackidx(ptop)	((ptop) + 4)++++typedef unsigned char byte;++typedef unsigned int uint;+++#define BITSPERCHAR		8++#define CHARSETSIZE		((UCHAR_MAX/BITSPERCHAR) + 1)++++typedef struct Charset {+  byte cs[CHARSETSIZE];+} Charset;++++#define loopset(v,b)    { int v; for (v = 0; v < CHARSETSIZE; v++) {b;} }++#define fillset(s,c)	memset(s,c,CHARSETSIZE)+#define clearset(s)	fillset(s,0)++/* number of slots needed for 'n' bytes */+#define bytes2slots(n)  (((n) - 1u) / (uint)sizeof(TTree) + 1u)++/* set 'b' bit in charset 'cs' */+#define setchar(cs,b)   ((cs)[(b) >> 3] |= (1 << ((b) & 7)))+++/*+** in capture instructions, 'kind' of capture and its offset are+** packed in field 'aux', 4 bits for each+*/+#define getkind(op)		((op)->i.aux1 & 0xF)+#define getoff(op)		(((op)->i.aux1 >> 4) & 0xF)+#define joinkindoff(k,o)	((k) | ((o) << 4))++#define MAXOFF		0xF+#define MAXAUX		0xFF+++/* maximum number of bytes to look behind */+#define MAXBEHIND	MAXAUX+++/* maximum size (in elements) for a pattern */+#define MAXPATTSIZE	(SHRT_MAX - 10)+++/* size (in instructions) for l bytes (l > 0) */+#define instsize(l) ((int)(((l) + (uint)sizeof(Instruction) - 1u) \+			/ (uint)sizeof(Instruction)))+++/* size (in elements) for a ISet instruction */+#define CHARSETINSTSIZE		(1 + instsize(CHARSETSIZE))++/* size (in elements) for a IFunc instruction */+#define funcinstsize(p)		((p)->i.aux + 2)++++#define testchar(st,c)	((((uint)(st)[((c) >> 3)]) >> ((c) & 7)) & 1)+++#endif+
+ cbits/lpeg-1.1.0/lpvm.c view
@@ -0,0 +1,455 @@++#include <limits.h>+#include <string.h>+++#include "lua.h"+#include "lauxlib.h"++#include "lpcap.h"+#include "lptypes.h"+#include "lpvm.h"+#include "lpprint.h"+++/* initial size for call/backtrack stack */+#if !defined(INITBACK)+#define INITBACK	MAXBACK+#endif+++#define getoffset(p)	(((p) + 1)->offset)++static const Instruction giveup = {{IGiveup, 0, {0}}};+++int charinset (const Instruction *i, const byte *buff, uint c) {+  c -= i->i.aux2.set.offset;+  if (c >= ((uint)i->i.aux2.set.size  /* size in instructions... */+           * (uint)sizeof(Instruction)  /* in bytes... */+           * 8u))  /* in bits */+    return i->i.aux1;  /* out of range; return default value */+  return testchar(buff, c);+}+++/*+** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.+*/+static const char *utf8_decode (const char *o, int *val) {+  static const uint limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFFu};+  const unsigned char *s = (const unsigned char *)o;+  uint c = s[0];  /* first byte */+  uint res = 0;  /* final result */+  if (c < 0x80)  /* ascii? */+    res = c;+  else {+    int count = 0;  /* to count number of continuation bytes */+    while (c & 0x40) {  /* still have continuation bytes? */+      int cc = s[++count];  /* read next byte */+      if ((cc & 0xC0) != 0x80)  /* not a continuation byte? */+        return NULL;  /* invalid byte sequence */+      res = (res << 6) | (cc & 0x3F);  /* add lower 6 bits from cont. byte */+      c <<= 1;  /* to test next bit */+    }+    res |= (c & 0x7F) << (count * 5);  /* add first byte */+    if (count > 3 || res > 0x10FFFFu || res <= limits[count])+      return NULL;  /* invalid byte sequence */+    s += count;  /* skip continuation bytes read */+  }+  *val = res;+  return (const char *)s + 1;  /* +1 to include first byte */+}+++/*+** {======================================================+** Virtual Machine+** =======================================================+*/+++typedef struct Stack {+  const char *s;  /* saved position (or NULL for calls) */+  const Instruction *p;  /* next instruction */+  int caplevel;+} Stack;+++#define getstackbase(L, ptop)	((Stack *)lua_touserdata(L, stackidx(ptop)))+++/*+** Ensures the size of array 'capture' (with size '*capsize' and+** 'captop' elements being used) is enough to accomodate 'n' extra+** elements plus one.  (Because several opcodes add stuff to the capture+** array, it is simpler to ensure the array always has at least one free+** slot upfront and check its size later.)+*/++/* new size in number of elements cannot overflow integers, and new+   size in bytes cannot overflow size_t. */+#define MAXNEWSIZE  \+    (((size_t)INT_MAX) <= (~(size_t)0 / sizeof(Capture)) ?  \+     ((size_t)INT_MAX) : (~(size_t)0 / sizeof(Capture)))++static Capture *growcap (lua_State *L, Capture *capture, int *capsize,+                                       int captop, int n, int ptop) {+  if (*capsize - captop > n)+    return capture;  /* no need to grow array */+  else {  /* must grow */+    Capture *newc;+    uint newsize = captop + n + 1;  /* minimum size needed */+    if (newsize < (MAXNEWSIZE / 3) * 2)+      newsize += newsize / 2;  /* 1.5 that size, if not too big */+    else if (newsize < (MAXNEWSIZE / 9) * 8)+      newsize += newsize / 8;  /* else, try 9/8 that size */+    else+      luaL_error(L, "too many captures");+    newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));+    memcpy(newc, capture, captop * sizeof(Capture));+    *capsize = newsize;+    lua_replace(L, caplistidx(ptop));+    return newc;+  }+}+++/*+** Double the size of the stack+*/+static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {+  Stack *stack = getstackbase(L, ptop);+  Stack *newstack;+  int n = *stacklimit - stack;  /* current stack size */+  int max, newn;+  lua_getfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);+  max = lua_tointeger(L, -1);  /* maximum allowed size */+  lua_pop(L, 1);+  if (n >= max)  /* already at maximum size? */+    luaL_error(L, "backtrack stack overflow (current limit is %d)", max);+  newn = 2 * n;  /* new size */+  if (newn > max) newn = max;+  newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));+  memcpy(newstack, stack, n * sizeof(Stack));+  lua_replace(L, stackidx(ptop));+  *stacklimit = newstack + newn;+  return newstack + n;  /* return next position */+}+++/*+** Interpret the result of a dynamic capture: false -> fail;+** true -> keep current position; number -> next position.+** Return new subject position. 'fr' is stack index where+** is the result; 'curr' is current subject position; 'limit'+** is subject's size.+*/+static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {+  lua_Integer res;+  if (!lua_toboolean(L, fr)) {  /* false value? */+    lua_settop(L, fr - 1);  /* remove results */+    return -1;  /* and fail */+  }+  else if (lua_isboolean(L, fr))  /* true? */+    res = curr;  /* keep current position */+  else {+    res = lua_tointeger(L, fr) - 1;  /* new position */+    if (res < curr || res > limit)+      luaL_error(L, "invalid position returned by match-time capture");+  }+  lua_remove(L, fr);  /* remove first result (offset) */+  return res;+}+++/*+** Add capture values returned by a dynamic capture to the list+** 'capture', nested inside a group. 'fd' indexes the first capture+** value, 'n' is the number of values (at least 1). The open group+** capture is already in 'capture', before the place for the new entries.+*/+static void adddyncaptures (Index_t index, Capture *capture, int n, int fd) {+  int i;+  assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);+  capture[-1].idx = 0;  /* make group capture an anonymous group */+  for (i = 0; i < n; i++) {  /* add runtime captures */+    capture[i].kind = Cruntime;+    capture[i].siz = 1;  /* mark it as closed */+    capture[i].idx = fd + i;  /* stack index of capture value */+    capture[i].index = index;+  }+  capture[n].kind = Cclose;  /* close group */+  capture[n].siz = 1;+  capture[n].index = index;+}+++/*+** Remove dynamic captures from the Lua stack (called in case of failure)+*/+static int removedyncap (lua_State *L, Capture *capture,+                         int level, int last) {+  int id = finddyncap(capture + level, capture + last);  /* index of 1st cap. */+  int top = lua_gettop(L);+  if (id == 0) return 0;  /* no dynamic captures? */+  lua_settop(L, id - 1);  /* remove captures */+  return top - id + 1;  /* number of values removed */+}+++/*+** Find the corresponding 'open' capture before 'cap', when that capture+** can become a full capture. If a full capture c1 is followed by an+** empty capture c2, there is no way to know whether c2 is inside+** c1. So, full captures can enclose only captures that start *before*+** its end.+*/+static Capture *findopen (Capture *cap, Index_t currindex) {+  int i;+  cap--;  /* check last capture */+  /* Must it be inside current one, but starts where current one ends? */+  if (!isopencap(cap) && cap->index == currindex)+    return NULL;  /* current one cannot be a full capture */+  /* else, look for an 'open' capture */+  for (i = 0; i < MAXLOP; i++, cap--) {+    if (currindex - cap->index >= UCHAR_MAX)+      return NULL;  /* capture too long for a full capture */+    else if (isopencap(cap))  /* open capture? */+      return cap;  /* that's the one to be closed */+    else if (cap->kind == Cclose)+      return NULL;  /* a full capture should not nest a non-full one */+  }+  return NULL;  /* not found within allowed search limit */+}+++/*+** Opcode interpreter+*/+const char *match (lua_State *L, const char *o, const char *s, const char *e,+                   Instruction *op, Capture *capture, int ptop) {+  Stack stackbase[INITBACK];+  Stack *stacklimit = stackbase + INITBACK;+  Stack *stack = stackbase;  /* point to first empty slot in stack */+  int capsize = INITCAPSIZE;+  int captop = 0;  /* point to first empty slot in captures */+  int ndyncap = 0;  /* number of dynamic captures (in Lua stack) */+  const Instruction *p = op;  /* current instruction */+  stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;+  lua_pushlightuserdata(L, stackbase);+  for (;;) {+#if defined(DEBUG)+      printf("-------------------------------------\n");+      printcaplist(capture, capture + captop);+      printf("s: |%s| stck:%d, dyncaps:%d, caps:%d  ",+             s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop);+      printinst(op, p);+#endif+    assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);+    switch ((Opcode)p->i.code) {+      case IEnd: {+        assert(stack == getstackbase(L, ptop) + 1);+        capture[captop].kind = Cclose;+        capture[captop].index = MAXINDT;+        return s;+      }+      case IGiveup: {+        assert(stack == getstackbase(L, ptop));+        return NULL;+      }+      case IRet: {+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s == NULL);+        p = (--stack)->p;+        continue;+      }+      case IAny: {+        if (s < e) { p++; s++; }+        else goto fail;+        continue;+      }+      case IUTFR: {+        int codepoint;+        if (s >= e)+          goto fail;+        s = utf8_decode (s, &codepoint);+        if (s && p[1].offset <= codepoint && codepoint <= utf_to(p))+          p += 2;+        else+          goto fail;+        continue;+      }+      case ITestAny: {+        if (s < e) p += 2;+        else p += getoffset(p);+        continue;+      }+      case IChar: {+        if ((byte)*s == p->i.aux1 && s < e) { p++; s++; }+        else goto fail;+        continue;+      }+      case ITestChar: {+        if ((byte)*s == p->i.aux1 && s < e) p += 2;+        else p += getoffset(p);+        continue;+      }+      case ISet: {+        uint c = (byte)*s;+        if (charinset(p, (p+1)->buff, c) && s < e)+          { p += 1 + p->i.aux2.set.size; s++; }+        else goto fail;+        continue;+      }+      case ITestSet: {+        uint c = (byte)*s;+        if (charinset(p, (p + 2)->buff, c) && s < e)+          p += 2 + p->i.aux2.set.size;+        else p += getoffset(p);+        continue;+      }+      case IBehind: {+        int n = p->i.aux1;+        if (n > s - o) goto fail;+        s -= n; p++;+        continue;+      }+      case ISpan: {+        for (; s < e; s++) {+          uint c = (byte)*s;+          if (!charinset(p, (p+1)->buff, c)) break;+        }+        p += 1 + p->i.aux2.set.size;+        continue;+      }+      case IJmp: {+        p += getoffset(p);+        continue;+      }+      case IChoice: {+        if (stack == stacklimit)+          stack = doublestack(L, &stacklimit, ptop);+        stack->p = p + getoffset(p);+        stack->s = s;+        stack->caplevel = captop;+        stack++;+        p += 2;+        continue;+      }+      case ICall: {+        if (stack == stacklimit)+          stack = doublestack(L, &stacklimit, ptop);+        stack->s = NULL;+        stack->p = p + 2;  /* save return address */+        stack++;+        p += getoffset(p);+        continue;+      }+      case ICommit: {+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);+        stack--;+        p += getoffset(p);+        continue;+      }+      case IPartialCommit: {+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);+        (stack - 1)->s = s;+        (stack - 1)->caplevel = captop;+        p += getoffset(p);+        continue;+      }+      case IBackCommit: {+        assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);+        s = (--stack)->s;+        if (ndyncap > 0)  /* are there matchtime captures? */+          ndyncap -= removedyncap(L, capture, stack->caplevel, captop);+        captop = stack->caplevel;+        p += getoffset(p);+        continue;+      }+      case IFailTwice:+        assert(stack > getstackbase(L, ptop));+        stack--;+        /* FALLTHROUGH */+      case IFail:+      fail: { /* pattern failed: try to backtrack */+        do {  /* remove pending calls */+          assert(stack > getstackbase(L, ptop));+          s = (--stack)->s;+        } while (s == NULL);+        if (ndyncap > 0)  /* is there matchtime captures? */+          ndyncap -= removedyncap(L, capture, stack->caplevel, captop);+        captop = stack->caplevel;+        p = stack->p;+#if defined(DEBUG)+        printf("**FAIL**\n");+#endif+        continue;+      }+      case ICloseRunTime: {+        CapState cs;+        int rem, res, n;+        int fr = lua_gettop(L) + 1;  /* stack index of first result */+        cs.reclevel = 0; cs.L = L;+        cs.s = o; cs.ocap = capture; cs.ptop = ptop;+        n = runtimecap(&cs, capture + captop, s, &rem);  /* call function */+        captop -= n;  /* remove nested captures */+        ndyncap -= rem;  /* update number of dynamic captures */+        fr -= rem;  /* 'rem' items were popped from Lua stack */+        res = resdyncaptures(L, fr, s - o, e - o);  /* get result */+        if (res == -1)  /* fail? */+          goto fail;+        s = o + res;  /* else update current position */+        n = lua_gettop(L) - fr + 1;  /* number of new captures */+        ndyncap += n;  /* update number of dynamic captures */+        if (n == 0)  /* no new captures? */+          captop--;  /* remove open group */+        else {  /* new captures; keep original open group */+          if (fr + n >= SHRT_MAX)+            luaL_error(L, "too many results in match-time capture");+          /* add new captures + close group to 'capture' list */+          capture = growcap(L, capture, &capsize, captop, n + 1, ptop);+          adddyncaptures(s - o, capture + captop, n, fr);+          captop += n + 1;  /* new captures + close group */+        }+        p++;+        continue;+      }+      case ICloseCapture: {+        Capture *open = findopen(capture + captop, s - o);+        assert(captop > 0);+        if (open) {  /* if possible, turn capture into a full capture */+          open->siz = (s - o) - open->index + 1;+          p++;+          continue;+        }+        else {  /* must create a close capture */+          capture[captop].siz = 1;  /* mark entry as closed */+          capture[captop].index = s - o;+          goto pushcapture;+        }+      }+      case IOpenCapture:+        capture[captop].siz = 0;  /* mark entry as open */+        capture[captop].index = s - o;+        goto pushcapture;+      case IFullCapture:+        capture[captop].siz = getoff(p) + 1;  /* save capture size */+        capture[captop].index = s - o - getoff(p);+        /* goto pushcapture; */+      pushcapture: {+        capture[captop].idx = p->i.aux2.key;+        capture[captop].kind = getkind(p);+        captop++;+        capture = growcap(L, capture, &capsize, captop, 0, ptop);+        p++;+        continue;+      }+      default: assert(0); return NULL;+    }+  }+}++/* }====================================================== */++
+ cbits/lpeg-1.1.0/lpvm.h view
@@ -0,0 +1,79 @@++#if !defined(lpvm_h)+#define lpvm_h++#include "lpcap.h"+++/*+** About Character sets in instructions: a set is a bit map with an+** initial offset, in bits, and a size, in number of instructions.+** aux1 has the default value for the bits outsize that range.+*/+++/* Virtual Machine's instructions */+typedef enum Opcode {+  IAny, /* if no char, fail */+  IChar,  /* if char != aux1, fail */+  ISet,  /* if char not in set, fail */+  ITestAny,  /* in no char, jump to 'offset' */+  ITestChar,  /* if char != aux1, jump to 'offset' */+  ITestSet,  /* if char not in set, jump to 'offset' */+  ISpan,  /* read a span of chars in set */+  IUTFR,  /* if codepoint not in range [offset, utf_to], fail */+  IBehind,  /* walk back 'aux1' characters (fail if not possible) */+  IRet,  /* return from a rule */+  IEnd,  /* end of pattern */+  IChoice,  /* stack a choice; next fail will jump to 'offset' */+  IJmp,  /* jump to 'offset' */+  ICall,  /* call rule at 'offset' */+  IOpenCall,  /* call rule number 'key' (must be closed to a ICall) */+  ICommit,  /* pop choice and jump to 'offset' */+  IPartialCommit,  /* update top choice to current position and jump */+  IBackCommit,  /* backtrack like "fail" but jump to its own 'offset' */+  IFailTwice,  /* pop one choice and then fail */+  IFail,  /* go back to saved state on choice and jump to saved offset */+  IGiveup,  /* internal use */+  IFullCapture,  /* complete capture of last 'off' chars */+  IOpenCapture,  /* start a capture */+  ICloseCapture,+  ICloseRunTime,+  IEmpty  /* to fill empty slots left by optimizations */+} Opcode;+++/*+** All array of instructions has a 'codesize' as its first element+** and is referred by a pointer to its second element, which is the+** first actual opcode.+*/+typedef union Instruction {+  struct Inst {+    byte code;+    byte aux1;+    union {+      short key;+      struct {+        byte offset;+        byte size;+      } set;+    } aux2;+  } i;+  int offset;+  uint codesize;+  byte buff[1];+} Instruction;+++/* extract 24-bit value from an instruction */+#define utf_to(inst)	(((inst)->i.aux2.key << 8) | (inst)->i.aux1)+++int charinset (const Instruction *i, const byte *buff, uint c);+const char *match (lua_State *L, const char *o, const char *s, const char *e,+                   Instruction *op, Capture *capture, int ptop);+++#endif+
cbits/re.c view
@@ -4,7 +4,7 @@  int luaopen_re(lua_State *L); int luaopen_re(lua_State *L) {-  luaL_loadstring(L, cbits_lpeg_1_0_2_re_lua);+  luaL_loadstring(L, cbits_lpeg_1_1_0_re_lua);   lua_call(L, 0, 1);   return 1; }
cbits/re.h view
@@ -1,47 +1,55 @@-unsigned char cbits_lpeg_1_0_2_re_lua[] = {-  0x2d, 0x2d, 0x20, 0x24, 0x49, 0x64, 0x3a, 0x20, 0x72, 0x65, 0x2e, 0x6c,-  0x75, 0x61, 0x20, 0x24, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x69, 0x6d, 0x70,-  0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,-  0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x75,-  0x6c, 0x65, 0x73, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x6f,-  0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x79, 0x70, 0x65,-  0x2c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72,-  0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65,-  0x72, 0x2c, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x69,-  0x6e, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, 0x6c, 0x6f,-  0x63, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74,-  0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65,-  0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61,-  0x6c, 0x20, 0x6d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,-  0x65, 0x22, 0x6c, 0x70, 0x65, 0x67, 0x22, 0x0a, 0x0a, 0x2d, 0x2d, 0x20,-  0x27, 0x6d, 0x27, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,-  0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x72, 0x73,-  0x65, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,-  0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x27, 0x6d, 0x6d, 0x27, 0x20,-  0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,-  0x20, 0x74, 0x6f, 0x0a, 0x2d, 0x2d, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74,-  0x65, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,-  0x73, 0x3b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x2c, 0x20,-  0x27, 0x72, 0x65, 0x27, 0x20, 0x72, 0x75, 0x6e, 0x73, 0x20, 0x6f, 0x6e,-  0x20, 0x27, 0x6d, 0x27, 0x2c, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69,-  0x6e, 0x67, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x0a,-  0x2d, 0x2d, 0x20, 0x6f, 0x6e, 0x20, 0x27, 0x6d, 0x6d, 0x27, 0x0a, 0x6c,-  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6d, 0x20, 0x3d, 0x20, 0x6d, 0x0a,-  0x0a, 0x2d, 0x2d, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x27,-  0x73, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a,-  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x74, 0x20, 0x3d, 0x20, 0x67,-  0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28,-  0x6d, 0x6d, 0x2e, 0x50, 0x28, 0x30, 0x29, 0x29, 0x0a, 0x0a, 0x0a, 0x0a,-  0x2d, 0x2d, 0x20, 0x4e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x67,-  0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,-  0x65, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69,-  0x73, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a, 0x6c, 0x6f, 0x63, 0x61,-  0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20,-  0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x0a, 0x69, 0x66, 0x20,-  0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x22,-  0x4c, 0x75, 0x61, 0x20, 0x35, 0x2e, 0x32, 0x22, 0x20, 0x74, 0x68, 0x65,-  0x6e, 0x20, 0x5f, 0x45, 0x4e, 0x56, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c,-  0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,+unsigned char cbits_lpeg_1_1_0_re_lua[] = {+  0x2d, 0x2d, 0x0a, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,+  0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x32,+  0x33, 0x2c, 0x20, 0x4c, 0x75, 0x61, 0x2e, 0x6f, 0x72, 0x67, 0x20, 0x26,+  0x20, 0x50, 0x55, 0x43, 0x2d, 0x52, 0x69, 0x6f, 0x20, 0x20, 0x28, 0x73,+  0x65, 0x65, 0x20, 0x27, 0x6c, 0x70, 0x65, 0x67, 0x2e, 0x68, 0x74, 0x6d,+  0x6c, 0x27, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e,+  0x73, 0x65, 0x29, 0x0a, 0x2d, 0x2d, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74,+  0x65, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x52, 0x6f, 0x62, 0x65, 0x72, 0x74,+  0x6f, 0x20, 0x49, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x69, 0x6d, 0x73,+  0x63, 0x68, 0x79, 0x0a, 0x2d, 0x2d, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x69,+  0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x66, 0x75, 0x6e, 0x63,+  0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x6f,+  0x64, 0x75, 0x6c, 0x65, 0x73, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,+  0x74, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x79,+  0x70, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x65,+  0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x6e, 0x75, 0x6d,+  0x62, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x70,+  0x72, 0x69, 0x6e, 0x74, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a,+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74,+  0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74,+  0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x6c, 0x6f,+  0x63, 0x61, 0x6c, 0x20, 0x6d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75,+  0x69, 0x72, 0x65, 0x22, 0x6c, 0x70, 0x65, 0x67, 0x22, 0x0a, 0x0a, 0x2d,+  0x2d, 0x20, 0x27, 0x6d, 0x27, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62,+  0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61,+  0x72, 0x73, 0x65, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69,+  0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x27, 0x6d, 0x6d,+  0x27, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73,+  0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, 0x2d, 0x2d, 0x20, 0x63, 0x72, 0x65,+  0x61, 0x74, 0x65, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69,+  0x6f, 0x6e, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,+  0x2c, 0x20, 0x27, 0x72, 0x65, 0x27, 0x20, 0x72, 0x75, 0x6e, 0x73, 0x20,+  0x6f, 0x6e, 0x20, 0x27, 0x6d, 0x27, 0x2c, 0x20, 0x63, 0x72, 0x65, 0x61,+  0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e,+  0x73, 0x0a, 0x2d, 0x2d, 0x20, 0x6f, 0x6e, 0x20, 0x27, 0x6d, 0x6d, 0x27,+  0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x6d, 0x20, 0x3d, 0x20,+  0x6d, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72,+  0x6e, 0x73, 0x27, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c,+  0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x74, 0x20, 0x3d,+  0x20, 0x67, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c,+  0x65, 0x28, 0x6d, 0x6d, 0x2e, 0x50, 0x28, 0x30, 0x29, 0x29, 0x0a, 0x0a,+  0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,+  0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f,+  0x4e, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x4e, 0x6f, 0x20, 0x6d, 0x6f, 0x72,+  0x65, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x61, 0x63, 0x63,+  0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,+  0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a, 0x5f,+  0x45, 0x4e, 0x56, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x2d, 0x2d, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x6e, 0x6f,+  0x20, 0x68, 0x61, 0x72, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x4c, 0x75, 0x61,+  0x20, 0x35, 0x2e, 0x31, 0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,   0x20, 0x61, 0x6e, 0x79, 0x20, 0x3d, 0x20, 0x6d, 0x2e, 0x50, 0x28, 0x31,   0x29, 0x0a, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x50, 0x72, 0x65, 0x2d, 0x64,   0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73,@@ -260,282 +268,283 @@   0x29, 0x29, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x6f, 0x70, 0x74,   0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,   0x6d, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x0a,-  0x20, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x66, 0x28, 0x69, 0x74, 0x65,-  0x6d, 0x20, 0x2a, 0x20, 0x28, 0x69, 0x74, 0x65, 0x6d, 0x20, 0x2d, 0x20,-  0x22, 0x5d, 0x22, 0x29, 0x5e, 0x30, 0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f,-  0x5f, 0x61, 0x64, 0x64, 0x29, 0x20, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x2a, 0x20, 0x28, 0x69, 0x74, 0x65, 0x6d, 0x20, 0x2a, 0x20,+  0x28, 0x28, 0x69, 0x74, 0x65, 0x6d, 0x20, 0x25, 0x20, 0x6d, 0x74, 0x2e,+  0x5f, 0x5f, 0x61, 0x64, 0x64, 0x29, 0x20, 0x2d, 0x20, 0x22, 0x5d, 0x22,+  0x29, 0x5e, 0x30, 0x29, 0x20, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75,-  0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x63, 0x2c, 0x20, 0x70,-  0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x20, 0x3d,-  0x3d, 0x20, 0x22, 0x5e, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e,-  0x79, 0x20, 0x2d, 0x20, 0x70, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x20, 0x65,-  0x6e, 0x64, 0x0a, 0x20, 0x20, 0x2a, 0x20, 0x22, 0x5d, 0x22, 0x0a, 0x0a,-  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,-  0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x64, 0x65, 0x66, 0x20, 0x28, 0x74,-  0x2c, 0x20, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x70, 0x29, 0x0a, 0x20, 0x20,-  0x69, 0x66, 0x20, 0x74, 0x5b, 0x6b, 0x5d, 0x20, 0x74, 0x68, 0x65, 0x6e,-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22,-  0x27, 0x22, 0x2e, 0x2e, 0x6b, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x61, 0x6c,-  0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,-  0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x22,-  0x29, 0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20,-  0x20, 0x74, 0x5b, 0x6b, 0x5d, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x70, 0x0a,-  0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,-  0x72, 0x6e, 0x20, 0x74, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f,-  0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,-  0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x64, 0x65, 0x66, 0x20, 0x28, 0x6e,-  0x2c, 0x20, 0x72, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,-  0x61, 0x64, 0x64, 0x64, 0x65, 0x66, 0x28, 0x7b, 0x6e, 0x7d, 0x2c, 0x20,-  0x6e, 0x2c, 0x20, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x0a,-  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,-  0x6f, 0x6e, 0x20, 0x4e, 0x54, 0x20, 0x28, 0x6e, 0x2c, 0x20, 0x62, 0x29,-  0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x20,-  0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x72, 0x72,-  0x6f, 0x72, 0x28, 0x22, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x27, 0x22, 0x2e,-  0x2e, 0x6e, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20,-  0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x20, 0x61, 0x20, 0x67, 0x72,-  0x61, 0x6d, 0x6d, 0x61, 0x72, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6c,-  0x73, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x6d,-  0x2e, 0x56, 0x28, 0x6e, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,-  0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,-  0x65, 0x78, 0x70, 0x20, 0x3d, 0x20, 0x6d, 0x2e, 0x50, 0x7b, 0x20, 0x22,-  0x45, 0x78, 0x70, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x45, 0x78, 0x70, 0x20,-  0x3d, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x28, 0x20, 0x6d, 0x2e, 0x56, 0x22,-  0x47, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x72, 0x22, 0x0a, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d,-  0x2e, 0x43, 0x66, 0x28, 0x6d, 0x2e, 0x56, 0x22, 0x53, 0x65, 0x71, 0x22,-  0x20, 0x2a, 0x20, 0x28, 0x22, 0x2f, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20,-  0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x53, 0x65, 0x71, 0x22, 0x29, 0x5e,-  0x30, 0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x61, 0x64, 0x64, 0x29,-  0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x53, 0x65, 0x71, 0x20, 0x3d, 0x20,-  0x6d, 0x2e, 0x43, 0x66, 0x28, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6d, 0x2e,-  0x50, 0x22, 0x22, 0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x50,-  0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x5e, 0x30, 0x20, 0x2c, 0x20, 0x6d,-  0x74, 0x2e, 0x5f, 0x5f, 0x6d, 0x75, 0x6c, 0x29, 0x0a, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x28, 0x23, 0x73, 0x65, 0x71,-  0x5f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x2b, 0x20, 0x70, 0x61,-  0x74, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x3b, 0x0a, 0x20,-  0x20, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x26,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e,+  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x63, 0x2c, 0x20, 0x70, 0x29,+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x20, 0x3d, 0x3d,+  0x20, 0x22, 0x5e, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79,+  0x20, 0x2d, 0x20, 0x70, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x20, 0x65, 0x6e,+  0x64, 0x0a, 0x20, 0x20, 0x2a, 0x20, 0x22, 0x5d, 0x22, 0x0a, 0x0a, 0x6c,+  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,+  0x6e, 0x20, 0x61, 0x64, 0x64, 0x64, 0x65, 0x66, 0x20, 0x28, 0x74, 0x2c,+  0x20, 0x6b, 0x2c, 0x20, 0x65, 0x78, 0x70, 0x29, 0x0a, 0x20, 0x20, 0x69,+  0x66, 0x20, 0x74, 0x5b, 0x6b, 0x5d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,+  0x20, 0x20, 0x20, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x27,+  0x22, 0x2e, 0x2e, 0x6b, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x61, 0x6c, 0x72,+  0x65, 0x61, 0x64, 0x79, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64,+  0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x22, 0x29,+  0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x74, 0x5b, 0x6b, 0x5d, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x70, 0x0a, 0x20,+  0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,+  0x6e, 0x20, 0x74, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63,+  0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,+  0x66, 0x69, 0x72, 0x73, 0x74, 0x64, 0x65, 0x66, 0x20, 0x28, 0x6e, 0x2c,+  0x20, 0x72, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61,+  0x64, 0x64, 0x64, 0x65, 0x66, 0x28, 0x7b, 0x6e, 0x7d, 0x2c, 0x20, 0x6e,+  0x2c, 0x20, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x0a, 0x6c,+  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,+  0x6e, 0x20, 0x4e, 0x54, 0x20, 0x28, 0x6e, 0x2c, 0x20, 0x62, 0x29, 0x0a,+  0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x20, 0x74,+  0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x72, 0x72, 0x6f,+  0x72, 0x28, 0x22, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x27, 0x22, 0x2e, 0x2e,+  0x6e, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x6f,+  0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x61,+  0x6d, 0x6d, 0x61, 0x72, 0x22, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73,+  0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d, 0x6d, 0x2e,+  0x56, 0x28, 0x6e, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65,+  0x6e, 0x64, 0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65,+  0x78, 0x70, 0x20, 0x3d, 0x20, 0x6d, 0x2e, 0x50, 0x7b, 0x20, 0x22, 0x45,+  0x78, 0x70, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x45, 0x78, 0x70, 0x20, 0x3d,+  0x20, 0x53, 0x20, 0x2a, 0x20, 0x28, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x47,+  0x72, 0x61, 0x6d, 0x6d, 0x61, 0x72, 0x22, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e,+  0x56, 0x22, 0x53, 0x65, 0x71, 0x22, 0x20, 0x2a, 0x20, 0x28, 0x22, 0x2f,   0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22,+  0x53, 0x65, 0x71, 0x22, 0x20, 0x25, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f,+  0x61, 0x64, 0x64, 0x29, 0x5e, 0x30, 0x20, 0x29, 0x3b, 0x0a, 0x20, 0x20,+  0x53, 0x65, 0x71, 0x20, 0x3d, 0x20, 0x28, 0x6d, 0x2e, 0x43, 0x63, 0x28,+  0x6d, 0x2e, 0x50, 0x22, 0x22, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x2e,+  0x56, 0x22, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x20, 0x25, 0x20,+  0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x6d, 0x75, 0x6c, 0x29, 0x5e, 0x30, 0x29,+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2a, 0x20, 0x28,+  0x23, 0x73, 0x65, 0x71, 0x5f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20,+  0x2b, 0x20, 0x70, 0x61, 0x74, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72,+  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20,+  0x3d, 0x20, 0x22, 0x26, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20,+  0x6d, 0x2e, 0x56, 0x22, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x20,+  0x2f, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x6c, 0x65, 0x6e, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x21,+  0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22,   0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x74,-  0x2e, 0x5f, 0x5f, 0x6c, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x21, 0x22, 0x20, 0x2a, 0x20,-  0x53, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x50, 0x72, 0x65, 0x66,-  0x69, 0x78, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x75,-  0x6e, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x2b, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78,-  0x22, 0x3b, 0x0a, 0x20, 0x20, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x20,-  0x3d, 0x20, 0x6d, 0x2e, 0x43, 0x66, 0x28, 0x6d, 0x2e, 0x56, 0x22, 0x50,-  0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20,-  0x2a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x28, 0x20, 0x28, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x2b, 0x22, 0x20, 0x2a,-  0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x31, 0x2c, 0x20, 0x6d, 0x74, 0x2e,-  0x5f, 0x5f, 0x70, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50,-  0x22, 0x2a, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x30,-  0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x70, 0x6f, 0x77, 0x29, 0x0a,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x3f, 0x22, 0x20, 0x2a, 0x20, 0x6d,-  0x2e, 0x43, 0x63, 0x28, 0x2d, 0x31, 0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f,+  0x2e, 0x5f, 0x5f, 0x75, 0x6e, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x53, 0x75,+  0x66, 0x66, 0x69, 0x78, 0x22, 0x3b, 0x0a, 0x20, 0x20, 0x53, 0x75, 0x66,+  0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x50, 0x72,+  0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a,+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28,+  0x20, 0x28, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x2b, 0x22, 0x20, 0x2a, 0x20,+  0x6d, 0x2e, 0x43, 0x63, 0x28, 0x31, 0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f,   0x5f, 0x70, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x5e, 0x22, 0x20,-  0x2a, 0x20, 0x28, 0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6e, 0x75, 0x6d,-  0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6d, 0x75, 0x6c, 0x74,-  0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b,-  0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6d, 0x2e, 0x43, 0x28, 0x6d, 0x2e,-  0x53, 0x22, 0x2b, 0x2d, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x52, 0x22,-  0x30, 0x39, 0x22, 0x5e, 0x31, 0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43,-  0x63, 0x28, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x70, 0x6f, 0x77, 0x29, 0x29,-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22,+  0x2a, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x30, 0x2c,+  0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x70, 0x6f, 0x77, 0x29, 0x0a, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b,-  0x20, 0x22, 0x2d, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20,-  0x28, 0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x28, 0x53, 0x74, 0x72, 0x69,-  0x6e, 0x67, 0x20, 0x2b, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x2a, 0x20,-  0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x64, 0x69,-  0x76, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x7b,-  0x7d, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6e, 0x69,-  0x6c, 0x2c, 0x20, 0x6d, 0x2e, 0x43, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20,+  0x20, 0x6d, 0x2e, 0x50, 0x22, 0x3f, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e,+  0x43, 0x63, 0x28, 0x2d, 0x31, 0x2c, 0x20, 0x6d, 0x74, 0x2e, 0x5f, 0x5f,+  0x70, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x5e, 0x22, 0x20, 0x2a,+  0x20, 0x28, 0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6e, 0x75, 0x6d, 0x20,+  0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6d, 0x75, 0x6c, 0x74, 0x29,+  0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20,+  0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6d, 0x2e, 0x43, 0x28, 0x6d, 0x2e, 0x53,+  0x22, 0x2b, 0x2d, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x52, 0x22, 0x30,+  0x39, 0x22, 0x5e, 0x31, 0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63,+  0x28, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x70, 0x6f, 0x77, 0x29, 0x29, 0x0a,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x0a, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20,-  0x64, 0x65, 0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63, 0x28,-  0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x64, 0x69, 0x76, 0x29, 0x0a, 0x20, 0x20,+  0x22, 0x2d, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x28,+  0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x28, 0x53, 0x74, 0x72, 0x69, 0x6e,+  0x67, 0x20, 0x2b, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x2a, 0x20, 0x6d,+  0x2e, 0x43, 0x63, 0x28, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x64, 0x69, 0x76,+  0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29,-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x2b, 0x20, 0x22, 0x3d, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20,-  0x2a, 0x20, 0x64, 0x65, 0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e,-  0x63, 0x28, 0x6d, 0x2e, 0x43, 0x6d, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22,-  0x7e, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x64, 0x65,-  0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6d, 0x2e,-  0x43, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x2a, 0x20, 0x53, 0x0a, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x5e, 0x30, 0x2c,-  0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x61,-  0x2c, 0x62, 0x2c, 0x66, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,-  0x20, 0x66, 0x28, 0x61, 0x2c, 0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x20,-  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,-  0x20, 0x3d, 0x20, 0x22, 0x28, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56,-  0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x29, 0x22, 0x0a,+  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x7b, 0x7d,+  0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x6e, 0x69, 0x6c,+  0x2c, 0x20, 0x6d, 0x2e, 0x43, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x2b, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x2f, 0x20, 0x6d,-  0x6d, 0x2e, 0x50, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x0a,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x64,+  0x65, 0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6d,+  0x74, 0x2e, 0x5f, 0x5f, 0x64, 0x69, 0x76, 0x29, 0x0a, 0x20, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x2b, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x0a, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20,-  0x22, 0x7b, 0x3a, 0x22, 0x20, 0x2a, 0x20, 0x28, 0x6e, 0x61, 0x6d, 0x65,-  0x20, 0x2a, 0x20, 0x22, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x43,-  0x63, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e,-  0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x3a, 0x7d,-  0x22, 0x20, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x0a,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6e,-  0x2c, 0x20, 0x70, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,-  0x6d, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x70, 0x2c, 0x20, 0x6e, 0x29, 0x20,-  0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x3d, 0x22, 0x20, 0x2a, 0x20,-  0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2f, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,-  0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6e, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75,-  0x72, 0x6e, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x6d, 0x74, 0x28, 0x6d, 0x6d,-  0x2e, 0x43, 0x62, 0x28, 0x6e, 0x29, 0x2c, 0x20, 0x65, 0x71, 0x75, 0x61,-  0x6c, 0x63, 0x61, 0x70, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20,-  0x6d, 0x2e, 0x50, 0x22, 0x7b, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d,-  0x2e, 0x43, 0x70, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x7b, 0x7e, 0x22, 0x20, 0x2a,-  0x20, 0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20,-  0x22, 0x7e, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x73,-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x2b, 0x20, 0x22, 0x7b, 0x7c, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e,-  0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x7c, 0x7d,-  0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x74, 0x0a, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20,-  0x22, 0x7b, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78,-  0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d,-  0x6d, 0x2e, 0x43, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x2e, 0x22,-  0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x61, 0x6e, 0x79, 0x29,-  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x2b, 0x20, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2a, 0x20, 0x2d,-  0x61, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x2b, 0x20, 0x22, 0x3c, 0x22, 0x20,-  0x2a, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2a, 0x20, 0x22, 0x3e, 0x22,-  0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x62, 0x28, 0x22, 0x47, 0x22,-  0x29, 0x20, 0x2f, 0x20, 0x4e, 0x54, 0x3b, 0x0a, 0x20, 0x20, 0x44, 0x65,-  0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6e,-  0x61, 0x6d, 0x65, 0x20, 0x2a, 0x20, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x20,-  0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x3b, 0x0a,-  0x20, 0x20, 0x47, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x72, 0x20, 0x3d, 0x20,-  0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x74, 0x72,-  0x75, 0x65, 0x29, 0x2c, 0x20, 0x22, 0x47, 0x22, 0x29, 0x20, 0x2a, 0x0a,+  0x2b, 0x20, 0x22, 0x3d, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a,+  0x20, 0x64, 0x65, 0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63,+  0x28, 0x6d, 0x6d, 0x2e, 0x43, 0x6d, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22,+  0x3e, 0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x64, 0x65,+  0x66, 0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6d, 0x74,+  0x2e, 0x5f, 0x5f, 0x6d, 0x6f, 0x64, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x7e,+  0x3e, 0x22, 0x20, 0x2a, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x64, 0x65, 0x66,+  0x77, 0x69, 0x74, 0x68, 0x66, 0x75, 0x6e, 0x63, 0x28, 0x6d, 0x6d, 0x2e,+  0x43, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x25, 0x20, 0x66, 0x75, 0x6e, 0x63,+  0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x61, 0x2c, 0x62, 0x2c, 0x66, 0x29,+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x28, 0x61, 0x2c,+  0x62, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x2a, 0x20, 0x53, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x5e, 0x30,+  0x3b, 0x0a, 0x20, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20,+  0x3d, 0x20, 0x22, 0x28, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22,+  0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x29, 0x22, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b,+  0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x2f, 0x20, 0x6d, 0x6d,+  0x2e, 0x50, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x2b, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b,+  0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22,+  0x7b, 0x3a, 0x22, 0x20, 0x2a, 0x20, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x20,+  0x2a, 0x20, 0x22, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x43, 0x63,+  0x28, 0x6e, 0x69, 0x6c, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56,+  0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x3a, 0x7d, 0x22,+  0x20, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x6d, 0x2e, 0x43, 0x66, 0x28, 0x6d, 0x2e, 0x56, 0x22, 0x44, 0x65, 0x66,-  0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x2f, 0x20, 0x66,-  0x69, 0x72, 0x73, 0x74, 0x64, 0x65, 0x66, 0x20, 0x2a, 0x20, 0x6d, 0x2e,-  0x43, 0x67, 0x28, 0x6d, 0x2e, 0x56, 0x22, 0x44, 0x65, 0x66, 0x69, 0x6e,-  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x29, 0x5e, 0x30, 0x2c, 0x0a, 0x20,+  0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6e, 0x2c,+  0x20, 0x70, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6d,+  0x6d, 0x2e, 0x43, 0x67, 0x28, 0x70, 0x2c, 0x20, 0x6e, 0x29, 0x20, 0x65,+  0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x3d, 0x22, 0x20, 0x2a, 0x20, 0x6e,+  0x61, 0x6d, 0x65, 0x20, 0x2f, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,+  0x6f, 0x6e, 0x20, 0x28, 0x6e, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,+  0x6e, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x6d, 0x74, 0x28, 0x6d, 0x6d, 0x2e,+  0x43, 0x62, 0x28, 0x6e, 0x29, 0x2c, 0x20, 0x65, 0x71, 0x75, 0x61, 0x6c,+  0x63, 0x61, 0x70, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d,+  0x2e, 0x50, 0x22, 0x7b, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e,+  0x43, 0x70, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x2b, 0x20, 0x22, 0x7b, 0x7e, 0x22, 0x20, 0x2a, 0x20,+  0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22,+  0x7e, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x73, 0x0a,   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,-  0x20, 0x61, 0x64, 0x64, 0x64, 0x65, 0x66, 0x29, 0x20, 0x2f, 0x20, 0x6d,-  0x6d, 0x2e, 0x50, 0x0a, 0x7d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,-  0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x3d, 0x20, 0x53,-  0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28, 0x6d, 0x2e, 0x43, 0x63,-  0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x2c, 0x20, 0x22, 0x47, 0x22,-  0x29, 0x20, 0x2a, 0x20, 0x65, 0x78, 0x70, 0x20, 0x2f, 0x20, 0x6d, 0x6d,-  0x2e, 0x50, 0x20, 0x2a, 0x20, 0x28, 0x2d, 0x61, 0x6e, 0x79, 0x20, 0x2b,-  0x20, 0x70, 0x61, 0x74, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29,-  0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e,-  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,-  0x65, 0x20, 0x28, 0x70, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x73, 0x29, 0x0a,-  0x20, 0x20, 0x69, 0x66, 0x20, 0x6d, 0x6d, 0x2e, 0x74, 0x79, 0x70, 0x65,-  0x28, 0x70, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x70, 0x61, 0x74, 0x74,-  0x65, 0x72, 0x6e, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65,-  0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x20,-  0x20, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20,-  0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x6c,-  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x61,-  0x74, 0x74, 0x65, 0x72, 0x6e, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28,-  0x70, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x64, 0x65, 0x66, 0x73, 0x29, 0x0a,-  0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x70, 0x20,-  0x74, 0x68, 0x65, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22,-  0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x70, 0x61,-  0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x2c, 0x20, 0x33, 0x29, 0x20, 0x65,-  0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,-  0x63, 0x70, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61,-  0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d,-  0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x73, 0x2c, 0x20, 0x70, 0x2c, 0x20,-  0x69, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63,-  0x70, 0x20, 0x3d, 0x20, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x0a, 0x20,-  0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x70, 0x20, 0x74,-  0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d,-  0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x70, 0x29, 0x0a,-  0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x3d,-  0x20, 0x63, 0x70, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,-  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x70, 0x3a, 0x6d, 0x61,-  0x74, 0x63, 0x68, 0x28, 0x73, 0x2c, 0x20, 0x69, 0x20, 0x6f, 0x72, 0x20,-  0x31, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61,-  0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,-  0x69, 0x6e, 0x64, 0x20, 0x28, 0x73, 0x2c, 0x20, 0x70, 0x2c, 0x20, 0x69,-  0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x70,-  0x20, 0x3d, 0x20, 0x66, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x0a, 0x20,-  0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x70, 0x20, 0x74,-  0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d,-  0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x70, 0x29, 0x20,-  0x2f, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d,-  0x20, 0x6d, 0x6d, 0x2e, 0x50, 0x7b, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x70,-  0x28, 0x29, 0x20, 0x2a, 0x20, 0x63, 0x70, 0x20, 0x2a, 0x20, 0x6d, 0x6d,-  0x2e, 0x43, 0x70, 0x28, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x20, 0x2a, 0x20,-  0x6d, 0x6d, 0x2e, 0x56, 0x28, 0x31, 0x29, 0x20, 0x7d, 0x0a, 0x20, 0x20,-  0x20, 0x20, 0x66, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x3d, 0x20,-  0x63, 0x70, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c,-  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x2c, 0x20, 0x65, 0x20, 0x3d, 0x20,-  0x63, 0x70, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x73, 0x2c, 0x20,-  0x69, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66,-  0x20, 0x69, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75,-  0x72, 0x6e, 0x20, 0x69, 0x2c, 0x20, 0x65, 0x20, 0x2d, 0x20, 0x31, 0x0a,-  0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,-  0x6e, 0x20, 0x69, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e,-  0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e,-  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x73, 0x75, 0x62, 0x20, 0x28,-  0x73, 0x2c, 0x20, 0x70, 0x2c, 0x20, 0x72, 0x65, 0x70, 0x29, 0x0a, 0x20,-  0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x67,-  0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x6f, 0x72, 0x20, 0x7b, 0x7d,-  0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65,-  0x20, 0x67, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x69, 0x73, 0x20,-  0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65,-  0x64, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x72, 0x65,-  0x0a, 0x20, 0x20, 0x67, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x3d,-  0x20, 0x67, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63,-  0x70, 0x20, 0x3d, 0x20, 0x67, 0x5b, 0x72, 0x65, 0x70, 0x5d, 0x0a, 0x20,-  0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x70, 0x20, 0x74,-  0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d,-  0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x70, 0x29, 0x0a,-  0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x6d, 0x6d, 0x2e,-  0x43, 0x73, 0x28, 0x28, 0x63, 0x70, 0x20, 0x2f, 0x20, 0x72, 0x65, 0x70,-  0x20, 0x2b, 0x20, 0x31, 0x29, 0x5e, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20,-  0x20, 0x67, 0x5b, 0x72, 0x65, 0x70, 0x5d, 0x20, 0x3d, 0x20, 0x63, 0x70,-  0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74,-  0x75, 0x72, 0x6e, 0x20, 0x63, 0x70, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68,-  0x28, 0x73, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x0a, 0x2d, 0x2d,-  0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x61,-  0x6d, 0x65, 0x73, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65,-  0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69,-  0x6c, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,-  0x2c, 0x0a, 0x20, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x3d, 0x20,-  0x6d, 0x61, 0x74, 0x63, 0x68, 0x2c, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x6e,-  0x64, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x2c, 0x0a, 0x20, 0x20,-  0x67, 0x73, 0x75, 0x62, 0x20, 0x3d, 0x20, 0x67, 0x73, 0x75, 0x62, 0x2c,-  0x0a, 0x20, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x6c, 0x6f, 0x63,-  0x61, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,-  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x2c, 0x0a, 0x7d, 0x0a, 0x0a, 0x69,-  0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d,-  0x20, 0x22, 0x4c, 0x75, 0x61, 0x20, 0x35, 0x2e, 0x31, 0x22, 0x20, 0x74,-  0x68, 0x65, 0x6e, 0x20, 0x5f, 0x47, 0x2e, 0x72, 0x65, 0x20, 0x3d, 0x20,-  0x72, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x72, 0x65, 0x74, 0x75,-  0x72, 0x6e, 0x20, 0x72, 0x65, 0x0a+  0x2b, 0x20, 0x22, 0x7b, 0x7c, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56,+  0x22, 0x45, 0x78, 0x70, 0x22, 0x20, 0x2a, 0x20, 0x22, 0x7c, 0x7d, 0x22,+  0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x74, 0x0a, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2b, 0x20, 0x22,+  0x7b, 0x22, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78, 0x70,+  0x22, 0x20, 0x2a, 0x20, 0x22, 0x7d, 0x22, 0x20, 0x2f, 0x20, 0x6d, 0x6d,+  0x2e, 0x43, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x20, 0x20, 0x20, 0x2b, 0x20, 0x6d, 0x2e, 0x50, 0x22, 0x2e, 0x22, 0x20,+  0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x61, 0x6e, 0x79, 0x29, 0x0a,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,+  0x2b, 0x20, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2a, 0x20, 0x2d, 0x61,+  0x72, 0x72, 0x6f, 0x77, 0x20, 0x2b, 0x20, 0x22, 0x3c, 0x22, 0x20, 0x2a,+  0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2a, 0x20, 0x22, 0x3e, 0x22, 0x29,+  0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x62, 0x28, 0x22, 0x47, 0x22, 0x29,+  0x20, 0x2f, 0x20, 0x4e, 0x54, 0x3b, 0x0a, 0x20, 0x20, 0x44, 0x65, 0x66,+  0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6e, 0x61,+  0x6d, 0x65, 0x20, 0x2a, 0x20, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x2a,+  0x20, 0x6d, 0x2e, 0x56, 0x22, 0x45, 0x78, 0x70, 0x22, 0x3b, 0x0a, 0x20,+  0x20, 0x47, 0x72, 0x61, 0x6d, 0x6d, 0x61, 0x72, 0x20, 0x3d, 0x20, 0x6d,+  0x2e, 0x43, 0x67, 0x28, 0x6d, 0x2e, 0x43, 0x63, 0x28, 0x74, 0x72, 0x75,+  0x65, 0x29, 0x2c, 0x20, 0x22, 0x47, 0x22, 0x29, 0x20, 0x2a, 0x0a, 0x20,+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28,+  0x28, 0x6d, 0x2e, 0x56, 0x22, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74,+  0x69, 0x6f, 0x6e, 0x22, 0x20, 0x2f, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,+  0x64, 0x65, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x6d, 0x2e, 0x56, 0x22,+  0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20,+  0x25, 0x20, 0x61, 0x64, 0x64, 0x64, 0x65, 0x66, 0x29, 0x5e, 0x30, 0x29,+  0x20, 0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x50, 0x0a, 0x7d, 0x0a, 0x0a, 0x6c,+  0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e,+  0x20, 0x3d, 0x20, 0x53, 0x20, 0x2a, 0x20, 0x6d, 0x2e, 0x43, 0x67, 0x28,+  0x6d, 0x2e, 0x43, 0x63, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x2c,+  0x20, 0x22, 0x47, 0x22, 0x29, 0x20, 0x2a, 0x20, 0x65, 0x78, 0x70, 0x20,+  0x2f, 0x20, 0x6d, 0x6d, 0x2e, 0x50, 0x20, 0x2a, 0x20, 0x28, 0x2d, 0x61,+  0x6e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x61, 0x74, 0x74, 0x5f, 0x65, 0x72,+  0x72, 0x6f, 0x72, 0x29, 0x0a, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,+  0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f,+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x70, 0x2c, 0x20, 0x64, 0x65,+  0x66, 0x73, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6d, 0x6d, 0x2e,+  0x74, 0x79, 0x70, 0x65, 0x28, 0x70, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x22,+  0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x20, 0x74, 0x68, 0x65,+  0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x70, 0x20, 0x65,+  0x6e, 0x64, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x72, 0x65,+  0x61, 0x64, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64,+  0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x70, 0x20,+  0x3d, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x3a, 0x6d, 0x61,+  0x74, 0x63, 0x68, 0x28, 0x70, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x64, 0x65,+  0x66, 0x73, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74,+  0x20, 0x63, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x65, 0x72, 0x72,+  0x6f, 0x72, 0x28, 0x22, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63,+  0x74, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x2c, 0x20,+  0x33, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74,+  0x75, 0x72, 0x6e, 0x20, 0x63, 0x70, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,+  0x6f, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x73, 0x2c,+  0x20, 0x70, 0x2c, 0x20, 0x69, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63,+  0x61, 0x6c, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x6d, 0x65, 0x6d, 0x5b,+  0x70, 0x5d, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20,+  0x63, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x63, 0x70, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,+  0x28, 0x70, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x6d, 0x5b,+  0x70, 0x5d, 0x20, 0x3d, 0x20, 0x63, 0x70, 0x0a, 0x20, 0x20, 0x65, 0x6e,+  0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63,+  0x70, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x73, 0x2c, 0x20, 0x69,+  0x20, 0x6f, 0x72, 0x20, 0x31, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,+  0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,+  0x6f, 0x6e, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x28, 0x73, 0x2c, 0x20,+  0x70, 0x2c, 0x20, 0x69, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,+  0x6c, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x66, 0x6d, 0x65, 0x6d, 0x5b,+  0x70, 0x5d, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20,+  0x63, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x63, 0x70, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,+  0x28, 0x70, 0x29, 0x20, 0x2f, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x63, 0x70, 0x20, 0x3d, 0x20, 0x6d, 0x6d, 0x2e, 0x50, 0x7b, 0x20, 0x6d,+  0x6d, 0x2e, 0x43, 0x70, 0x28, 0x29, 0x20, 0x2a, 0x20, 0x63, 0x70, 0x20,+  0x2a, 0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x70, 0x28, 0x29, 0x20, 0x2b, 0x20,+  0x31, 0x20, 0x2a, 0x20, 0x6d, 0x6d, 0x2e, 0x56, 0x28, 0x31, 0x29, 0x20,+  0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6d, 0x65, 0x6d, 0x5b, 0x70,+  0x5d, 0x20, 0x3d, 0x20, 0x63, 0x70, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64,+  0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x2c, 0x20,+  0x65, 0x20, 0x3d, 0x20, 0x63, 0x70, 0x3a, 0x6d, 0x61, 0x74, 0x63, 0x68,+  0x28, 0x73, 0x2c, 0x20, 0x69, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x29, 0x0a,+  0x20, 0x20, 0x69, 0x66, 0x20, 0x69, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,+  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x2c, 0x20, 0x65, 0x20,+  0x2d, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x72,+  0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x0a, 0x20, 0x20, 0x65, 0x6e,+  0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,+  0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x73,+  0x75, 0x62, 0x20, 0x28, 0x73, 0x2c, 0x20, 0x70, 0x2c, 0x20, 0x72, 0x65,+  0x70, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x67,+  0x20, 0x3d, 0x20, 0x67, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d, 0x20, 0x6f,+  0x72, 0x20, 0x7b, 0x7d, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x65, 0x6e,+  0x73, 0x75, 0x72, 0x65, 0x20, 0x67, 0x6d, 0x65, 0x6d, 0x5b, 0x70, 0x5d,+  0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6c,+  0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20,+  0x68, 0x65, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x67, 0x6d, 0x65, 0x6d, 0x5b,+  0x70, 0x5d, 0x20, 0x3d, 0x20, 0x67, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63,+  0x61, 0x6c, 0x20, 0x63, 0x70, 0x20, 0x3d, 0x20, 0x67, 0x5b, 0x72, 0x65,+  0x70, 0x5d, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20,+  0x63, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,+  0x63, 0x70, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,+  0x28, 0x70, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x70, 0x20, 0x3d,+  0x20, 0x6d, 0x6d, 0x2e, 0x43, 0x73, 0x28, 0x28, 0x63, 0x70, 0x20, 0x2f,+  0x20, 0x72, 0x65, 0x70, 0x20, 0x2b, 0x20, 0x31, 0x29, 0x5e, 0x30, 0x29,+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x5b, 0x72, 0x65, 0x70, 0x5d, 0x20,+  0x3d, 0x20, 0x63, 0x70, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x70, 0x3a, 0x6d,+  0x61, 0x74, 0x63, 0x68, 0x28, 0x73, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a,+  0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65,+  0x64, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x0a, 0x6c, 0x6f, 0x63, 0x61,+  0x6c, 0x20, 0x72, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x63,+  0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d,+  0x70, 0x69, 0x6c, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x6d, 0x61, 0x74, 0x63,+  0x68, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x2c, 0x0a, 0x20,+  0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6e, 0x64,+  0x2c, 0x0a, 0x20, 0x20, 0x67, 0x73, 0x75, 0x62, 0x20, 0x3d, 0x20, 0x67,+  0x73, 0x75, 0x62, 0x2c, 0x0a, 0x20, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,+  0x65, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x75, 0x70,+  0x64, 0x61, 0x74, 0x65, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x65, 0x2c, 0x0a,+  0x7d, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,+  0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x4c, 0x75, 0x61, 0x20, 0x35, 0x2e,+  0x31, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x5f, 0x47, 0x2e, 0x72,+  0x65, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a,+  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x0a };-unsigned int cbits_lpeg_1_0_2_re_lua_len = 6450;+unsigned int cbits_lpeg_1_1_0_re_lua_len = 6562;
lpeg.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                lpeg-version:             1.0.4+version:             1.1.0 synopsis:            LPeg – Parsing Expression Grammars For Lua description:         This package contains the C sources of LPeg, as well                      as some tiny Haskell helper to load the package.@@ -16,7 +16,7 @@                      © 2021-2023 Albert Krewinkel category:            Foreign build-type:          Simple-extra-source-files:  cbits/lpeg-1.0.2/*.h+extra-source-files:  cbits/lpeg-1.1.0/*.h                    , cbits/re.h                    , README.md                    , CHANGELOG.md@@ -69,13 +69,14 @@     cpp-options:         -DRELY_ON_SYSTEM_INSTALL   else     hs-source-dirs:      src-    include-dirs:        cbits/lpeg-1.0.2+    include-dirs:        cbits/lpeg-1.1.0                        , cbits-    c-sources:           cbits/lpeg-1.0.2/lpvm.c-                       , cbits/lpeg-1.0.2/lptree.c-                       , cbits/lpeg-1.0.2/lpprint.c-                       , cbits/lpeg-1.0.2/lpcode.c-                       , cbits/lpeg-1.0.2/lpcap.c+    c-sources:           cbits/lpeg-1.1.0/lpvm.c+                       , cbits/lpeg-1.1.0/lpcap.c+                       , cbits/lpeg-1.1.0/lptree.c+                       , cbits/lpeg-1.1.0/lpcode.c+                       , cbits/lpeg-1.1.0/lpprint.c+                       , cbits/lpeg-1.1.0/lpcset.c                        , cbits/re.c     cc-options:          -std=c99 -fPIC 
test/test-lpeg.hs view
@@ -54,8 +54,8 @@        _ <- withCString "version" $ lua_pushstring l       _ <- lua_rawget l (-2)-      assertEqual "module should have `version` field of type function"-        LUA_TFUNCTION =<< lua_type l (-1)+      assertEqual "module should have `version` field of type 'string'"+        LUA_TSTRING =<< lua_type l (-1)       lua_close l    , testCase "load libraries manually" $ do@@ -131,7 +131,7 @@ testScript :: String testScript = unlines   [ "local m = require 'lpeg'"-  , "assert(type(m.version()) == 'string')"+  , "assert(type(m.version) == 'string')"   , "assert(m.type(m.P'alo') == 'pattern')"   , "assert(m.match('a' * m.P(true), 'a') == 2)"   ]