diff --git a/3rd/lpeg/lpcap.h b/3rd/lpeg/lpcap.h
index d762fdcf..6133df2a 100644
--- a/3rd/lpeg/lpcap.h
+++ b/3rd/lpeg/lpcap.h
@@ -1,5 +1,5 @@
/*
-** $Id: lpcap.h,v 1.2 2015/02/27 17:13:17 roberto Exp $
+** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $
*/
#if !defined(lpcap_h)
@@ -11,8 +11,21 @@
/* kinds of captures */
typedef enum CapKind {
- Cclose, Cposition, Cconst, Cbackref, Carg, Csimple, Ctable, Cfunction,
- Cquery, Cstring, Cnum, Csubst, Cfold, Cruntime, Cgroup
+ 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;
diff --git a/3rd/lpeg/lpcode.c b/3rd/lpeg/lpcode.c
index fbf44feb..2722d716 100644
--- a/3rd/lpeg/lpcode.c
+++ b/3rd/lpeg/lpcode.c
@@ -1,5 +1,5 @@
/*
-** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $
+** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -125,6 +125,27 @@ int tocharset (TTree *tree, Charset *cs) {
}
+/*
+** 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
*/
@@ -134,14 +155,17 @@ int hascaptures (TTree *tree) {
case TCapture: case TRunTime:
return 1;
case TCall:
- tree = sib2(tree); goto tailcall; /* return hascaptures(sib2(tree)); */
+ 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;
+ if (hascaptures(sib1(tree)))
+ return 1;
/* else return hascaptures(sib2(tree)); */
tree = sib2(tree); goto tailcall;
default: assert(numsiblings[tree->tag] == 0); return 0;
@@ -208,9 +232,9 @@ int checkaux (TTree *tree, int pred) {
/*
** number of characters to match a pattern (or -1 if variable)
-** ('count' avoids infinite loops for grammars)
*/
-int fixedlenx (TTree *tree, int count, int len) {
+int fixedlen (TTree *tree) {
+ int len = 0; /* to accumulate in tail calls */
tailcall:
switch (tree->tag) {
case TChar: case TSet: case TAny:
@@ -220,26 +244,29 @@ int fixedlenx (TTree *tree, int count, int len) {
case TRep: case TRunTime: case TOpenCall:
return -1;
case TCapture: case TRule: case TGrammar:
- /* return fixedlenx(sib1(tree), count); */
+ /* return fixedlen(sib1(tree)); */
tree = sib1(tree); goto tailcall;
- case TCall:
- if (count++ >= MAXRULES)
- return -1; /* may be a loop */
- /* else return fixedlenx(sib2(tree), count); */
- tree = sib2(tree); goto tailcall;
+ case TCall: {
+ int n1 = callrecursive(tree, fixedlen, -1);
+ if (n1 < 0)
+ return -1;
+ else
+ return len + n1;
+ }
case TSeq: {
- len = fixedlenx(sib1(tree), count, len);
- if (len < 0) return -1;
- /* else return fixedlenx(sib2(tree), count, len); */
- tree = sib2(tree); goto tailcall;
+ 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, n2;
- n1 = fixedlenx(sib1(tree), count, len);
- if (n1 < 0) return -1;
- n2 = fixedlenx(sib2(tree), count, len);
- if (n1 == n2) return n1;
- else return -1;
+ 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;
};
@@ -710,9 +737,10 @@ static void codeand (CompileState *compst, TTree *tree, int tt) {
/*
-** Captures: if pattern has fixed (and not too big) length, use
-** a single IFullCapture instruction after the match; otherwise,
-** enclose the pattern with OpenCapture - CloseCapture.
+** 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) {
diff --git a/3rd/lpeg/lpcode.h b/3rd/lpeg/lpcode.h
index 896d3c79..2a5861ef 100644
--- a/3rd/lpeg/lpcode.h
+++ b/3rd/lpeg/lpcode.h
@@ -1,5 +1,5 @@
/*
-** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $
+** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $
*/
#if !defined(lpcode_h)
@@ -13,7 +13,7 @@
int tocharset (TTree *tree, Charset *cs);
int checkaux (TTree *tree, int pred);
-int fixedlenx (TTree *tree, int count, int len);
+int fixedlen (TTree *tree);
int hascaptures (TTree *tree);
int lp_gc (lua_State *L);
Instruction *compile (lua_State *L, Pattern *p);
@@ -35,8 +35,6 @@ int sizei (const Instruction *i);
*/
#define nullable(t) checkaux(t, PEnullable)
-#define fixedlen(t) fixedlenx(t, 0, 0)
-
#endif
diff --git a/3rd/lpeg/lpeg.html b/3rd/lpeg/lpeg.html
index c0a7f090..5c9535f7 100644
--- a/3rd/lpeg/lpeg.html
+++ b/3rd/lpeg/lpeg.html
@@ -10,7 +10,7 @@
-
+
@@ -577,8 +577,9 @@ It is equivalent to the following grammar in standard PEG notation:
-A capture is a pattern that creates values
-(the so called semantic information) when it matches.
+A capture is a pattern that produces values
+(the so called semantic information)
+according to what it matches.
LPeg offers several kinds of captures,
which produces values based on matches and combine these values to
produce new values.
@@ -632,10 +633,7 @@ or no value when number is zero.
-A capture pattern produces its values every time it succeeds.
-For instance,
-a capture inside a loop produces as many values as matched by the loop.
-A capture produces a value only when it succeeds.
+A capture pattern produces its values only when it succeeds.
For instance,
the pattern lpeg.C(lpeg.P"a"^-1)
produces the empty string when there is no "a"
@@ -643,14 +641,20 @@ produces the empty string when there is no "a"
while the pattern lpeg.C("a")^-1
does not produce any value when there is no "a"
(because the pattern "a" fails).
+A pattern inside a loop or inside a recursive structure
+produces values for each match.
Usually,
-LPeg evaluates all captures only after (and if) the entire match succeeds.
-During match time it only gathers enough information
-to produce the capture values later.
-As a particularly important consequence,
+LPeg does not specify when (and if) it evaluates its captures.
+(As an example,
+consider the pattern lpeg.P"a" / func / 0.
+Because the "division" by 0 instructs LPeg to throw away the
+results from the pattern,
+LPeg may or may not call func.)
+Therefore, captures should avoid side effects.
+Moreover,
most captures cannot affect the way a pattern matches a subject.
The only exception to this rule is the
so-called match-time capture.
@@ -700,6 +704,12 @@ An Outermost capture means that the capture is not inside
another complete capture.
+
+In the same way that LPeg does not specify when it evaluates captures,
+it does not specify whether it reuses
+values previously produced by the group
+or re-evaluates them.
+
lpeg.Cc ([value, ...])
@@ -806,7 +816,7 @@ all replacements.
lpeg.Ct (patt)
Creates a table capture.
-This capture creates a table and puts all values from all anonymous captures
+This capture returns a table with all values from all anonymous captures
made by patt inside this table in successive integer keys,
starting at 1.
Moreover,
@@ -872,7 +882,8 @@ there is no captured value.
Creates a match-time capture.
Unlike all other captures,
-this one is evaluated immediately when a match occurs.
+this one is evaluated immediately when a match occurs
+(even if it is part of a larger pattern that fails later).
It forces the immediate evaluation of all its nested captures
and then calls function.
@@ -1380,13 +1391,13 @@ and the new term for each repetition.
Download
LPeg
-source code.
+
source code.
-Copyright © 2007-2015 Lua.org, PUC-Rio.
+Copyright © 2007-2017 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge,
@@ -1424,7 +1435,7 @@ THE SOFTWARE.
-$Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $
+$Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $
diff --git a/3rd/lpeg/lpprint.c b/3rd/lpeg/lpprint.c
index 174d1687..f7be408f 100644
--- a/3rd/lpeg/lpprint.c
+++ b/3rd/lpeg/lpprint.c
@@ -1,5 +1,5 @@
/*
-** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $
+** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -37,13 +37,13 @@ void printcharset (const byte *st) {
}
-static void printcapkind (int kind) {
+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"};
- printf("%s", modes[kind]);
+ return modes[kind];
}
@@ -73,13 +73,12 @@ void printinst (const Instruction *op, const Instruction *p) {
break;
}
case IFullCapture: {
- printcapkind(getkind(p));
- printf(" (size = %d) (idx = %d)", getoff(p), p->i.key);
+ printf("%s (size = %d) (idx = %d)",
+ capkind(getkind(p)), getoff(p), p->i.key);
break;
}
case IOpenCapture: {
- printcapkind(getkind(p));
- printf(" (idx = %d)", p->i.key);
+ printf("%s (idx = %d)", capkind(getkind(p)), p->i.key);
break;
}
case ISet: {
@@ -124,8 +123,8 @@ void printpatt (Instruction *p, int n) {
#if defined(LPEG_DEBUG)
static void printcap (Capture *cap) {
- printcapkind(cap->kind);
- printf(" (idx: %d - size: %d) -> %p\n", cap->idx, cap->siz, cap->s);
+ printf("%s (idx: %d - size: %d) -> %p\n",
+ capkind(cap->kind), cap->idx, cap->siz, cap->s);
}
@@ -177,7 +176,8 @@ void printtree (TTree *tree, int ident) {
break;
}
case TOpenCall: case TCall: {
- printf(" key: %d\n", tree->key);
+ assert(sib2(tree)->tag == TRule);
+ printf(" key: %d (rule: %d)\n", tree->key, sib2(tree)->cap);
break;
}
case TBehind: {
@@ -186,7 +186,7 @@ void printtree (TTree *tree, int ident) {
break;
}
case TCapture: {
- printf(" cap: %d key: %d n: %d\n", tree->cap, tree->key, tree->u.n);
+ printf(" kind: '%s' key: %d\n", capkind(tree->cap), tree->key);
printtree(sib1(tree), ident + 2);
break;
}
diff --git a/3rd/lpeg/lptree.c b/3rd/lpeg/lptree.c
index ac5f5150..bda61b91 100644
--- a/3rd/lpeg/lptree.c
+++ b/3rd/lpeg/lptree.c
@@ -1,5 +1,5 @@
/*
-** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $
+** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -64,7 +64,7 @@ static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {
t->tag = TCall;
t->u.ps = n - (t - g); /* position relative to node */
assert(sib2(t)->tag == TRule);
- sib2(t)->key = t->key;
+ sib2(t)->key = t->key; /* fix rule's key */
}
@@ -935,7 +935,7 @@ static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {
int rulesize;
TTree *rn = gettree(L, ridx, &rulesize);
nd->tag = TRule;
- nd->key = 0;
+ 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 */
@@ -969,6 +969,11 @@ static int checkloops (TTree *tree) {
}
+/*
+** 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 */
@@ -990,6 +995,8 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
** 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,
diff --git a/3rd/lpeg/lptree.h b/3rd/lpeg/lptree.h
index b69528a6..34ee15ca 100644
--- a/3rd/lpeg/lptree.h
+++ b/3rd/lpeg/lptree.h
@@ -1,5 +1,5 @@
/*
-** $Id: lptree.h,v 1.2 2013/03/24 13:51:12 roberto Exp $
+** $Id: lptree.h,v 1.3 2016/09/13 18:07:51 roberto Exp $
*/
#if !defined(lptree_h)
@@ -13,38 +13,43 @@
** types of trees
*/
typedef enum TTag {
- TChar = 0, TSet, TAny, /* standard PEG elements */
- TTrue, TFalse,
- TRep,
- TSeq, TChoice,
- TNot, TAnd,
- TCall,
- TOpenCall,
- TRule, /* sib1 is rule's pattern, sib2 is 'next' rule */
- TGrammar, /* sib1 is initial (and first) rule */
- TBehind, /* match behind */
- TCapture, /* regular capture */
- TRunTime /* run-time capture */
+ 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;
-/* number of siblings for each tree */
-extern const byte numsiblings[];
-
/*
** Tree trees
-** The first sibling of a tree (if there is one) is immediately after
-** the tree. A reference to a second sibling (ps) is its position
-** relative to the position of the tree itself. A key in ktable
-** uses the (unique) address of the original tree that created that
-** entry. NULL means no data.
+** 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 sibling */
+ int ps; /* occasional second child */
int n; /* occasional counter */
} u;
} TTree;
@@ -61,10 +66,10 @@ typedef struct Pattern {
} Pattern;
-/* number of siblings for each tree */
+/* number of children for each tree */
extern const byte numsiblings[];
-/* access to siblings */
+/* access to children */
#define sib1(t) ((t) + 1)
#define sib2(t) ((t) + (t)->u.ps)
diff --git a/3rd/lpeg/lptypes.h b/3rd/lpeg/lptypes.h
index 5eb7987b..8e78bc81 100644
--- a/3rd/lpeg/lptypes.h
+++ b/3rd/lpeg/lptypes.h
@@ -1,7 +1,7 @@
/*
-** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $
+** $Id: lptypes.h,v 1.16 2017/01/13 13:33:17 roberto Exp $
** LPeg - PEG pattern matching for Lua
-** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license)
+** Copyright 2007-2017, Lua.org & PUC-Rio (see 'lpeg.html' for license)
** written by Roberto Ierusalimschy
*/
@@ -19,7 +19,7 @@
#include "lua.h"
-#define VERSION "1.0.0"
+#define VERSION "1.0.1"
#define PATTERN_T "lpeg-pattern"
@@ -55,9 +55,9 @@
#endif
-/* maximum number of rules in a grammar */
+/* maximum number of rules in a grammar (limited by 'unsigned char') */
#if !defined(MAXRULES)
-#define MAXRULES 1000
+#define MAXRULES 250
#endif
diff --git a/3rd/lpeg/lpvm.c b/3rd/lpeg/lpvm.c
index eaf2ebfd..05a5f68c 100644
--- a/3rd/lpeg/lpvm.c
+++ b/3rd/lpeg/lpvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $
+** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
@@ -45,14 +45,16 @@ typedef struct Stack {
/*
-** Double the size of the array of captures
+** Make the size of the array of captures 'cap' twice as large as needed
+** (which is 'captop'). ('n' is the number of new elements.)
*/
-static Capture *doublecap (lua_State *L, Capture *cap, int captop, int ptop) {
+static Capture *doublecap (lua_State *L, Capture *cap, int captop,
+ int n, int ptop) {
Capture *newc;
if (captop >= INT_MAX/((int)sizeof(Capture) * 2))
luaL_error(L, "too many captures");
newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture));
- memcpy(newc, cap, captop * sizeof(Capture));
+ memcpy(newc, cap, (captop - n) * sizeof(Capture));
lua_replace(L, caplistidx(ptop));
return newc;
}
@@ -113,8 +115,8 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
*/
static void adddyncaptures (const char *s, Capture *base, int n, int fd) {
int i;
- /* Cgroup capture is already there */
- assert(base[0].kind == Cgroup && base[0].siz == 0);
+ base[0].kind = Cgroup; /* create group capture */
+ base[0].siz = 0;
base[0].idx = 0; /* make it an anonymous group */
for (i = 1; i <= n; i++) { /* add runtime captures */
base[i].kind = Cruntime;
@@ -157,10 +159,11 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
lua_pushlightuserdata(L, stackbase);
for (;;) {
#if defined(DEBUG)
- printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
- s, stack - getstackbase(L, ptop), ndyncap, captop);
- printinst(op, p);
+ 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) {
@@ -284,6 +287,9 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
captop = stack->caplevel;
p = stack->p;
+#if defined(DEBUG)
+ printf("**FAIL**\n");
+#endif
continue;
}
case ICloseRunTime: {
@@ -293,16 +299,19 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
cs.s = o; cs.L = L; 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 - rem; /* update number of dynamic captures */
+ ndyncap += n; /* update number of dynamic captures */
if (n > 0) { /* any new capture? */
+ if (fr + n >= SHRT_MAX)
+ luaL_error(L, "too many results in match-time capture");
if ((captop += n + 2) >= capsize) {
- capture = doublecap(L, capture, captop, ptop);
+ capture = doublecap(L, capture, captop, n + 2, ptop);
capsize = 2 * captop;
}
/* add new captures to 'capture' list */
@@ -339,7 +348,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
capture[captop].idx = p->i.key;
capture[captop].kind = getkind(p);
if (++captop >= capsize) {
- capture = doublecap(L, capture, captop, ptop);
+ capture = doublecap(L, capture, captop, 0, ptop);
capsize = 2 * captop;
}
p++;
diff --git a/3rd/lpeg/re.html b/3rd/lpeg/re.html
index d0d9744f..32f0a458 100644
--- a/3rd/lpeg/re.html
+++ b/3rd/lpeg/re.html
@@ -10,7 +10,7 @@
-
+
@@ -406,7 +406,7 @@ of patterns accepted by
re.
p = [=[
pattern <- exp !.
-exp <- S (alternative / grammar)
+exp <- S (grammar / alternative)
alternative <- seq ('/' S seq)*
seq <- prefix*
@@ -488,7 +488,7 @@ THE SOFTWARE.
-$Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $
+$Id: re.html,v 1.24 2016/09/20 17:41:27 roberto Exp $
diff --git a/3rd/lpeg/test.lua b/3rd/lpeg/test.lua
index 017a3abf..20ad07f8 100755
--- a/3rd/lpeg/test.lua
+++ b/3rd/lpeg/test.lua
@@ -1,6 +1,6 @@
#!/usr/bin/env lua
--- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $
+-- $Id: test.lua,v 1.112 2017/01/14 18:55:22 roberto Exp $
-- require"strict" -- just to be pedantic
@@ -202,6 +202,14 @@ do
end
+-- bug: loop in 'hascaptures'
+do
+ local p = m.C(-m.P{m.P'x' * m.V(1) + m.P'y'})
+ assert(p:match("xxx") == "")
+end
+
+
+
-- test for small capture boundary
for i = 250,260 do
assert(#m.match(m.C(i), string.rep('a', i)) == i)
@@ -517,6 +525,27 @@ assert(m.match(m.Cs((#((#m.P"a")/"") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
assert(m.match(m.Cs((- -m.P("a") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
assert(m.match(m.Cs((-((-m.P"a")/"") * 1 + m.P(1)/".")^0), "aloal") == "a..a.")
+
+-- fixed length
+do
+ -- 'and' predicate using fixed length
+ local p = m.C(#("a" * (m.P("bd") + "cd")) * 2)
+ assert(p:match("acd") == "ac")
+
+ p = #m.P{ "a" * m.V(2), m.P"b" } * 2
+ assert(p:match("abc") == 3)
+
+ p = #(m.P"abc" * m.B"c")
+ assert(p:match("abc") == 1 and not p:match("ab"))
+
+ p = m.P{ "a" * m.V(2), m.P"b"^1 }
+ checkerr("pattern may not have fixed length", m.B, p)
+
+ p = "abc" * (m.P"b"^1 + m.P"a"^0)
+ checkerr("pattern may not have fixed length", m.B, p)
+end
+
+
p = -m.P'a' * m.Cc(1) + -m.P'b' * m.Cc(2) + -m.P'c' * m.Cc(3)
assert(p:match('a') == 2 and p:match('') == 1 and p:match('b') == 1)
@@ -1098,6 +1127,32 @@ do
assert(c == 11)
end
+
+-- Return a match-time capture that returns 'n' captures
+local function manyCmt (n)
+ return m.Cmt("a", function ()
+ local a = {}; for i = 1, n do a[i] = n - i end
+ return true, unpack(a)
+ end)
+end
+
+-- bug in 1.0: failed match-time that used previous match-time results
+do
+ local x
+ local function aux (...) x = #{...}; return false end
+ local res = {m.match(m.Cmt(manyCmt(20), aux) + manyCmt(10), "a")}
+ assert(#res == 10 and res[1] == 9 and res[10] == 0)
+end
+
+
+-- bug in 1.0: problems with math-times returning too many captures
+do
+ local lim = 2^11 - 10
+ local res = {m.match(manyCmt(lim), "a")}
+ assert(#res == lim and res[1] == lim - 1 and res[lim] == 0)
+ checkerr("too many", m.match, manyCmt(2^15), "a")
+end
+
p = (m.P(function () return true, "a" end) * 'a'
+ m.P(function (s, i) return i, "aa", 20 end) * 'b'
+ m.P(function (s,i) if i <= #s then return i, "aaa" end end) * 1)^0
diff --git a/skynet-src/skynet_module.c b/skynet-src/skynet_module.c
index d586427f..a473e422 100644
--- a/skynet-src/skynet_module.c
+++ b/skynet-src/skynet_module.c
@@ -73,19 +73,28 @@ _query(const char * name) {
return NULL;
}
-static int
-_open_sym(struct skynet_module *mod) {
+static void *
+get_api(struct skynet_module *mod, const char *api_name) {
size_t name_size = strlen(mod->name);
- char tmp[name_size + 9]; // create/init/release/signal , longest name is release (7)
+ size_t api_size = strlen(api_name);
+ char tmp[name_size + api_size + 1];
memcpy(tmp, mod->name, name_size);
- strcpy(tmp+name_size, "_create");
- mod->create = dlsym(mod->module, tmp);
- strcpy(tmp+name_size, "_init");
- mod->init = dlsym(mod->module, tmp);
- strcpy(tmp+name_size, "_release");
- mod->release = dlsym(mod->module, tmp);
- strcpy(tmp+name_size, "_signal");
- mod->signal = dlsym(mod->module, tmp);
+ memcpy(tmp+name_size, api_name, api_size+1);
+ char *ptr = strrchr(tmp, '.');
+ if (ptr == NULL) {
+ ptr = tmp;
+ } else {
+ ptr = ptr + 1;
+ }
+ return dlsym(mod->module, ptr);
+}
+
+static int
+open_sym(struct skynet_module *mod) {
+ mod->create = get_api(mod, "_create");
+ mod->init = get_api(mod, "_init");
+ mod->release = get_api(mod, "_release");
+ mod->signal = get_api(mod, "_signal");
return mod->init == NULL;
}
@@ -107,7 +116,7 @@ skynet_module_query(const char * name) {
M->m[index].name = name;
M->m[index].module = dl;
- if (_open_sym(&M->m[index]) == 0) {
+ if (open_sym(&M->m[index]) == 0) {
M->m[index].name = skynet_strdup(name);
M->count ++;
result = &M->m[index];