From 8e7796a67284bb086c18974cc781bd50bfb1a1f7 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Tue, 11 Apr 2017 13:09:24 +0800 Subject: [PATCH] lpeg 1.0.1 --- 3rd/lpeg/lpcap.h | 19 ++++++++-- 3rd/lpeg/lpcode.c | 76 ++++++++++++++++++++++++++------------ 3rd/lpeg/lpcode.h | 6 +-- 3rd/lpeg/lpeg.html | 43 +++++++++++++-------- 3rd/lpeg/lpprint.c | 22 +++++------ 3rd/lpeg/lptree.c | 13 +++++-- 3rd/lpeg/lptree.h | 53 ++++++++++++++------------ 3rd/lpeg/lptypes.h | 10 ++--- 3rd/lpeg/lpvm.c | 33 +++++++++++------ 3rd/lpeg/re.html | 6 +-- 3rd/lpeg/test.lua | 57 +++++++++++++++++++++++++++- skynet-src/skynet_module.c | 33 +++++++++++------ 12 files changed, 253 insertions(+), 118 deletions(-) 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:

Captures

-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.

License

-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];