mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
Submodule 3rd/jemalloc updated: 3541a904d6...e9192eacf8
@@ -1,4 +1,10 @@
|
||||
HISTORY for LPeg 0.12
|
||||
HISTORY for LPeg 1.0
|
||||
|
||||
* Changes from version 0.12 to 1.0
|
||||
---------------------------------
|
||||
+ group "names" can be any Lua value
|
||||
+ some bugs fixed
|
||||
+ other small improvements
|
||||
|
||||
* Changes from version 0.11 to 0.12
|
||||
---------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcap.c,v 1.5 2014/12/12 16:58:47 roberto Exp $
|
||||
** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -126,7 +126,7 @@ static Capture *findback (CapState *cs, Capture *cap) {
|
||||
continue; /* opening an enclosing capture: skip and get previous */
|
||||
if (captype(cap) == Cgroup) {
|
||||
getfromktable(cs, cap->idx); /* get group name */
|
||||
if (lua_equal(L, -2, -1)) { /* right group? */
|
||||
if (lp_equal(L, -2, -1)) { /* right group? */
|
||||
lua_pop(L, 2); /* remove reference name and group name */
|
||||
return cap;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcap.h,v 1.1 2013/03/21 20:25:12 roberto Exp $
|
||||
** $Id: lpcap.h,v 1.2 2015/02/27 17:13:17 roberto Exp $
|
||||
*/
|
||||
|
||||
#if !defined(lpcap_h)
|
||||
@@ -18,7 +18,7 @@ typedef enum CapKind {
|
||||
|
||||
typedef struct Capture {
|
||||
const char *s; /* subject position */
|
||||
short idx; /* extra info about capture (group name, arg index, etc.) */
|
||||
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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $
|
||||
** $Id: lpcode.c,v 1.23 2015/06/12 18:36:47 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -431,11 +431,11 @@ typedef struct CompileState {
|
||||
|
||||
|
||||
/*
|
||||
** code generation is recursive; 'opt' indicates that the code is
|
||||
** being generated under a 'IChoice' operator jumping to its end
|
||||
** (that is, the match is "optional").
|
||||
** 'tt' points to a previous test protecting this code. 'fl' is
|
||||
** the follow set of the pattern.
|
||||
** 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);
|
||||
@@ -638,13 +638,13 @@ static void codebehind (CompileState *compst, TTree *tree) {
|
||||
|
||||
/*
|
||||
** Choice; optimizations:
|
||||
** - when p1 is headfail
|
||||
** - when first(p1) and first(p2) are disjoint; than
|
||||
** - 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 resuse
|
||||
** - 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,
|
||||
@@ -671,7 +671,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
|
||||
}
|
||||
else {
|
||||
/* <p1 / p2> ==
|
||||
test(fail(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
|
||||
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);
|
||||
@@ -759,7 +759,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt,
|
||||
/* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */
|
||||
int jmp;
|
||||
int test = codetestset(compst, &st, 0);
|
||||
codegen(compst, tree, opt, test, fullset);
|
||||
codegen(compst, tree, 0, test, fullset);
|
||||
jmp = addoffsetinst(compst, IJmp);
|
||||
jumptohere(compst, test);
|
||||
jumptothere(compst, jmp, test);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpcode.h,v 1.6 2013/11/28 14:56:02 roberto Exp $
|
||||
** $Id: lpcode.h,v 1.7 2015/06/12 18:24:45 roberto Exp $
|
||||
*/
|
||||
|
||||
#if !defined(lpcode_h)
|
||||
@@ -24,7 +24,15 @@ 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)
|
||||
|
||||
#define fixedlen(t) fixedlenx(t, 0, 0)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: lpeg.html,v 1.72 2014/12/12 17:11:35 roberto Exp $ -->
|
||||
<!-- $Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
<div id="product_name"><big><strong>LPeg</strong></big></div>
|
||||
<div id="product_description">
|
||||
Parsing Expression Grammars For Lua, version 0.12
|
||||
Parsing Expression Grammars For Lua, version 1.0
|
||||
</div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
@@ -195,13 +195,16 @@ Returns a string with the running version of LPeg.
|
||||
|
||||
<h3><a name="f-setstack"></a><code>lpeg.setmaxstack (max)</code></h3>
|
||||
<p>
|
||||
Sets the maximum size for the backtrack stack used by LPeg to
|
||||
Sets a limit for the size of the backtrack stack used by LPeg to
|
||||
track calls and choices.
|
||||
(The default limit is 400.)
|
||||
Most well-written patterns need little backtrack levels and
|
||||
therefore you seldom need to change this maximum;
|
||||
but a few useful patterns may need more space.
|
||||
Before changing this maximum you should try to rewrite your
|
||||
therefore you seldom need to change this limit;
|
||||
before changing it you should try to rewrite your
|
||||
pattern to avoid the need for extra space.
|
||||
Nevertheless, a few useful patterns may overflow.
|
||||
Also, with recursive grammars,
|
||||
subjects with deep recursion may also need larger limits.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -682,7 +685,8 @@ argument given in the call to <code>lpeg.match</code>.
|
||||
Creates a <em>back capture</em>.
|
||||
This pattern matches the empty string and
|
||||
produces the values produced by the <em>most recent</em>
|
||||
<a href="#cap-g">group capture</a> named <code>name</code>.
|
||||
<a href="#cap-g">group capture</a> named <code>name</code>
|
||||
(where <code>name</code> can be any Lua value).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -762,7 +766,8 @@ Creates a <em>group capture</em>.
|
||||
It groups all values returned by <code>patt</code>
|
||||
into a single capture.
|
||||
The group may be anonymous (if no name is given)
|
||||
or named with the given name.
|
||||
or named with the given name
|
||||
(which can be any non-nil Lua value).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -1375,13 +1380,13 @@ and the new term for each repetition.
|
||||
<h2><a name="download"></a>Download</h2>
|
||||
|
||||
<p>LPeg
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-0.12.1.tar.gz">source code</a>.</p>
|
||||
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.0.tar.gz">source code</a>.</p>
|
||||
|
||||
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
Copyright © 2014 Lua.org, PUC-Rio.
|
||||
Copyright © 2007-2015 Lua.org, PUC-Rio.
|
||||
</p>
|
||||
<p>
|
||||
Permission is hereby granted, free of charge,
|
||||
@@ -1419,7 +1424,7 @@ THE SOFTWARE.
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: lpeg.html,v 1.72 2014/12/12 17:11:35 roberto Exp $
|
||||
$Id: lpeg.html,v 1.75 2015/09/28 17:17:41 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpprint.c,v 1.7 2013/04/12 16:29:49 roberto Exp $
|
||||
** $Id: lpprint.c,v 1.9 2015/06/15 16:09:57 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,7 @@ static void printjmp (const Instruction *op, const Instruction *p) {
|
||||
}
|
||||
|
||||
|
||||
static void printinst (const Instruction *op, const Instruction *p) {
|
||||
void printinst (const Instruction *op, const Instruction *p) {
|
||||
const char *const names[] = {
|
||||
"any", "char", "set",
|
||||
"testany", "testchar", "testset",
|
||||
@@ -221,10 +221,10 @@ void printtree (TTree *tree, int ident) {
|
||||
|
||||
void printktable (lua_State *L, int idx) {
|
||||
int n, i;
|
||||
lua_getfenv(L, idx);
|
||||
lua_getuservalue(L, idx);
|
||||
if (lua_isnil(L, -1)) /* no ktable? */
|
||||
return;
|
||||
n = lua_objlen(L, -1);
|
||||
n = lua_rawlen(L, -1);
|
||||
printf("[");
|
||||
for (i = 1; i <= n; i++) {
|
||||
printf("%d = ", i);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpprint.h,v 1.1 2013/03/21 20:25:12 roberto Exp $
|
||||
** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ 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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lptree.c,v 1.13 2014/12/12 16:59:10 roberto Exp $
|
||||
** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $
|
||||
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -126,6 +126,189 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {===================================================================
|
||||
** 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
|
||||
@@ -155,7 +338,7 @@ static Pattern *getpattern (lua_State *L, int idx) {
|
||||
|
||||
|
||||
static int getsize (lua_State *L, int idx) {
|
||||
return (lua_objlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
|
||||
return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,12 +351,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) {
|
||||
|
||||
|
||||
/*
|
||||
** create a pattern
|
||||
** 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;
|
||||
@@ -206,35 +393,6 @@ static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Add element 'idx' to 'ktable' of pattern at the top of the stack;
|
||||
** create new 'ktable' if necessary. 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 (idx == 0) /* no actual value to insert? */
|
||||
return 0;
|
||||
else {
|
||||
int n;
|
||||
lua_getfenv(L, -1); /* get ktable from pattern */
|
||||
n = lua_objlen(L, -1);
|
||||
if (n == 0) { /* is it empty/non-existent? */
|
||||
lua_pop(L, 1); /* remove it */
|
||||
lua_createtable(L, 1, 0); /* create a fresh table */
|
||||
lua_pushvalue(L, -1); /* make a copy */
|
||||
lua_setfenv(L, -3); /* set it as 'ktable' for pattern */
|
||||
}
|
||||
if (!lua_isnil(L, idx)) { /* non-nil value? */
|
||||
lua_pushvalue(L, idx); /* element to be added */
|
||||
lua_rawseti(L, -2, ++n);
|
||||
}
|
||||
lua_pop(L, 1); /* remove 'ktable' */
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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
|
||||
@@ -310,7 +468,7 @@ static TTree *getpatt (lua_State *L, int idx, int *len) {
|
||||
case LUA_TFUNCTION: {
|
||||
tree = newtree(L, 2);
|
||||
tree->tag = TRunTime;
|
||||
tree->key = addtoktable(L, idx);
|
||||
tree->key = addtonewktable(L, 0, idx);
|
||||
sib1(tree)->tag = TTrue;
|
||||
break;
|
||||
}
|
||||
@@ -325,123 +483,6 @@ static TTree *getpatt (lua_State *L, int idx, int *len) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the number of elements in the ktable of pattern at 'idx'.
|
||||
** In Lua 5.2, 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_objlen(L, idx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Concatentate the contents of table 'idx1' into table 'idx2'.
|
||||
** (Assume that both indices are negative.)
|
||||
** Return the original length of table 'idx2'
|
||||
*/
|
||||
static int concattable (lua_State *L, int idx1, int idx2) {
|
||||
int i;
|
||||
int n1 = ktablelen(L, idx1);
|
||||
int n2 = ktablelen(L, idx2);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Make a merge of ktables from p1 and p2 the ktable for the new
|
||||
** pattern at the top of the stack.
|
||||
*/
|
||||
static int joinktables (lua_State *L, int p1, int p2) {
|
||||
int n1, n2;
|
||||
lua_getfenv(L, p1); /* get ktables */
|
||||
lua_getfenv(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 */
|
||||
return 0; /* nothing to correct */
|
||||
}
|
||||
if (n2 == 0 || lua_equal(L, -2, -1)) { /* second table is empty or equal? */
|
||||
lua_pop(L, 1); /* pop 2nd table */
|
||||
lua_setfenv(L, -2); /* set 1st ktable into new pattern */
|
||||
return 0; /* nothing to correct */
|
||||
}
|
||||
if (n1 == 0) { /* first table is empty? */
|
||||
lua_setfenv(L, -3); /* set 2nd table into new pattern */
|
||||
lua_pop(L, 1); /* pop 1st table */
|
||||
return 0; /* nothing to correct */
|
||||
}
|
||||
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_setfenv(L, -4); /* new ktable becomes p env */
|
||||
lua_pop(L, 2); /* pop other ktables */
|
||||
return n1; /* correction for indices from p2 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** copy 'ktable' of element 'idx' to new tree (on top of stack)
|
||||
*/
|
||||
static void copyktable (lua_State *L, int idx) {
|
||||
lua_getfenv(L, idx);
|
||||
lua_setfenv(L, -2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** merge 'ktable' from rule 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 *rule) {
|
||||
int n;
|
||||
lua_getfenv(L, -1); /* get ktables */
|
||||
lua_getfenv(L, idx);
|
||||
n = concattable(L, -1, -2);
|
||||
lua_pop(L, 2); /* remove both ktables */
|
||||
correctkeys(rule, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** create a new tree, whith a new root and one sibling.
|
||||
** Sibling must be on the Lua stack, at index 1.
|
||||
@@ -470,7 +511,7 @@ static TTree *newroot2sib (lua_State *L, int tag) {
|
||||
tree->u.ps = 1 + s1;
|
||||
memcpy(sib1(tree), tree1, s1 * sizeof(TTree));
|
||||
memcpy(sib2(tree), tree2, s2 * sizeof(TTree));
|
||||
correctkeys(sib2(tree), joinktables(L, 1, 2));
|
||||
joinktables(L, 1, sib2(tree), 2);
|
||||
return tree;
|
||||
}
|
||||
|
||||
@@ -599,7 +640,7 @@ static int lp_sub (lua_State *L) {
|
||||
sib1(tree)->tag = TNot; /* ...not... */
|
||||
memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree)); /* ...t2 */
|
||||
memcpy(sib2(tree), t1, s1 * sizeof(TTree)); /* ... and t1 */
|
||||
correctkeys(sib1(tree), joinktables(L, 1, 2));
|
||||
joinktables(L, 1, sib1(tree), 2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -640,7 +681,7 @@ 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, 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);
|
||||
@@ -655,7 +696,7 @@ static int lp_behind (lua_State *L) {
|
||||
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 = addtoktable(L, 1);
|
||||
tree->key = addtonewktable(L, 0, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -668,7 +709,7 @@ static int lp_V (lua_State *L) {
|
||||
static int capture_aux (lua_State *L, int cap, int labelidx) {
|
||||
TTree *tree = newroot1sib(L, TCapture);
|
||||
tree->cap = cap;
|
||||
tree->key = addtoktable(L, labelidx);
|
||||
tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -676,10 +717,9 @@ static int capture_aux (lua_State *L, int cap, int labelidx) {
|
||||
/*
|
||||
** Fill a tree with an empty capture, using an empty (TTrue) sibling.
|
||||
*/
|
||||
static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) {
|
||||
static TTree *auxemptycap (TTree *tree, int cap) {
|
||||
tree->tag = TCapture;
|
||||
tree->cap = cap;
|
||||
tree->key = addtoktable(L, idx);
|
||||
sib1(tree)->tag = TTrue;
|
||||
return tree;
|
||||
}
|
||||
@@ -688,8 +728,18 @@ static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) {
|
||||
/*
|
||||
** Create a tree for an empty capture
|
||||
*/
|
||||
static TTree *newemptycap (lua_State *L, int cap, int idx) {
|
||||
return auxemptycap(L, newtree(L, 2), cap, idx);
|
||||
static TTree *newemptycap (lua_State *L, int cap) {
|
||||
return auxemptycap(newtree(L, 2), cap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -728,10 +778,8 @@ static int lp_tablecapture (lua_State *L) {
|
||||
static int lp_groupcapture (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 2))
|
||||
return capture_aux(L, Cgroup, 0);
|
||||
else {
|
||||
luaL_checkstring(L, 2);
|
||||
else
|
||||
return capture_aux(L, Cgroup, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -747,14 +795,14 @@ static int lp_simplecapture (lua_State *L) {
|
||||
|
||||
|
||||
static int lp_poscapture (lua_State *L) {
|
||||
newemptycap(L, Cposition, 0);
|
||||
newemptycap(L, Cposition);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int lp_argcapture (lua_State *L) {
|
||||
int n = (int)luaL_checkinteger(L, 1);
|
||||
TTree *tree = newemptycap(L, Carg, 0);
|
||||
TTree *tree = newemptycap(L, Carg);
|
||||
tree->key = n;
|
||||
luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");
|
||||
return 1;
|
||||
@@ -762,8 +810,8 @@ static int lp_argcapture (lua_State *L) {
|
||||
|
||||
|
||||
static int lp_backref (lua_State *L) {
|
||||
luaL_checkstring(L, 1);
|
||||
newemptycap(L, Cbackref, 1);
|
||||
luaL_checkany(L, 1);
|
||||
newemptycapkey(L, Cbackref, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -777,9 +825,10 @@ static int lp_constcapture (lua_State *L) {
|
||||
if (n == 0) /* no values? */
|
||||
newleaf(L, TTrue); /* no capture */
|
||||
else if (n == 1)
|
||||
newemptycap(L, Cconst, 1); /* single constant capture */
|
||||
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;
|
||||
@@ -787,10 +836,12 @@ static int lp_constcapture (lua_State *L) {
|
||||
for (i = 1; i <= n - 1; i++) {
|
||||
tree->tag = TSeq;
|
||||
tree->u.ps = 3; /* skip TCapture and its sibling */
|
||||
auxemptycap(L, sib1(tree), Cconst, i);
|
||||
auxemptycap(sib1(tree), Cconst);
|
||||
sib1(tree)->key = addtoktable(L, i);
|
||||
tree = sib2(tree);
|
||||
}
|
||||
auxemptycap(L, tree, Cconst, i);
|
||||
auxemptycap(tree, Cconst);
|
||||
tree->key = addtoktable(L, i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -800,7 +851,7 @@ static int lp_matchtime (lua_State *L) {
|
||||
TTree *tree;
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
tree = newroot1sib(L, TRunTime);
|
||||
tree->key = addtoktable(L, 2);
|
||||
tree->key = addtonewktable(L, 1, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -857,7 +908,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) {
|
||||
lua_pushnil(L); /* prepare to traverse grammar table */
|
||||
while (lua_next(L, arg) != 0) {
|
||||
if (lua_tonumber(L, -2) == 1 ||
|
||||
lua_equal(L, -2, postab + 1)) { /* initial rule? */
|
||||
lp_equal(L, -2, postab + 1)) { /* initial rule? */
|
||||
lua_pop(L, 1); /* remove value (keep key for lua_next) */
|
||||
continue;
|
||||
}
|
||||
@@ -934,36 +985,40 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
|
||||
|
||||
/*
|
||||
** Check whether a rule can be left recursive; raise an error in that
|
||||
** case; otherwise return 1 iff pattern is nullable. Assume ktable at
|
||||
** the top of the stack.
|
||||
** 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.)
|
||||
** Assume ktable at the top of the stack.
|
||||
*/
|
||||
static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
|
||||
int nullable) {
|
||||
int nb) {
|
||||
tailcall:
|
||||
switch (tree->tag) {
|
||||
case TChar: case TSet: case TAny:
|
||||
case TFalse:
|
||||
return nullable; /* cannot pass from here */
|
||||
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); nullable = 1; goto tailcall;
|
||||
tree = sib1(tree); nb = 1; goto tailcall;
|
||||
case TCapture: case TRunTime:
|
||||
/* return verifyrule(L, sib1(tree), passed, npassed); */
|
||||
/* return verifyrule(L, sib1(tree), passed, npassed, nb); */
|
||||
tree = sib1(tree); goto tailcall;
|
||||
case TCall:
|
||||
/* return verifyrule(L, sib2(tree), passed, npassed); */
|
||||
/* return verifyrule(L, sib2(tree), passed, npassed, nb); */
|
||||
tree = sib2(tree); goto tailcall;
|
||||
case TSeq: /* only check 2nd child if first is nullable */
|
||||
case TSeq: /* only check 2nd child if first is nb */
|
||||
if (!verifyrule(L, sib1(tree), passed, npassed, 0))
|
||||
return nullable;
|
||||
/* else return verifyrule(L, sib2(tree), passed, npassed); */
|
||||
return nb;
|
||||
/* else return verifyrule(L, sib2(tree), passed, npassed, nb); */
|
||||
tree = sib2(tree); goto tailcall;
|
||||
case TChoice: /* must check both children */
|
||||
nullable = verifyrule(L, sib1(tree), passed, npassed, nullable);
|
||||
/* return verifyrule(L, sib2(tree), passed, npassed, nullable); */
|
||||
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)
|
||||
@@ -1006,7 +1061,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) {
|
||||
*/
|
||||
static void initialrulename (lua_State *L, TTree *grammar, int frule) {
|
||||
if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */
|
||||
int n = lua_objlen(L, -1) + 1; /* index for name */
|
||||
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;
|
||||
@@ -1022,9 +1077,9 @@ static TTree *newgrammar (lua_State *L, int arg) {
|
||||
luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");
|
||||
g->tag = TGrammar; g->u.n = n;
|
||||
lua_newtable(L); /* create 'ktable' */
|
||||
lua_setfenv(L, -2);
|
||||
lua_setuservalue(L, -2);
|
||||
buildgrammar(L, g, frule, n);
|
||||
lua_getfenv(L, -1); /* get 'ktable' for new tree */
|
||||
lua_getuservalue(L, -1); /* get 'ktable' for new tree */
|
||||
finalfix(L, frule - 1, g, sib1(g));
|
||||
initialrulename(L, g, frule);
|
||||
verifygrammar(L, g);
|
||||
@@ -1038,7 +1093,7 @@ static TTree *newgrammar (lua_State *L, int arg) {
|
||||
|
||||
|
||||
static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {
|
||||
lua_getfenv(L, idx); /* push 'ktable' (may be used by 'finalfix') */
|
||||
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);
|
||||
@@ -1049,7 +1104,7 @@ static int lp_printtree (lua_State *L) {
|
||||
TTree *tree = getpatt(L, 1, NULL);
|
||||
int c = lua_toboolean(L, 2);
|
||||
if (c) {
|
||||
lua_getfenv(L, 1); /* push 'ktable' (may be used by 'finalfix') */
|
||||
lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */
|
||||
finalfix(L, 0, NULL, tree);
|
||||
lua_pop(L, 1); /* remove 'ktable' */
|
||||
}
|
||||
@@ -1102,7 +1157,7 @@ static int lp_match (lua_State *L) {
|
||||
int ptop = lua_gettop(L);
|
||||
lua_pushnil(L); /* initialize subscache */
|
||||
lua_pushlightuserdata(L, capture); /* initialize caplistidx */
|
||||
lua_getfenv(L, 1); /* initialize penvidx */
|
||||
lua_getuservalue(L, 1); /* initialize penvidx */
|
||||
r = match(L, s, s + i, s + l, code, capture, ptop);
|
||||
if (r == NULL) {
|
||||
lua_pushnil(L);
|
||||
@@ -1119,8 +1174,12 @@ static int lp_match (lua_State *L) {
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
/* maximum limit for stack size */
|
||||
#define MAXLIM (INT_MAX / 100)
|
||||
|
||||
static int lp_setmax (lua_State *L) {
|
||||
luaL_optinteger(L, 1, -1);
|
||||
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;
|
||||
@@ -1144,8 +1203,7 @@ static int lp_type (lua_State *L) {
|
||||
|
||||
int lp_gc (lua_State *L) {
|
||||
Pattern *p = getpattern(L, 1);
|
||||
if (p->codesize > 0)
|
||||
realloccode(L, p, 0);
|
||||
realloccode(L, p, 0); /* delete code block */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1228,8 +1286,8 @@ 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_register(L, NULL, metareg);
|
||||
luaL_register(L, "lpeg", pattreg);
|
||||
luaL_setfuncs(L, metareg, 0);
|
||||
luaL_newlib(L, pattreg);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, "__index");
|
||||
return 1;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** $Id: lptypes.h,v 1.10 2014/12/12 17:11:35 roberto Exp $
|
||||
** $Id: lptypes.h,v 1.14 2015/09/28 17:17:41 roberto Exp $
|
||||
** LPeg - PEG pattern matching for Lua
|
||||
** Copyright 2007-2014, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** Copyright 2007-2015, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** written by Roberto Ierusalimschy
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define VERSION "0.12.1"
|
||||
#define VERSION "1.0.0"
|
||||
|
||||
|
||||
#define PATTERN_T "lpeg-pattern"
|
||||
@@ -27,31 +27,31 @@
|
||||
|
||||
|
||||
/*
|
||||
** compatibility with Lua 5.2
|
||||
** compatibility with Lua 5.1
|
||||
*/
|
||||
#if (LUA_VERSION_NUM >= 502)
|
||||
#if (LUA_VERSION_NUM == 501)
|
||||
|
||||
#undef lua_equal
|
||||
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
|
||||
#define lp_equal lua_equal
|
||||
|
||||
#undef lua_getfenv
|
||||
#define lua_getfenv lua_getuservalue
|
||||
#undef lua_setfenv
|
||||
#define lua_setfenv lua_setuservalue
|
||||
#define lua_getuservalue lua_getfenv
|
||||
#define lua_setuservalue lua_setfenv
|
||||
|
||||
#undef lua_objlen
|
||||
#define lua_objlen lua_rawlen
|
||||
#define lua_rawlen lua_objlen
|
||||
|
||||
#undef luaL_register
|
||||
#define luaL_register(L,n,f) \
|
||||
{ if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
|
||||
#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 100
|
||||
#define MAXBACK 400
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lpvm.c,v 1.5 2013/04/12 16:29:49 roberto Exp $
|
||||
** $Id: lpvm.c,v 1.6 2015/09/28 17:01:25 roberto Exp $
|
||||
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/* initial size for call/backtrack stack */
|
||||
#if !defined(INITBACK)
|
||||
#define INITBACK 100
|
||||
#define INITBACK MAXBACK
|
||||
#endif
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {
|
||||
max = lua_tointeger(L, -1); /* maximum allowed size */
|
||||
lua_pop(L, 1);
|
||||
if (n >= max) /* already at maximum size? */
|
||||
luaL_error(L, "too many pending calls/choices");
|
||||
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));
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- $Id: re.html,v 1.21 2013/03/28 20:43:30 roberto Exp $ -->
|
||||
<!-- $Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $ -->
|
||||
|
||||
<div id="container">
|
||||
|
||||
@@ -296,7 +296,7 @@ it would be useful if each table had
|
||||
a <code>tag</code> field telling what non terminal
|
||||
that table represents.
|
||||
We can add such a tag using
|
||||
<a href="lpeg.html/#cap-g">named group captures</a>:
|
||||
<a href="lpeg.html#cap-g">named group captures</a>:
|
||||
</p>
|
||||
<pre class="example">
|
||||
x = re.compile[[
|
||||
@@ -450,7 +450,7 @@ print(re.match(p, p)) -- a self description must match itself
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
Copyright © 2008-2010 Lua.org, PUC-Rio.
|
||||
Copyright © 2008-2015 Lua.org, PUC-Rio.
|
||||
</p>
|
||||
<p>
|
||||
Permission is hereby granted, free of charge,
|
||||
@@ -488,7 +488,7 @@ THE SOFTWARE.
|
||||
|
||||
<div id="about">
|
||||
<p><small>
|
||||
$Id: re.html,v 1.21 2013/03/28 20:43:30 roberto Exp $
|
||||
$Id: re.html,v 1.23 2015/09/28 17:17:41 roberto Exp $
|
||||
</small></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env lua5.1
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- $Id: test.lua,v 1.105 2014/12/12 17:00:39 roberto Exp $
|
||||
-- $Id: test.lua,v 1.109 2015/09/28 17:01:25 roberto Exp $
|
||||
|
||||
-- require"strict" -- just to be pedantic
|
||||
|
||||
@@ -16,9 +16,6 @@ local unpack = rawget(table, "unpack") or unpack
|
||||
local loadstring = rawget(_G, "loadstring") or load
|
||||
|
||||
|
||||
-- most tests here do not need much stack space
|
||||
m.setmaxstack(5)
|
||||
|
||||
local any = m.P(1)
|
||||
local space = m.S" \t\n"^0
|
||||
|
||||
@@ -291,6 +288,13 @@ assert(m.match(m.P"ab"^-1 - "c", "abcd") == 3)
|
||||
|
||||
p = ('Aa' * ('Bb' * ('Cc' * m.P'Dd'^0)^0)^0)^-1
|
||||
assert(p:match("AaBbCcDdBbCcDdDdDdBb") == 21)
|
||||
|
||||
|
||||
-- bug in 0.12.2
|
||||
-- p = { ('ab' ('c' 'ef'?)*)? }
|
||||
p = m.C(('ab' * ('c' * m.P'ef'^-1)^0)^-1)
|
||||
s = "abcefccefc"
|
||||
assert(s == p:match(s))
|
||||
|
||||
|
||||
pi = "3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510"
|
||||
@@ -352,6 +356,11 @@ checkeq(t, {hi = 10, ho = 20})
|
||||
t = p:match'abc'
|
||||
checkeq(t, {hi = 10, ho = 20, 'a', 'b', 'c'})
|
||||
|
||||
-- non-string group names
|
||||
p = m.Ct(m.Cg(1, print) * m.Cg(1, 23.5) * m.Cg(1, io))
|
||||
t = p:match('abcdefghij')
|
||||
assert(t[print] == 'a' and t[23.5] == 'b' and t[io] == 'c')
|
||||
|
||||
|
||||
-- test for error messages
|
||||
local function checkerr (msg, f, ...)
|
||||
@@ -388,6 +397,25 @@ p = m.P { (m.P {m.P'abc'} + 'ayz') * m.V'y'; y = m.P'x' }
|
||||
assert(p:match('abcx') == 5 and p:match('ayzx') == 5 and not p:match'abc')
|
||||
|
||||
|
||||
do
|
||||
-- large dynamic Cc
|
||||
local lim = 2^16 - 1
|
||||
local c = 0
|
||||
local function seq (n)
|
||||
if n == 1 then c = c + 1; return m.Cc(c)
|
||||
else
|
||||
local m = math.floor(n / 2)
|
||||
return seq(m) * seq(n - m)
|
||||
end
|
||||
end
|
||||
p = m.Ct(seq(lim))
|
||||
t = p:match('')
|
||||
assert(t[lim] == lim)
|
||||
checkerr("too many", function () p = p / print end)
|
||||
checkerr("too many", seq, lim + 1)
|
||||
end
|
||||
|
||||
|
||||
-- tests for non-pattern as arguments to pattern functions
|
||||
|
||||
p = { ('a' * m.V(1))^-1 } * m.P'b' * { 'a' * m.V(2); m.V(1)^-1 }
|
||||
@@ -575,9 +603,9 @@ assert(not p:match(string.rep("011", 10001)))
|
||||
-- this grammar does need backtracking info.
|
||||
local lim = 10000
|
||||
p = m.P{ '0' * m.V(1) + '0' }
|
||||
checkerr("too many pending", m.match, p, string.rep("0", lim))
|
||||
checkerr("stack overflow", m.match, p, string.rep("0", lim))
|
||||
m.setmaxstack(2*lim)
|
||||
checkerr("too many pending", m.match, p, string.rep("0", lim))
|
||||
checkerr("stack overflow", m.match, p, string.rep("0", lim))
|
||||
m.setmaxstack(2*lim + 4)
|
||||
assert(m.match(p, string.rep("0", lim)) == lim + 1)
|
||||
|
||||
@@ -586,7 +614,7 @@ p = m.P{ ('a' * m.V(1))^0 * 'b' + 'c' }
|
||||
m.setmaxstack(200)
|
||||
assert(p:match(string.rep('a', 180) .. 'c' .. string.rep('b', 180)) == 362)
|
||||
|
||||
m.setmaxstack(5) -- restore original limit
|
||||
m.setmaxstack(100) -- restore low limit
|
||||
|
||||
-- tests for optional start position
|
||||
assert(m.match("a", "abc", 1))
|
||||
@@ -718,6 +746,10 @@ t = {m.match(m.Cc(nil,nil,4) * m.Cc(nil,3) * m.Cc(nil, nil) / g / g, "")}
|
||||
t1 = {1,1,nil,nil,4,nil,3,nil,nil}
|
||||
for i=1,10 do assert(t[i] == t1[i]) end
|
||||
|
||||
-- bug in 0.12.2: ktable with only nil could be eliminated when joining
|
||||
-- with a pattern without ktable
|
||||
assert((m.P"aaa" * m.Cc(nil)):match"aaa" == nil)
|
||||
|
||||
t = {m.match((m.C(1) / function (x) return x, x.."x" end)^0, "abc")}
|
||||
checkeq(t, {"a", "ax", "b", "bx", "c", "cx"})
|
||||
|
||||
@@ -925,6 +957,13 @@ p = m.Cg(m.C(1) * m.C(1), "k") * m.Ct(m.Cb("k"))
|
||||
t = p:match("ab")
|
||||
checkeq(t, {"a", "b"})
|
||||
|
||||
p = m.P(true)
|
||||
for i = 1, 10 do p = p * m.Cg(1, i) end
|
||||
for i = 1, 10 do
|
||||
local p = p * m.Cb(i)
|
||||
assert(p:match('abcdefghij') == string.sub('abcdefghij', i, i))
|
||||
end
|
||||
|
||||
|
||||
t = {}
|
||||
function foo (p) t[#t + 1] = p; return p .. "x" end
|
||||
|
||||
@@ -972,29 +972,28 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
|
||||
|
||||
// use clonefunction
|
||||
|
||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
||||
#include "spinlock.h"
|
||||
|
||||
struct codecache {
|
||||
int lock;
|
||||
struct spinlock lock;
|
||||
lua_State *L;
|
||||
};
|
||||
|
||||
static struct codecache CC = { 0 , NULL };
|
||||
static struct codecache CC;
|
||||
|
||||
static void
|
||||
clearcache() {
|
||||
if (CC.L == NULL)
|
||||
return;
|
||||
LOCK(&CC)
|
||||
SPIN_LOCK(&CC)
|
||||
lua_close(CC.L);
|
||||
CC.L = luaL_newstate();
|
||||
UNLOCK(&CC)
|
||||
SPIN_UNLOCK(&CC)
|
||||
}
|
||||
|
||||
static void
|
||||
init() {
|
||||
CC.lock = 0;
|
||||
SPIN_INIT(&CC);
|
||||
CC.L = luaL_newstate();
|
||||
}
|
||||
|
||||
@@ -1002,13 +1001,13 @@ static const void *
|
||||
load(const char *key) {
|
||||
if (CC.L == NULL)
|
||||
return NULL;
|
||||
LOCK(&CC)
|
||||
SPIN_LOCK(&CC)
|
||||
lua_State *L = CC.L;
|
||||
lua_pushstring(L, key);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
const void * result = lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
UNLOCK(&CC)
|
||||
SPIN_UNLOCK(&CC)
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1018,7 +1017,7 @@ save(const char *key, const void * proto) {
|
||||
lua_State *L;
|
||||
const void * result = NULL;
|
||||
|
||||
LOCK(&CC)
|
||||
SPIN_LOCK(&CC)
|
||||
if (CC.L == NULL) {
|
||||
init();
|
||||
L = CC.L;
|
||||
@@ -1036,17 +1035,66 @@ save(const char *key, const void * proto) {
|
||||
lua_pop(L,2);
|
||||
}
|
||||
}
|
||||
UNLOCK(&CC)
|
||||
SPIN_UNLOCK(&CC)
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CACHE_OFF 0
|
||||
#define CACHE_EXIST 1
|
||||
#define CACHE_ON 2
|
||||
|
||||
static int cache_key = 0;
|
||||
|
||||
static int cache_level(lua_State *L) {
|
||||
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
int r = lua_tointeger(L, -1);
|
||||
lua_pop(L,1);
|
||||
if (t == LUA_TNUMBER) {
|
||||
return r;
|
||||
}
|
||||
return CACHE_ON;
|
||||
}
|
||||
|
||||
static int cache_mode(lua_State *L) {
|
||||
static const char * lst[] = {
|
||||
"OFF",
|
||||
"EXIST",
|
||||
"ON",
|
||||
NULL,
|
||||
};
|
||||
if (lua_isnoneornil(L,1)) {
|
||||
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
int r = lua_tointeger(L, -1);
|
||||
if (t == LUA_TNUMBER) {
|
||||
if (r < 0 || r >= CACHE_ON) {
|
||||
r = CACHE_ON;
|
||||
}
|
||||
} else {
|
||||
r = CACHE_ON;
|
||||
}
|
||||
lua_pushstring(L, lst[r]);
|
||||
return 1;
|
||||
}
|
||||
int t = luaL_checkoption(L, 1, "OFF" , lst);
|
||||
lua_pushinteger(L, t);
|
||||
lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
|
||||
const char *mode) {
|
||||
int level = cache_level(L);
|
||||
if (level == CACHE_OFF) {
|
||||
return luaL_loadfilex_(L, filename, mode);
|
||||
}
|
||||
const void * proto = load(filename);
|
||||
if (proto) {
|
||||
lua_clonefunction(L, proto);
|
||||
return LUA_OK;
|
||||
}
|
||||
if (level == CACHE_EXIST) {
|
||||
return luaL_loadfilex_(L, filename, mode);
|
||||
}
|
||||
lua_State * eL = luaL_newstate();
|
||||
if (eL == NULL) {
|
||||
lua_pushliteral(L, "New state failed");
|
||||
@@ -1083,6 +1131,7 @@ cache_clear(lua_State *L) {
|
||||
LUAMOD_API int luaopen_cache(lua_State *L) {
|
||||
luaL_Reg l[] = {
|
||||
{ "clear", cache_clear },
|
||||
{ "mode", cache_mode },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
luaL_newlib(L,l);
|
||||
|
||||
5
Makefile
5
Makefile
@@ -24,7 +24,7 @@ JEMALLOC_INC := 3rd/jemalloc/include/jemalloc
|
||||
|
||||
all : jemalloc
|
||||
|
||||
.PHONY : jemalloc
|
||||
.PHONY : jemalloc update3rd
|
||||
|
||||
MALLOC_STATICLIB := $(JEMALLOC_STATICLIB)
|
||||
|
||||
@@ -39,6 +39,9 @@ $(JEMALLOC_STATICLIB) : 3rd/jemalloc/Makefile
|
||||
|
||||
jemalloc : $(MALLOC_STATICLIB)
|
||||
|
||||
update3rd :
|
||||
rm -rf 3rd/jemalloc && git submodule update --init
|
||||
|
||||
# skynet
|
||||
|
||||
CSERVICE = snlua logger gate harbor
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#define DEFAULT_CAP 64
|
||||
#define MAX_NUMBER 1024
|
||||
// avoid circular reference while encodeing
|
||||
#define MAX_DEPTH 128
|
||||
|
||||
#define BSON_REAL 1
|
||||
#define BSON_STRING 2
|
||||
@@ -236,7 +238,7 @@ write_double(struct bson *b, lua_Number d) {
|
||||
}
|
||||
}
|
||||
|
||||
static void pack_dict(lua_State *L, struct bson *b, bool array);
|
||||
static void pack_dict(lua_State *L, struct bson *b, bool array, int depth);
|
||||
|
||||
static inline void
|
||||
append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
||||
@@ -268,7 +270,7 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
}
|
||||
|
||||
static void
|
||||
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
||||
size_t len = lua_rawlen(L, -1);
|
||||
bool isarray = false;
|
||||
if (len > 0) {
|
||||
@@ -284,7 +286,7 @@ append_table(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
} else {
|
||||
append_key(bs, BSON_DOCUMENT, key, sz);
|
||||
}
|
||||
pack_dict(L, bs, isarray);
|
||||
pack_dict(L, bs, isarray, depth);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -297,7 +299,7 @@ write_binary(struct bson *b, const void * buffer, size_t sz) {
|
||||
}
|
||||
|
||||
static void
|
||||
append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
append_one(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
||||
int vt = lua_type(L,-1);
|
||||
switch(vt) {
|
||||
case LUA_TNUMBER:
|
||||
@@ -385,7 +387,7 @@ append_one(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
||||
break;
|
||||
}
|
||||
case LUA_TTABLE:
|
||||
append_table(bs, L, key, sz);
|
||||
append_table(bs, L, key, sz, depth+1);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
append_key(bs, BSON_BOOLEAN, key, sz);
|
||||
@@ -407,7 +409,11 @@ bson_numstr( char *str, unsigned int i ) {
|
||||
}
|
||||
|
||||
static void
|
||||
pack_dict(lua_State *L, struct bson *b, bool isarray) {
|
||||
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
||||
if (depth > MAX_DEPTH) {
|
||||
luaL_error(L, "Too depth while encoding bson");
|
||||
}
|
||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
||||
int length = reserve_length(b);
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L,-2) != 0) {
|
||||
@@ -423,7 +429,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
|
||||
sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1);
|
||||
key = numberkey;
|
||||
|
||||
append_one(b, L, key, sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
} else {
|
||||
switch(kt) {
|
||||
@@ -432,12 +438,12 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
|
||||
lua_pushvalue(L,-2);
|
||||
lua_insert(L,-2);
|
||||
key = lua_tolstring(L,-2,&sz);
|
||||
append_one(b, L, key, sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,2);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
key = lua_tolstring(L,-2,&sz);
|
||||
append_one(b, L, key, sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
break;
|
||||
default:
|
||||
@@ -451,7 +457,7 @@ pack_dict(lua_State *L, struct bson *b, bool isarray) {
|
||||
}
|
||||
|
||||
static void
|
||||
pack_ordered_dict(lua_State *L, struct bson *b, int n) {
|
||||
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
|
||||
int length = reserve_length(b);
|
||||
int i;
|
||||
for (i=0;i<n;i+=2) {
|
||||
@@ -461,7 +467,7 @@ pack_ordered_dict(lua_State *L, struct bson *b, int n) {
|
||||
luaL_error(L, "Argument %d need a string", i+1);
|
||||
}
|
||||
lua_pushvalue(L, i+2);
|
||||
append_one(b, L, key, sz);
|
||||
append_one(b, L, key, sz, depth);
|
||||
lua_pop(L,1);
|
||||
}
|
||||
write_byte(b,0);
|
||||
@@ -495,6 +501,7 @@ make_object(lua_State *L, int type, const void * ptr, size_t len) {
|
||||
|
||||
static void
|
||||
unpack_dict(lua_State *L, struct bson_reader *br, bool array) {
|
||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to unpack table
|
||||
int sz = read_int32(L, br);
|
||||
const void * bytes = read_bytes(L, br, sz-5);
|
||||
struct bson_reader t = { bytes, sz-5 };
|
||||
@@ -846,7 +853,7 @@ lencode(lua_State *L) {
|
||||
bson_create(&b);
|
||||
lua_settop(L,1);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
pack_dict(L, &b, false);
|
||||
pack_dict(L, &b, false, 0);
|
||||
void * ud = lua_newuserdata(L, b.size);
|
||||
memcpy(ud, b.ptr, b.size);
|
||||
bson_destroy(&b);
|
||||
@@ -862,7 +869,7 @@ lencode_order(lua_State *L) {
|
||||
if (n%2 != 0) {
|
||||
return luaL_error(L, "Invalid ordered dict");
|
||||
}
|
||||
pack_ordered_dict(L, &b, n);
|
||||
pack_ordered_dict(L, &b, n, 0);
|
||||
lua_settop(L,1);
|
||||
void * ud = lua_newuserdata(L, b.size);
|
||||
memcpy(ud, b.ptr, b.size);
|
||||
|
||||
@@ -677,6 +677,7 @@ encode_object(sproto_callback cb, struct sproto_arg *args, uint8_t *data, int si
|
||||
args->value = data+SIZEOF_LENGTH;
|
||||
args->length = size-SIZEOF_LENGTH;
|
||||
sz = cb(args);
|
||||
assert(sz <= size-SIZEOF_LENGTH); // verify buffer overflow
|
||||
if (sz <= 0)
|
||||
return sz;
|
||||
if (args->type == SPROTO_TSTRING) {
|
||||
|
||||
@@ -265,7 +265,7 @@ local function suspend(tid, name, qtype)
|
||||
co = coroutine.running(),
|
||||
}
|
||||
request_pool[tid] = req
|
||||
skynet.wait()
|
||||
skynet.wait(req.co)
|
||||
local answers = request_pool[tid].answers
|
||||
request_pool[tid] = nil
|
||||
assert(answers, "no ip")
|
||||
|
||||
@@ -275,10 +275,10 @@ function skynet.yield()
|
||||
return skynet.sleep(0)
|
||||
end
|
||||
|
||||
function skynet.wait()
|
||||
function skynet.wait(co)
|
||||
local session = c.genid()
|
||||
local ret, msg = coroutine_yield("SLEEP", session)
|
||||
local co = coroutine.running()
|
||||
co = co or coroutine.running()
|
||||
sleep_session[co] = nil
|
||||
session_id_coroutine[session] = nil
|
||||
end
|
||||
|
||||
@@ -49,7 +49,6 @@ end
|
||||
|
||||
local function launch_slave(auth_handler)
|
||||
local function auth(fd, addr)
|
||||
fd = assert(tonumber(fd))
|
||||
skynet.error(string.format("connect from %s (fd = %d)", addr, fd))
|
||||
socket.start(fd)
|
||||
|
||||
@@ -84,11 +83,11 @@ local function launch_slave(auth_handler)
|
||||
|
||||
local ok, server, uid = pcall(auth_handler,token)
|
||||
|
||||
socket.abandon(fd)
|
||||
return ok, server, uid, secret
|
||||
end
|
||||
|
||||
local function ret_pack(ok, err, ...)
|
||||
local function ret_pack(fd, ok, err, ...)
|
||||
socket.abandon(fd)
|
||||
if ok then
|
||||
skynet.ret(skynet.pack(err, ...))
|
||||
else
|
||||
@@ -100,8 +99,12 @@ local function launch_slave(auth_handler)
|
||||
end
|
||||
end
|
||||
|
||||
skynet.dispatch("lua", function(_,_,...)
|
||||
ret_pack(pcall(auth, ...))
|
||||
skynet.dispatch("lua", function(_,_,fd,...)
|
||||
if type(fd) ~= "number" then
|
||||
skynet.ret(skynet.pack(false, "invalid fd type"))
|
||||
else
|
||||
ret_pack(fd,pcall(auth, fd, ...))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ end
|
||||
local function suspend(s)
|
||||
assert(not s.co)
|
||||
s.co = coroutine.running()
|
||||
skynet.wait()
|
||||
skynet.wait(s.co)
|
||||
-- wakeup closing corouting every time suspend,
|
||||
-- because socket.close() will wait last socket buffer operation before clear the buffer.
|
||||
if s.closing then
|
||||
@@ -232,7 +232,7 @@ function socket.close(id)
|
||||
-- wait reading coroutine read the buffer.
|
||||
assert(not s.closing)
|
||||
s.closing = coroutine.running()
|
||||
skynet.wait()
|
||||
skynet.wait(s.closing)
|
||||
else
|
||||
suspend(s)
|
||||
end
|
||||
@@ -361,7 +361,7 @@ function socket.lock(id)
|
||||
else
|
||||
local co = coroutine.running()
|
||||
table.insert(lock_set, co)
|
||||
skynet.wait()
|
||||
skynet.wait(co)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -116,7 +116,14 @@ local function dispatch_by_session(self)
|
||||
end
|
||||
|
||||
local function pop_response(self)
|
||||
return table.remove(self.__request, 1), table.remove(self.__thread, 1)
|
||||
while true do
|
||||
local func,co = table.remove(self.__request, 1), table.remove(self.__thread, 1)
|
||||
if func then
|
||||
return func, co
|
||||
end
|
||||
self.__wait_response = coroutine.running()
|
||||
skynet.wait(self.__wait_response)
|
||||
end
|
||||
end
|
||||
|
||||
local function push_response(self, response, co)
|
||||
@@ -127,46 +134,43 @@ local function push_response(self, response, co)
|
||||
-- response is a function, push it to __request
|
||||
table.insert(self.__request, response)
|
||||
table.insert(self.__thread, co)
|
||||
if self.__wait_response then
|
||||
skynet.wakeup(self.__wait_response)
|
||||
self.__wait_response = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function dispatch_by_order(self)
|
||||
while self.__sock do
|
||||
local func, co = pop_response(self)
|
||||
if func == nil then
|
||||
if not socket.block(self.__sock[1]) then
|
||||
close_channel_socket(self)
|
||||
wakeup_all(self)
|
||||
local ok, result_ok, result_data, padding = pcall(func, self.__sock)
|
||||
if ok then
|
||||
if padding and result_ok then
|
||||
-- if padding is true, wait for next result_data
|
||||
-- self.__result_data[co] is a table
|
||||
local result = self.__result_data[co] or {}
|
||||
self.__result_data[co] = result
|
||||
table.insert(result, result_data)
|
||||
else
|
||||
self.__result[co] = result_ok
|
||||
if result_ok and self.__result_data[co] then
|
||||
table.insert(self.__result_data[co], result_data)
|
||||
else
|
||||
self.__result_data[co] = result_data
|
||||
end
|
||||
skynet.wakeup(co)
|
||||
end
|
||||
else
|
||||
local ok, result_ok, result_data, padding = pcall(func, self.__sock)
|
||||
if ok then
|
||||
if padding and result_ok then
|
||||
-- if padding is true, wait for next result_data
|
||||
-- self.__result_data[co] is a table
|
||||
local result = self.__result_data[co] or {}
|
||||
self.__result_data[co] = result
|
||||
table.insert(result, result_data)
|
||||
else
|
||||
self.__result[co] = result_ok
|
||||
if result_ok and self.__result_data[co] then
|
||||
table.insert(self.__result_data[co], result_data)
|
||||
else
|
||||
self.__result_data[co] = result_data
|
||||
end
|
||||
skynet.wakeup(co)
|
||||
end
|
||||
else
|
||||
close_channel_socket(self)
|
||||
local errmsg
|
||||
if result_ok ~= socket_error then
|
||||
errmsg = result_ok
|
||||
end
|
||||
self.__result[co] = socket_error
|
||||
self.__result_data[co] = errmsg
|
||||
skynet.wakeup(co)
|
||||
wakeup_all(self, errmsg)
|
||||
close_channel_socket(self)
|
||||
local errmsg
|
||||
if result_ok ~= socket_error then
|
||||
errmsg = result_ok
|
||||
end
|
||||
self.__result[co] = socket_error
|
||||
self.__result_data[co] = errmsg
|
||||
skynet.wakeup(co)
|
||||
wakeup_all(self, errmsg)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -288,7 +292,7 @@ local function block_connect(self, once)
|
||||
-- connecting in other coroutine
|
||||
local co = coroutine.running()
|
||||
table.insert(self.__connecting, co)
|
||||
skynet.wait()
|
||||
skynet.wait(co)
|
||||
else
|
||||
self.__connecting[1] = true
|
||||
try_connect(self, once)
|
||||
@@ -319,7 +323,7 @@ end
|
||||
local function wait_for_response(self, response)
|
||||
local co = coroutine.running()
|
||||
push_response(self, response, co)
|
||||
skynet.wait()
|
||||
skynet.wait(co)
|
||||
|
||||
local result = self.__result[co]
|
||||
self.__result[co] = nil
|
||||
|
||||
@@ -58,6 +58,15 @@ local function querytype(self, typename)
|
||||
return v
|
||||
end
|
||||
|
||||
function sproto:exist_type(typename)
|
||||
local v = self.__tcache[typename]
|
||||
if not v then
|
||||
return core.querytype(self.__cobj, typename) ~= nil
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function sproto:encode(typename, tbl)
|
||||
local st = querytype(self, typename)
|
||||
return core.encode(st, tbl)
|
||||
@@ -99,6 +108,15 @@ local function queryproto(self, pname)
|
||||
return v
|
||||
end
|
||||
|
||||
function sproto:exist_proto(pname)
|
||||
local v = self.__pcache[pname]
|
||||
if not v then
|
||||
return core.protocol(self.__cobj, pname) ~= nil
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function sproto:request_encode(protoname, tbl)
|
||||
local p = queryproto(self, protoname)
|
||||
local request = p.request
|
||||
|
||||
@@ -132,7 +132,12 @@ _ctrl(struct gate * g, const void * msg, int sz) {
|
||||
return;
|
||||
}
|
||||
if (memcmp(command,"start",i) == 0) {
|
||||
skynet_socket_start(ctx, g->listen_id);
|
||||
_parm(tmp, sz, i);
|
||||
int uid = strtol(command , NULL, 10);
|
||||
int id = hashid_lookup(&g->hash, uid);
|
||||
if (id>=0) {
|
||||
skynet_socket_start(ctx, uid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (memcmp(command, "close", i) == 0) {
|
||||
@@ -225,10 +230,7 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes
|
||||
break;
|
||||
}
|
||||
int id = hashid_lookup(&g->hash, message->id);
|
||||
if (id>=0) {
|
||||
struct connection *c = &g->conn[id];
|
||||
_report(g, "%d open %d %s:0",message->id,message->id,c->remote_name);
|
||||
} else {
|
||||
if (id<0) {
|
||||
skynet_error(ctx, "Close unknown connection %d", message->id);
|
||||
skynet_socket_close(ctx, message->id);
|
||||
}
|
||||
@@ -259,7 +261,8 @@ dispatch_socket_message(struct gate *g, const struct skynet_socket_message * mes
|
||||
c->id = message->ud;
|
||||
memcpy(c->remote_name, message+1, sz);
|
||||
c->remote_name[sz] = '\0';
|
||||
skynet_socket_start(ctx, message->ud);
|
||||
_report(g, "%d open %d %s:0",c->id, c->id, c->remote_name);
|
||||
skynet_error(ctx, "socket open: %x", c->id);
|
||||
}
|
||||
break;
|
||||
case SKYNET_SOCKET_TYPE_WARNING:
|
||||
@@ -327,6 +330,7 @@ start_listen(struct gate *g, char * listen_addr) {
|
||||
if (g->listen_id < 0) {
|
||||
return 1;
|
||||
}
|
||||
skynet_socket_start(ctx, g->listen_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,13 +339,12 @@ gate_init(struct gate *g , struct skynet_context * ctx, char * parm) {
|
||||
if (parm == NULL)
|
||||
return 1;
|
||||
int max = 0;
|
||||
int buffer = 0;
|
||||
int sz = strlen(parm)+1;
|
||||
char watchdog[sz];
|
||||
char binding[sz];
|
||||
int client_tag = 0;
|
||||
char header;
|
||||
int n = sscanf(parm, "%c %s %s %d %d %d",&header,watchdog, binding,&client_tag , &max,&buffer);
|
||||
int n = sscanf(parm, "%c %s %s %d %d", &header, watchdog, binding, &client_tag, &max);
|
||||
if (n<4) {
|
||||
skynet_error(ctx, "Invalid gate parm %s",parm);
|
||||
return 1;
|
||||
|
||||
@@ -30,6 +30,7 @@ static int
|
||||
codecache(lua_State *L) {
|
||||
luaL_Reg l[] = {
|
||||
{ "clear", cleardummy },
|
||||
{ "mode", cleardummy },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
luaL_newlib(L,l);
|
||||
|
||||
@@ -67,7 +67,7 @@ end
|
||||
-- for remote node, call remote_publish. (call mc.unpack and skynet.tostring to convert message pointer to string)
|
||||
local function publish(c , source, pack, size)
|
||||
local group = channel[c]
|
||||
if group == nil then
|
||||
if group == nil or next(group) == nil then
|
||||
-- dead channel, delete the pack. mc.bind returns the pointer in pack
|
||||
local pack = mc.bind(pack, 1)
|
||||
mc.close(pack)
|
||||
|
||||
@@ -208,7 +208,7 @@ timer_create_timer() {
|
||||
|
||||
int
|
||||
skynet_timeout(uint32_t handle, int time, int session) {
|
||||
if (time == 0) {
|
||||
if (time <= 0) {
|
||||
struct skynet_message message;
|
||||
message.source = 0;
|
||||
message.session = session;
|
||||
|
||||
@@ -1176,6 +1176,7 @@ clear_closed_event(struct socket_server *ss, struct socket_message * result, int
|
||||
if (s) {
|
||||
if (s->type == SOCKET_TYPE_INVALID && s->id == id) {
|
||||
e->s = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1245,21 +1246,19 @@ socket_server_poll(struct socket_server *ss, struct socket_message * result, int
|
||||
return SOCKET_UDP;
|
||||
}
|
||||
}
|
||||
if (e->write) {
|
||||
if (e->write && type != SOCKET_CLOSE && type != SOCKET_ERROR) {
|
||||
// Try to dispatch write message next step if write flag set.
|
||||
e->read = false;
|
||||
--ss->event_index;
|
||||
}
|
||||
if (type == -1)
|
||||
break;
|
||||
clear_closed_event(ss, result, type);
|
||||
break;
|
||||
return type;
|
||||
}
|
||||
if (e->write) {
|
||||
int type = send_buffer(ss, s, result);
|
||||
if (type == -1)
|
||||
break;
|
||||
clear_closed_event(ss, result, type);
|
||||
return type;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -34,6 +34,7 @@ spinlock_unlock(struct spinlock *lock) {
|
||||
|
||||
static inline void
|
||||
spinlock_destroy(struct spinlock *lock) {
|
||||
(void) lock;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user