immunio 1.1.13 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/immunio/plugins/action_view.rb +22 -4
- data/lib/immunio/plugins/active_record.rb +6 -1
- data/lib/immunio/plugins/active_record_relation.rb +5 -5
- data/lib/immunio/plugins/exception_handler.rb +8 -2
- data/lib/immunio/version.rb +1 -1
- data/lua-hooks/Makefile +31 -11
- data/lua-hooks/ext/all.c +3 -3
- data/lua-hooks/ext/libinjection/libinjection_sqli.h +1 -1
- data/lua-hooks/ext/libinjection/lualib.c +16 -0
- data/lua-hooks/ext/lpeg/HISTORY +7 -1
- data/lua-hooks/ext/lpeg/lpcap.c +2 -2
- data/lua-hooks/ext/lpeg/lpcap.h +17 -4
- data/lua-hooks/ext/lpeg/lpcode.c +123 -95
- data/lua-hooks/ext/lpeg/lpcode.h +12 -6
- data/lua-hooks/ext/lpeg/lpeg.html +39 -23
- data/lua-hooks/ext/lpeg/lpprint.c +17 -17
- data/lua-hooks/ext/lpeg/lpprint.h +3 -2
- data/lua-hooks/ext/lpeg/lptree.c +264 -199
- data/lua-hooks/ext/lpeg/lptree.h +30 -25
- data/lua-hooks/ext/lpeg/lptypes.h +24 -24
- data/lua-hooks/ext/lpeg/lpvm.c +27 -18
- data/lua-hooks/ext/lpeg/lpvm.h +6 -6
- data/lua-hooks/ext/lpeg/re.html +5 -5
- data/lua-hooks/ext/luajit/src/lib_init.c +19 -15
- data/lua-hooks/lib/hooks/module.mk +12 -7
- data/lua-hooks/lib/hooks/xss/module.mk +2 -2
- data/lua-hooks/lib/lexers/module.mk +2 -3
- data/lua-hooks/lib/module.mk +7 -3
- data/lua-hooks/options.mk +9 -3
- metadata +6 -7
- data/lua-hooks/ext/lpeg/test.lua +0 -1409
- data/lua-hooks/lib/schema/module.mk +0 -3
data/lua-hooks/ext/lpeg/lpcode.h
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
** $Id: lpcode.h,v 1.
|
2
|
+
** $Id: lpcode.h,v 1.8 2016/09/15 17:46:13 roberto Exp $
|
3
3
|
*/
|
4
4
|
|
5
5
|
#if !defined(lpcode_h)
|
@@ -13,21 +13,27 @@
|
|
13
13
|
|
14
14
|
int tocharset (TTree *tree, Charset *cs);
|
15
15
|
int checkaux (TTree *tree, int pred);
|
16
|
-
int
|
16
|
+
int fixedlen (TTree *tree);
|
17
17
|
int hascaptures (TTree *tree);
|
18
18
|
int lp_gc (lua_State *L);
|
19
|
-
|
19
|
+
Instruction *compile (lua_State *L, Pattern *p);
|
20
20
|
void realloccode (lua_State *L, Pattern *p, int nsize);
|
21
|
-
int sizei (const
|
21
|
+
int sizei (const Instruction *i);
|
22
22
|
|
23
23
|
|
24
24
|
#define PEnullable 0
|
25
25
|
#define PEnofail 1
|
26
26
|
|
27
|
+
/*
|
28
|
+
** nofail(t) implies that 't' cannot fail with any input
|
29
|
+
*/
|
27
30
|
#define nofail(t) checkaux(t, PEnofail)
|
28
|
-
#define nullable(t) checkaux(t, PEnullable)
|
29
31
|
|
30
|
-
|
32
|
+
/*
|
33
|
+
** (not nullable(t)) implies 't' cannot match without consuming
|
34
|
+
** something
|
35
|
+
*/
|
36
|
+
#define nullable(t) checkaux(t, PEnullable)
|
31
37
|
|
32
38
|
|
33
39
|
|
@@ -10,7 +10,7 @@
|
|
10
10
|
</head>
|
11
11
|
<body>
|
12
12
|
|
13
|
-
<!-- $Id: lpeg.html,v 1.
|
13
|
+
<!-- $Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $ -->
|
14
14
|
|
15
15
|
<div id="container">
|
16
16
|
|
@@ -22,7 +22,7 @@
|
|
22
22
|
</div>
|
23
23
|
<div id="product_name"><big><strong>LPeg</strong></big></div>
|
24
24
|
<div id="product_description">
|
25
|
-
Parsing Expression Grammars For Lua, version 0
|
25
|
+
Parsing Expression Grammars For Lua, version 1.0
|
26
26
|
</div>
|
27
27
|
</div> <!-- id="product" -->
|
28
28
|
|
@@ -195,13 +195,16 @@ Returns a string with the running version of LPeg.
|
|
195
195
|
|
196
196
|
<h3><a name="f-setstack"></a><code>lpeg.setmaxstack (max)</code></h3>
|
197
197
|
<p>
|
198
|
-
Sets the
|
198
|
+
Sets a limit for the size of the backtrack stack used by LPeg to
|
199
199
|
track calls and choices.
|
200
|
+
(The default limit is 400.)
|
200
201
|
Most well-written patterns need little backtrack levels and
|
201
|
-
therefore you seldom need to change this
|
202
|
-
|
203
|
-
Before changing this maximum you should try to rewrite your
|
202
|
+
therefore you seldom need to change this limit;
|
203
|
+
before changing it you should try to rewrite your
|
204
204
|
pattern to avoid the need for extra space.
|
205
|
+
Nevertheless, a few useful patterns may overflow.
|
206
|
+
Also, with recursive grammars,
|
207
|
+
subjects with deep recursion may also need larger limits.
|
205
208
|
</p>
|
206
209
|
|
207
210
|
|
@@ -574,8 +577,9 @@ It is equivalent to the following grammar in standard PEG notation:
|
|
574
577
|
<h2><a name="captures">Captures</a></h2>
|
575
578
|
|
576
579
|
<p>
|
577
|
-
A <em>capture</em> is a pattern that
|
578
|
-
(the so called <em>semantic information</em>)
|
580
|
+
A <em>capture</em> is a pattern that produces values
|
581
|
+
(the so called <em>semantic information</em>)
|
582
|
+
according to what it matches.
|
579
583
|
LPeg offers several kinds of captures,
|
580
584
|
which produces values based on matches and combine these values to
|
581
585
|
produce new values.
|
@@ -629,10 +633,7 @@ or no value when <code>number</code> is zero.</td></tr>
|
|
629
633
|
</tbody></table>
|
630
634
|
|
631
635
|
<p>
|
632
|
-
A capture pattern produces its values
|
633
|
-
For instance,
|
634
|
-
a capture inside a loop produces as many values as matched by the loop.
|
635
|
-
A capture produces a value only when it succeeds.
|
636
|
+
A capture pattern produces its values only when it succeeds.
|
636
637
|
For instance,
|
637
638
|
the pattern <code>lpeg.C(lpeg.P"a"^-1)</code>
|
638
639
|
produces the empty string when there is no <code>"a"</code>
|
@@ -640,14 +641,20 @@ produces the empty string when there is no <code>"a"</code>
|
|
640
641
|
while the pattern <code>lpeg.C("a")^-1</code>
|
641
642
|
does not produce any value when there is no <code>"a"</code>
|
642
643
|
(because the pattern <code>"a"</code> fails).
|
644
|
+
A pattern inside a loop or inside a recursive structure
|
645
|
+
produces values for each match.
|
643
646
|
</p>
|
644
647
|
|
645
648
|
<p>
|
646
649
|
Usually,
|
647
|
-
LPeg
|
648
|
-
|
649
|
-
|
650
|
-
|
650
|
+
LPeg does not specify when (and if) it evaluates its captures.
|
651
|
+
(As an example,
|
652
|
+
consider the pattern <code>lpeg.P"a" / func / 0</code>.
|
653
|
+
Because the "division" by 0 instructs LPeg to throw away the
|
654
|
+
results from the pattern,
|
655
|
+
LPeg may or may not call <code>func</code>.)
|
656
|
+
Therefore, captures should avoid side effects.
|
657
|
+
Moreover,
|
651
658
|
most captures cannot affect the way a pattern matches a subject.
|
652
659
|
The only exception to this rule is the
|
653
660
|
so-called <a href="#matchtime"><em>match-time capture</em></a>.
|
@@ -682,7 +689,8 @@ argument given in the call to <code>lpeg.match</code>.
|
|
682
689
|
Creates a <em>back capture</em>.
|
683
690
|
This pattern matches the empty string and
|
684
691
|
produces the values produced by the <em>most recent</em>
|
685
|
-
<a href="#cap-g">group capture</a> named <code>name</code
|
692
|
+
<a href="#cap-g">group capture</a> named <code>name</code>
|
693
|
+
(where <code>name</code> can be any Lua value).
|
686
694
|
</p>
|
687
695
|
|
688
696
|
<p>
|
@@ -696,6 +704,12 @@ An <em>Outermost</em> capture means that the capture is not inside
|
|
696
704
|
another complete capture.
|
697
705
|
</p>
|
698
706
|
|
707
|
+
<p>
|
708
|
+
In the same way that LPeg does not specify when it evaluates captures,
|
709
|
+
it does not specify whether it reuses
|
710
|
+
values previously produced by the group
|
711
|
+
or re-evaluates them.
|
712
|
+
</p>
|
699
713
|
|
700
714
|
<h3><a name="cap-cc"></a><code>lpeg.Cc ([value, ...])</code></h3>
|
701
715
|
<p>
|
@@ -762,7 +776,8 @@ Creates a <em>group capture</em>.
|
|
762
776
|
It groups all values returned by <code>patt</code>
|
763
777
|
into a single capture.
|
764
778
|
The group may be anonymous (if no name is given)
|
765
|
-
or named with the given name
|
779
|
+
or named with the given name
|
780
|
+
(which can be any non-nil Lua value).
|
766
781
|
</p>
|
767
782
|
|
768
783
|
<p>
|
@@ -801,7 +816,7 @@ all replacements.
|
|
801
816
|
<h3><a name="cap-t"></a><code>lpeg.Ct (patt)</code></h3>
|
802
817
|
<p>
|
803
818
|
Creates a <em>table capture</em>.
|
804
|
-
This capture
|
819
|
+
This capture returns a table with all values from all anonymous captures
|
805
820
|
made by <code>patt</code> inside this table in successive integer keys,
|
806
821
|
starting at 1.
|
807
822
|
Moreover,
|
@@ -867,7 +882,8 @@ there is no captured value.
|
|
867
882
|
<p>
|
868
883
|
Creates a <em>match-time capture</em>.
|
869
884
|
Unlike all other captures,
|
870
|
-
this one is evaluated immediately when a match occurs
|
885
|
+
this one is evaluated immediately when a match occurs
|
886
|
+
(even if it is part of a larger pattern that fails later).
|
871
887
|
It forces the immediate evaluation of all its nested captures
|
872
888
|
and then calls <code>function</code>.
|
873
889
|
</p>
|
@@ -1375,13 +1391,13 @@ and the new term for each repetition.
|
|
1375
1391
|
<h2><a name="download"></a>Download</h2>
|
1376
1392
|
|
1377
1393
|
<p>LPeg
|
1378
|
-
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-0.
|
1394
|
+
<a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.0.1.tar.gz">source code</a>.</p>
|
1379
1395
|
|
1380
1396
|
|
1381
1397
|
<h2><a name="license">License</a></h2>
|
1382
1398
|
|
1383
1399
|
<p>
|
1384
|
-
Copyright ©
|
1400
|
+
Copyright © 2007-2017 Lua.org, PUC-Rio.
|
1385
1401
|
</p>
|
1386
1402
|
<p>
|
1387
1403
|
Permission is hereby granted, free of charge,
|
@@ -1419,7 +1435,7 @@ THE SOFTWARE.
|
|
1419
1435
|
|
1420
1436
|
<div id="about">
|
1421
1437
|
<p><small>
|
1422
|
-
$Id: lpeg.html,v 1.
|
1438
|
+
$Id: lpeg.html,v 1.77 2017/01/13 13:40:05 roberto Exp $
|
1423
1439
|
</small></p>
|
1424
1440
|
</div> <!-- id="about" -->
|
1425
1441
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
** $Id: lpprint.c,v 1.
|
2
|
+
** $Id: lpprint.c,v 1.10 2016/09/13 16:06:03 roberto Exp $
|
3
3
|
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
4
4
|
*/
|
5
5
|
|
@@ -37,22 +37,22 @@ void printcharset (const byte *st) {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
|
40
|
-
static
|
40
|
+
static const char *capkind (int kind) {
|
41
41
|
const char *const modes[] = {
|
42
42
|
"close", "position", "constant", "backref",
|
43
43
|
"argument", "simple", "table", "function",
|
44
44
|
"query", "string", "num", "substitution", "fold",
|
45
45
|
"runtime", "group"};
|
46
|
-
|
46
|
+
return modes[kind];
|
47
47
|
}
|
48
48
|
|
49
49
|
|
50
|
-
static void printjmp (const
|
50
|
+
static void printjmp (const Instruction *op, const Instruction *p) {
|
51
51
|
printf("-> %d", (int)(p + (p + 1)->offset - op));
|
52
52
|
}
|
53
53
|
|
54
54
|
|
55
|
-
|
55
|
+
void printinst (const Instruction *op, const Instruction *p) {
|
56
56
|
const char *const names[] = {
|
57
57
|
"any", "char", "set",
|
58
58
|
"testany", "testchar", "testset",
|
@@ -73,13 +73,12 @@ static void printinst (const LpegInstruction *op, const LpegInstruction *p) {
|
|
73
73
|
break;
|
74
74
|
}
|
75
75
|
case IFullCapture: {
|
76
|
-
|
77
|
-
|
76
|
+
printf("%s (size = %d) (idx = %d)",
|
77
|
+
capkind(getkind(p)), getoff(p), p->i.key);
|
78
78
|
break;
|
79
79
|
}
|
80
80
|
case IOpenCapture: {
|
81
|
-
|
82
|
-
printf(" (idx = %d)", p->i.key);
|
81
|
+
printf("%s (idx = %d)", capkind(getkind(p)), p->i.key);
|
83
82
|
break;
|
84
83
|
}
|
85
84
|
case ISet: {
|
@@ -113,8 +112,8 @@ static void printinst (const LpegInstruction *op, const LpegInstruction *p) {
|
|
113
112
|
}
|
114
113
|
|
115
114
|
|
116
|
-
void printpatt (
|
117
|
-
|
115
|
+
void printpatt (Instruction *p, int n) {
|
116
|
+
Instruction *op = p;
|
118
117
|
while (p < op + n) {
|
119
118
|
printinst(op, p);
|
120
119
|
p += sizei(p);
|
@@ -124,8 +123,8 @@ void printpatt (LpegInstruction *p, int n) {
|
|
124
123
|
|
125
124
|
#if defined(LPEG_DEBUG)
|
126
125
|
static void printcap (Capture *cap) {
|
127
|
-
|
128
|
-
|
126
|
+
printf("%s (idx: %d - size: %d) -> %p\n",
|
127
|
+
capkind(cap->kind), cap->idx, cap->siz, cap->s);
|
129
128
|
}
|
130
129
|
|
131
130
|
|
@@ -177,7 +176,8 @@ void printtree (TTree *tree, int ident) {
|
|
177
176
|
break;
|
178
177
|
}
|
179
178
|
case TOpenCall: case TCall: {
|
180
|
-
|
179
|
+
assert(sib2(tree)->tag == TRule);
|
180
|
+
printf(" key: %d (rule: %d)\n", tree->key, sib2(tree)->cap);
|
181
181
|
break;
|
182
182
|
}
|
183
183
|
case TBehind: {
|
@@ -186,7 +186,7 @@ void printtree (TTree *tree, int ident) {
|
|
186
186
|
break;
|
187
187
|
}
|
188
188
|
case TCapture: {
|
189
|
-
printf("
|
189
|
+
printf(" kind: '%s' key: %d\n", capkind(tree->cap), tree->key);
|
190
190
|
printtree(sib1(tree), ident + 2);
|
191
191
|
break;
|
192
192
|
}
|
@@ -221,10 +221,10 @@ void printtree (TTree *tree, int ident) {
|
|
221
221
|
|
222
222
|
void printktable (lua_State *L, int idx) {
|
223
223
|
int n, i;
|
224
|
-
|
224
|
+
lua_getuservalue(L, idx);
|
225
225
|
if (lua_isnil(L, -1)) /* no ktable? */
|
226
226
|
return;
|
227
|
-
n =
|
227
|
+
n = lua_rawlen(L, -1);
|
228
228
|
printf("[");
|
229
229
|
for (i = 1; i <= n; i++) {
|
230
230
|
printf("%d = ", i);
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
** $Id: lpprint.h,v 1.
|
2
|
+
** $Id: lpprint.h,v 1.2 2015/06/12 18:18:08 roberto Exp $
|
3
3
|
*/
|
4
4
|
|
5
5
|
|
@@ -13,11 +13,12 @@
|
|
13
13
|
|
14
14
|
#if defined(LPEG_DEBUG)
|
15
15
|
|
16
|
-
void printpatt (
|
16
|
+
void printpatt (Instruction *p, int n);
|
17
17
|
void printtree (TTree *tree, int ident);
|
18
18
|
void printktable (lua_State *L, int idx);
|
19
19
|
void printcharset (const byte *st);
|
20
20
|
void printcaplist (Capture *cap, Capture *limit);
|
21
|
+
void printinst (const Instruction *op, const Instruction *p);
|
21
22
|
|
22
23
|
#else
|
23
24
|
|
data/lua-hooks/ext/lpeg/lptree.c
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
** $Id: lptree.c,v 1.
|
2
|
+
** $Id: lptree.c,v 1.22 2016/09/13 18:10:22 roberto Exp $
|
3
3
|
** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
4
4
|
*/
|
5
5
|
|
@@ -64,7 +64,7 @@ static void fixonecall (lua_State *L, int postable, TTree *g, TTree *t) {
|
|
64
64
|
t->tag = TCall;
|
65
65
|
t->u.ps = n - (t - g); /* position relative to node */
|
66
66
|
assert(sib2(t)->tag == TRule);
|
67
|
-
sib2(t)->key = t->key;
|
67
|
+
sib2(t)->key = t->key; /* fix rule's key */
|
68
68
|
}
|
69
69
|
|
70
70
|
|
@@ -126,6 +126,189 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) {
|
|
126
126
|
}
|
127
127
|
|
128
128
|
|
129
|
+
|
130
|
+
/*
|
131
|
+
** {===================================================================
|
132
|
+
** KTable manipulation
|
133
|
+
**
|
134
|
+
** - The ktable of a pattern 'p' can be shared by other patterns that
|
135
|
+
** contain 'p' and no other constants. Because of this sharing, we
|
136
|
+
** should not add elements to a 'ktable' unless it was freshly created
|
137
|
+
** for the new pattern.
|
138
|
+
**
|
139
|
+
** - The maximum index in a ktable is USHRT_MAX, because trees and
|
140
|
+
** patterns use unsigned shorts to store those indices.
|
141
|
+
** ====================================================================
|
142
|
+
*/
|
143
|
+
|
144
|
+
/*
|
145
|
+
** Create a new 'ktable' to the pattern at the top of the stack.
|
146
|
+
*/
|
147
|
+
static void newktable (lua_State *L, int n) {
|
148
|
+
lua_createtable(L, n, 0); /* create a fresh table */
|
149
|
+
lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */
|
150
|
+
}
|
151
|
+
|
152
|
+
|
153
|
+
/*
|
154
|
+
** Add element 'idx' to 'ktable' of pattern at the top of the stack;
|
155
|
+
** Return index of new element.
|
156
|
+
** If new element is nil, does not add it to table (as it would be
|
157
|
+
** useless) and returns 0, as ktable[0] is always nil.
|
158
|
+
*/
|
159
|
+
static int addtoktable (lua_State *L, int idx) {
|
160
|
+
if (lua_isnil(L, idx)) /* nil value? */
|
161
|
+
return 0;
|
162
|
+
else {
|
163
|
+
int n;
|
164
|
+
lua_getuservalue(L, -1); /* get ktable from pattern */
|
165
|
+
n = lua_rawlen(L, -1);
|
166
|
+
if (n >= USHRT_MAX)
|
167
|
+
luaL_error(L, "too many Lua values in pattern");
|
168
|
+
lua_pushvalue(L, idx); /* element to be added */
|
169
|
+
lua_rawseti(L, -2, ++n);
|
170
|
+
lua_pop(L, 1); /* remove 'ktable' */
|
171
|
+
return n;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
|
176
|
+
/*
|
177
|
+
** Return the number of elements in the ktable at 'idx'.
|
178
|
+
** In Lua 5.2/5.3, default "environment" for patterns is nil, not
|
179
|
+
** a table. Treat it as an empty table. In Lua 5.1, assumes that
|
180
|
+
** the environment has no numeric indices (len == 0)
|
181
|
+
*/
|
182
|
+
static int ktablelen (lua_State *L, int idx) {
|
183
|
+
if (!lua_istable(L, idx)) return 0;
|
184
|
+
else return lua_rawlen(L, idx);
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
/*
|
189
|
+
** Concatentate the contents of table 'idx1' into table 'idx2'.
|
190
|
+
** (Assume that both indices are negative.)
|
191
|
+
** Return the original length of table 'idx2' (or 0, if no
|
192
|
+
** element was added, as there is no need to correct any index).
|
193
|
+
*/
|
194
|
+
static int concattable (lua_State *L, int idx1, int idx2) {
|
195
|
+
int i;
|
196
|
+
int n1 = ktablelen(L, idx1);
|
197
|
+
int n2 = ktablelen(L, idx2);
|
198
|
+
if (n1 + n2 > USHRT_MAX)
|
199
|
+
luaL_error(L, "too many Lua values in pattern");
|
200
|
+
if (n1 == 0) return 0; /* nothing to correct */
|
201
|
+
for (i = 1; i <= n1; i++) {
|
202
|
+
lua_rawgeti(L, idx1, i);
|
203
|
+
lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */
|
204
|
+
}
|
205
|
+
return n2;
|
206
|
+
}
|
207
|
+
|
208
|
+
|
209
|
+
/*
|
210
|
+
** When joining 'ktables', constants from one of the subpatterns must
|
211
|
+
** be renumbered; 'correctkeys' corrects their indices (adding 'n'
|
212
|
+
** to each of them)
|
213
|
+
*/
|
214
|
+
static void correctkeys (TTree *tree, int n) {
|
215
|
+
if (n == 0) return; /* no correction? */
|
216
|
+
tailcall:
|
217
|
+
switch (tree->tag) {
|
218
|
+
case TOpenCall: case TCall: case TRunTime: case TRule: {
|
219
|
+
if (tree->key > 0)
|
220
|
+
tree->key += n;
|
221
|
+
break;
|
222
|
+
}
|
223
|
+
case TCapture: {
|
224
|
+
if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)
|
225
|
+
tree->key += n;
|
226
|
+
break;
|
227
|
+
}
|
228
|
+
default: break;
|
229
|
+
}
|
230
|
+
switch (numsiblings[tree->tag]) {
|
231
|
+
case 1: /* correctkeys(sib1(tree), n); */
|
232
|
+
tree = sib1(tree); goto tailcall;
|
233
|
+
case 2:
|
234
|
+
correctkeys(sib1(tree), n);
|
235
|
+
tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */
|
236
|
+
default: assert(numsiblings[tree->tag] == 0); break;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
|
241
|
+
/*
|
242
|
+
** Join the ktables from p1 and p2 the ktable for the new pattern at the
|
243
|
+
** top of the stack, reusing them when possible.
|
244
|
+
*/
|
245
|
+
static void joinktables (lua_State *L, int p1, TTree *t2, int p2) {
|
246
|
+
int n1, n2;
|
247
|
+
lua_getuservalue(L, p1); /* get ktables */
|
248
|
+
lua_getuservalue(L, p2);
|
249
|
+
n1 = ktablelen(L, -2);
|
250
|
+
n2 = ktablelen(L, -1);
|
251
|
+
if (n1 == 0 && n2 == 0) /* are both tables empty? */
|
252
|
+
lua_pop(L, 2); /* nothing to be done; pop tables */
|
253
|
+
else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */
|
254
|
+
lua_pop(L, 1); /* pop 2nd table */
|
255
|
+
lua_setuservalue(L, -2); /* set 1st ktable into new pattern */
|
256
|
+
}
|
257
|
+
else if (n1 == 0) { /* first table is empty? */
|
258
|
+
lua_setuservalue(L, -3); /* set 2nd table into new pattern */
|
259
|
+
lua_pop(L, 1); /* pop 1st table */
|
260
|
+
}
|
261
|
+
else {
|
262
|
+
lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */
|
263
|
+
/* stack: new p; ktable p1; ktable p2; new ktable */
|
264
|
+
concattable(L, -3, -1); /* from p1 into new ktable */
|
265
|
+
concattable(L, -2, -1); /* from p2 into new ktable */
|
266
|
+
lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */
|
267
|
+
lua_pop(L, 2); /* pop other ktables */
|
268
|
+
correctkeys(t2, n1); /* correction for indices from p2 */
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
|
273
|
+
/*
|
274
|
+
** copy 'ktable' of element 'idx' to new tree (on top of stack)
|
275
|
+
*/
|
276
|
+
static void copyktable (lua_State *L, int idx) {
|
277
|
+
lua_getuservalue(L, idx);
|
278
|
+
lua_setuservalue(L, -2);
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
/*
|
283
|
+
** merge 'ktable' from 'stree' at stack index 'idx' into 'ktable'
|
284
|
+
** from tree at the top of the stack, and correct corresponding
|
285
|
+
** tree.
|
286
|
+
*/
|
287
|
+
static void mergektable (lua_State *L, int idx, TTree *stree) {
|
288
|
+
int n;
|
289
|
+
lua_getuservalue(L, -1); /* get ktables */
|
290
|
+
lua_getuservalue(L, idx);
|
291
|
+
n = concattable(L, -1, -2);
|
292
|
+
lua_pop(L, 2); /* remove both ktables */
|
293
|
+
correctkeys(stree, n);
|
294
|
+
}
|
295
|
+
|
296
|
+
|
297
|
+
/*
|
298
|
+
** Create a new 'ktable' to the pattern at the top of the stack, adding
|
299
|
+
** all elements from pattern 'p' (if not 0) plus element 'idx' to it.
|
300
|
+
** Return index of new element.
|
301
|
+
*/
|
302
|
+
static int addtonewktable (lua_State *L, int p, int idx) {
|
303
|
+
newktable(L, 1);
|
304
|
+
if (p)
|
305
|
+
mergektable(L, p, NULL);
|
306
|
+
return addtoktable(L, idx);
|
307
|
+
}
|
308
|
+
|
309
|
+
/* }====================================================== */
|
310
|
+
|
311
|
+
|
129
312
|
/*
|
130
313
|
** {======================================================
|
131
314
|
** Tree generation
|
@@ -155,7 +338,7 @@ static Pattern *getpattern (lua_State *L, int idx) {
|
|
155
338
|
|
156
339
|
|
157
340
|
static int getsize (lua_State *L, int idx) {
|
158
|
-
return (
|
341
|
+
return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1;
|
159
342
|
}
|
160
343
|
|
161
344
|
|
@@ -168,12 +351,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) {
|
|
168
351
|
|
169
352
|
|
170
353
|
/*
|
171
|
-
** create a pattern
|
354
|
+
** create a pattern. Set its uservalue (the 'ktable') equal to its
|
355
|
+
** metatable. (It could be any empty sequence; the metatable is at
|
356
|
+
** hand here, so we use it.)
|
172
357
|
*/
|
173
358
|
static TTree *newtree (lua_State *L, int len) {
|
174
359
|
size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern);
|
175
360
|
Pattern *p = (Pattern *)lua_newuserdata(L, size);
|
176
361
|
luaL_getmetatable(L, PATTERN_T);
|
362
|
+
lua_pushvalue(L, -1);
|
363
|
+
lua_setuservalue(L, -3);
|
177
364
|
lua_setmetatable(L, -2);
|
178
365
|
p->code = NULL; p->codesize = 0;
|
179
366
|
return p->tree;
|
@@ -206,35 +393,6 @@ static TTree *seqaux (TTree *tree, TTree *sib, int sibsize) {
|
|
206
393
|
}
|
207
394
|
|
208
395
|
|
209
|
-
/*
|
210
|
-
** Add element 'idx' to 'ktable' of pattern at the top of the stack;
|
211
|
-
** create new 'ktable' if necessary. Return index of new element.
|
212
|
-
** If new element is nil, does not add it to table (as it would be
|
213
|
-
** useless) and returns 0, as ktable[0] is always nil.
|
214
|
-
*/
|
215
|
-
static int addtoktable (lua_State *L, int idx) {
|
216
|
-
if (idx == 0) /* no actual value to insert? */
|
217
|
-
return 0;
|
218
|
-
else {
|
219
|
-
int n;
|
220
|
-
lua_getfenv(L, -1); /* get ktable from pattern */
|
221
|
-
n = lua_objlen(L, -1);
|
222
|
-
if (n == 0) { /* is it empty/non-existent? */
|
223
|
-
lua_pop(L, 1); /* remove it */
|
224
|
-
lua_createtable(L, 1, 0); /* create a fresh table */
|
225
|
-
lua_pushvalue(L, -1); /* make a copy */
|
226
|
-
lua_setfenv(L, -3); /* set it as 'ktable' for pattern */
|
227
|
-
}
|
228
|
-
if (!lua_isnil(L, idx)) { /* non-nil value? */
|
229
|
-
lua_pushvalue(L, idx); /* element to be added */
|
230
|
-
lua_rawseti(L, -2, ++n);
|
231
|
-
}
|
232
|
-
lua_pop(L, 1); /* remove 'ktable' */
|
233
|
-
return n;
|
234
|
-
}
|
235
|
-
}
|
236
|
-
|
237
|
-
|
238
396
|
/*
|
239
397
|
** Build a sequence of 'n' nodes, each with tag 'tag' and 'u.n' got
|
240
398
|
** 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) {
|
|
310
468
|
case LUA_TFUNCTION: {
|
311
469
|
tree = newtree(L, 2);
|
312
470
|
tree->tag = TRunTime;
|
313
|
-
tree->key =
|
471
|
+
tree->key = addtonewktable(L, 0, idx);
|
314
472
|
sib1(tree)->tag = TTrue;
|
315
473
|
break;
|
316
474
|
}
|
@@ -325,123 +483,6 @@ static TTree *getpatt (lua_State *L, int idx, int *len) {
|
|
325
483
|
}
|
326
484
|
|
327
485
|
|
328
|
-
/*
|
329
|
-
** Return the number of elements in the ktable of pattern at 'idx'.
|
330
|
-
** In Lua 5.2, default "environment" for patterns is nil, not
|
331
|
-
** a table. Treat it as an empty table. In Lua 5.1, assumes that
|
332
|
-
** the environment has no numeric indices (len == 0)
|
333
|
-
*/
|
334
|
-
static int ktablelen (lua_State *L, int idx) {
|
335
|
-
if (!lua_istable(L, idx)) return 0;
|
336
|
-
else return lua_objlen(L, idx);
|
337
|
-
}
|
338
|
-
|
339
|
-
|
340
|
-
/*
|
341
|
-
** Concatentate the contents of table 'idx1' into table 'idx2'.
|
342
|
-
** (Assume that both indices are negative.)
|
343
|
-
** Return the original length of table 'idx2'
|
344
|
-
*/
|
345
|
-
static int concattable (lua_State *L, int idx1, int idx2) {
|
346
|
-
int i;
|
347
|
-
int n1 = ktablelen(L, idx1);
|
348
|
-
int n2 = ktablelen(L, idx2);
|
349
|
-
if (n1 == 0) return 0; /* nothing to correct */
|
350
|
-
for (i = 1; i <= n1; i++) {
|
351
|
-
lua_rawgeti(L, idx1, i);
|
352
|
-
lua_rawseti(L, idx2 - 1, n2 + i); /* correct 'idx2' */
|
353
|
-
}
|
354
|
-
return n2;
|
355
|
-
}
|
356
|
-
|
357
|
-
|
358
|
-
/*
|
359
|
-
** Make a merge of ktables from p1 and p2 the ktable for the new
|
360
|
-
** pattern at the top of the stack.
|
361
|
-
*/
|
362
|
-
static int joinktables (lua_State *L, int p1, int p2) {
|
363
|
-
int n1, n2;
|
364
|
-
lua_getfenv(L, p1); /* get ktables */
|
365
|
-
lua_getfenv(L, p2);
|
366
|
-
n1 = ktablelen(L, -2);
|
367
|
-
n2 = ktablelen(L, -1);
|
368
|
-
if (n1 == 0 && n2 == 0) { /* are both tables empty? */
|
369
|
-
lua_pop(L, 2); /* nothing to be done; pop tables */
|
370
|
-
return 0; /* nothing to correct */
|
371
|
-
}
|
372
|
-
if (n2 == 0 || lua_equal(L, -2, -1)) { /* second table is empty or equal? */
|
373
|
-
lua_pop(L, 1); /* pop 2nd table */
|
374
|
-
lua_setfenv(L, -2); /* set 1st ktable into new pattern */
|
375
|
-
return 0; /* nothing to correct */
|
376
|
-
}
|
377
|
-
if (n1 == 0) { /* first table is empty? */
|
378
|
-
lua_setfenv(L, -3); /* set 2nd table into new pattern */
|
379
|
-
lua_pop(L, 1); /* pop 1st table */
|
380
|
-
return 0; /* nothing to correct */
|
381
|
-
}
|
382
|
-
else {
|
383
|
-
lua_createtable(L, n1 + n2, 0); /* create ktable for new pattern */
|
384
|
-
/* stack: new p; ktable p1; ktable p2; new ktable */
|
385
|
-
concattable(L, -3, -1); /* from p1 into new ktable */
|
386
|
-
concattable(L, -2, -1); /* from p2 into new ktable */
|
387
|
-
lua_setfenv(L, -4); /* new ktable becomes p env */
|
388
|
-
lua_pop(L, 2); /* pop other ktables */
|
389
|
-
return n1; /* correction for indices from p2 */
|
390
|
-
}
|
391
|
-
}
|
392
|
-
|
393
|
-
|
394
|
-
static void correctkeys (TTree *tree, int n) {
|
395
|
-
if (n == 0) return; /* no correction? */
|
396
|
-
tailcall:
|
397
|
-
switch (tree->tag) {
|
398
|
-
case TOpenCall: case TCall: case TRunTime: case TRule: {
|
399
|
-
if (tree->key > 0)
|
400
|
-
tree->key += n;
|
401
|
-
break;
|
402
|
-
}
|
403
|
-
case TCapture: {
|
404
|
-
if (tree->key > 0 && tree->cap != Carg && tree->cap != Cnum)
|
405
|
-
tree->key += n;
|
406
|
-
break;
|
407
|
-
}
|
408
|
-
default: break;
|
409
|
-
}
|
410
|
-
switch (numsiblings[tree->tag]) {
|
411
|
-
case 1: /* correctkeys(sib1(tree), n); */
|
412
|
-
tree = sib1(tree); goto tailcall;
|
413
|
-
case 2:
|
414
|
-
correctkeys(sib1(tree), n);
|
415
|
-
tree = sib2(tree); goto tailcall; /* correctkeys(sib2(tree), n); */
|
416
|
-
default: assert(numsiblings[tree->tag] == 0); break;
|
417
|
-
}
|
418
|
-
}
|
419
|
-
|
420
|
-
|
421
|
-
/*
|
422
|
-
** copy 'ktable' of element 'idx' to new tree (on top of stack)
|
423
|
-
*/
|
424
|
-
static void copyktable (lua_State *L, int idx) {
|
425
|
-
lua_getfenv(L, idx);
|
426
|
-
lua_setfenv(L, -2);
|
427
|
-
}
|
428
|
-
|
429
|
-
|
430
|
-
/*
|
431
|
-
** merge 'ktable' from rule at stack index 'idx' into 'ktable'
|
432
|
-
** from tree at the top of the stack, and correct corresponding
|
433
|
-
** tree.
|
434
|
-
*/
|
435
|
-
static void mergektable (lua_State *L, int idx, TTree *rule) {
|
436
|
-
int n;
|
437
|
-
lua_getfenv(L, -1); /* get ktables */
|
438
|
-
lua_getfenv(L, idx);
|
439
|
-
n = concattable(L, -1, -2);
|
440
|
-
lua_pop(L, 2); /* remove both ktables */
|
441
|
-
correctkeys(rule, n);
|
442
|
-
}
|
443
|
-
|
444
|
-
|
445
486
|
/*
|
446
487
|
** create a new tree, whith a new root and one sibling.
|
447
488
|
** Sibling must be on the Lua stack, at index 1.
|
@@ -470,7 +511,7 @@ static TTree *newroot2sib (lua_State *L, int tag) {
|
|
470
511
|
tree->u.ps = 1 + s1;
|
471
512
|
memcpy(sib1(tree), tree1, s1 * sizeof(TTree));
|
472
513
|
memcpy(sib2(tree), tree2, s2 * sizeof(TTree));
|
473
|
-
|
514
|
+
joinktables(L, 1, sib2(tree), 2);
|
474
515
|
return tree;
|
475
516
|
}
|
476
517
|
|
@@ -599,7 +640,7 @@ static int lp_sub (lua_State *L) {
|
|
599
640
|
sib1(tree)->tag = TNot; /* ...not... */
|
600
641
|
memcpy(sib1(sib1(tree)), t2, s2 * sizeof(TTree)); /* ...t2 */
|
601
642
|
memcpy(sib2(tree), t1, s1 * sizeof(TTree)); /* ... and t1 */
|
602
|
-
|
643
|
+
joinktables(L, 1, sib1(tree), 2);
|
603
644
|
}
|
604
645
|
return 1;
|
605
646
|
}
|
@@ -640,7 +681,7 @@ static int lp_behind (lua_State *L) {
|
|
640
681
|
TTree *tree;
|
641
682
|
TTree *tree1 = getpatt(L, 1, NULL);
|
642
683
|
int n = fixedlen(tree1);
|
643
|
-
luaL_argcheck(L, n
|
684
|
+
luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length");
|
644
685
|
luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures");
|
645
686
|
luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind");
|
646
687
|
tree = newroot1sib(L, TBehind);
|
@@ -655,7 +696,7 @@ static int lp_behind (lua_State *L) {
|
|
655
696
|
static int lp_V (lua_State *L) {
|
656
697
|
TTree *tree = newleaf(L, TOpenCall);
|
657
698
|
luaL_argcheck(L, !lua_isnoneornil(L, 1), 1, "non-nil value expected");
|
658
|
-
tree->key =
|
699
|
+
tree->key = addtonewktable(L, 0, 1);
|
659
700
|
return 1;
|
660
701
|
}
|
661
702
|
|
@@ -668,7 +709,7 @@ static int lp_V (lua_State *L) {
|
|
668
709
|
static int capture_aux (lua_State *L, int cap, int labelidx) {
|
669
710
|
TTree *tree = newroot1sib(L, TCapture);
|
670
711
|
tree->cap = cap;
|
671
|
-
tree->key =
|
712
|
+
tree->key = (labelidx == 0) ? 0 : addtonewktable(L, 1, labelidx);
|
672
713
|
return 1;
|
673
714
|
}
|
674
715
|
|
@@ -676,10 +717,9 @@ static int capture_aux (lua_State *L, int cap, int labelidx) {
|
|
676
717
|
/*
|
677
718
|
** Fill a tree with an empty capture, using an empty (TTrue) sibling.
|
678
719
|
*/
|
679
|
-
static TTree *auxemptycap (
|
720
|
+
static TTree *auxemptycap (TTree *tree, int cap) {
|
680
721
|
tree->tag = TCapture;
|
681
722
|
tree->cap = cap;
|
682
|
-
tree->key = addtoktable(L, idx);
|
683
723
|
sib1(tree)->tag = TTrue;
|
684
724
|
return tree;
|
685
725
|
}
|
@@ -688,8 +728,18 @@ static TTree *auxemptycap (lua_State *L, TTree *tree, int cap, int idx) {
|
|
688
728
|
/*
|
689
729
|
** Create a tree for an empty capture
|
690
730
|
*/
|
691
|
-
static TTree *newemptycap (lua_State *L, int cap
|
692
|
-
return auxemptycap(
|
731
|
+
static TTree *newemptycap (lua_State *L, int cap) {
|
732
|
+
return auxemptycap(newtree(L, 2), cap);
|
733
|
+
}
|
734
|
+
|
735
|
+
|
736
|
+
/*
|
737
|
+
** Create a tree for an empty capture with an associated Lua value
|
738
|
+
*/
|
739
|
+
static TTree *newemptycapkey (lua_State *L, int cap, int idx) {
|
740
|
+
TTree *tree = auxemptycap(newtree(L, 2), cap);
|
741
|
+
tree->key = addtonewktable(L, 0, idx);
|
742
|
+
return tree;
|
693
743
|
}
|
694
744
|
|
695
745
|
|
@@ -728,10 +778,8 @@ static int lp_tablecapture (lua_State *L) {
|
|
728
778
|
static int lp_groupcapture (lua_State *L) {
|
729
779
|
if (lua_isnoneornil(L, 2))
|
730
780
|
return capture_aux(L, Cgroup, 0);
|
731
|
-
else
|
732
|
-
luaL_checkstring(L, 2);
|
781
|
+
else
|
733
782
|
return capture_aux(L, Cgroup, 2);
|
734
|
-
}
|
735
783
|
}
|
736
784
|
|
737
785
|
|
@@ -747,14 +795,14 @@ static int lp_simplecapture (lua_State *L) {
|
|
747
795
|
|
748
796
|
|
749
797
|
static int lp_poscapture (lua_State *L) {
|
750
|
-
newemptycap(L, Cposition
|
798
|
+
newemptycap(L, Cposition);
|
751
799
|
return 1;
|
752
800
|
}
|
753
801
|
|
754
802
|
|
755
803
|
static int lp_argcapture (lua_State *L) {
|
756
804
|
int n = (int)luaL_checkinteger(L, 1);
|
757
|
-
TTree *tree = newemptycap(L, Carg
|
805
|
+
TTree *tree = newemptycap(L, Carg);
|
758
806
|
tree->key = n;
|
759
807
|
luaL_argcheck(L, 0 < n && n <= SHRT_MAX, 1, "invalid argument index");
|
760
808
|
return 1;
|
@@ -762,8 +810,8 @@ static int lp_argcapture (lua_State *L) {
|
|
762
810
|
|
763
811
|
|
764
812
|
static int lp_backref (lua_State *L) {
|
765
|
-
|
766
|
-
|
813
|
+
luaL_checkany(L, 1);
|
814
|
+
newemptycapkey(L, Cbackref, 1);
|
767
815
|
return 1;
|
768
816
|
}
|
769
817
|
|
@@ -777,9 +825,10 @@ static int lp_constcapture (lua_State *L) {
|
|
777
825
|
if (n == 0) /* no values? */
|
778
826
|
newleaf(L, TTrue); /* no capture */
|
779
827
|
else if (n == 1)
|
780
|
-
|
828
|
+
newemptycapkey(L, Cconst, 1); /* single constant capture */
|
781
829
|
else { /* create a group capture with all values */
|
782
830
|
TTree *tree = newtree(L, 1 + 3 * (n - 1) + 2);
|
831
|
+
newktable(L, n); /* create a 'ktable' for new tree */
|
783
832
|
tree->tag = TCapture;
|
784
833
|
tree->cap = Cgroup;
|
785
834
|
tree->key = 0;
|
@@ -787,10 +836,12 @@ static int lp_constcapture (lua_State *L) {
|
|
787
836
|
for (i = 1; i <= n - 1; i++) {
|
788
837
|
tree->tag = TSeq;
|
789
838
|
tree->u.ps = 3; /* skip TCapture and its sibling */
|
790
|
-
auxemptycap(
|
839
|
+
auxemptycap(sib1(tree), Cconst);
|
840
|
+
sib1(tree)->key = addtoktable(L, i);
|
791
841
|
tree = sib2(tree);
|
792
842
|
}
|
793
|
-
auxemptycap(
|
843
|
+
auxemptycap(tree, Cconst);
|
844
|
+
tree->key = addtoktable(L, i);
|
794
845
|
}
|
795
846
|
return 1;
|
796
847
|
}
|
@@ -800,7 +851,7 @@ static int lp_matchtime (lua_State *L) {
|
|
800
851
|
TTree *tree;
|
801
852
|
luaL_checktype(L, 2, LUA_TFUNCTION);
|
802
853
|
tree = newroot1sib(L, TRunTime);
|
803
|
-
tree->key =
|
854
|
+
tree->key = addtonewktable(L, 1, 2);
|
804
855
|
return 1;
|
805
856
|
}
|
806
857
|
|
@@ -857,7 +908,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) {
|
|
857
908
|
lua_pushnil(L); /* prepare to traverse grammar table */
|
858
909
|
while (lua_next(L, arg) != 0) {
|
859
910
|
if (lua_tonumber(L, -2) == 1 ||
|
860
|
-
|
911
|
+
lp_equal(L, -2, postab + 1)) { /* initial rule? */
|
861
912
|
lua_pop(L, 1); /* remove value (keep key for lua_next) */
|
862
913
|
continue;
|
863
914
|
}
|
@@ -884,7 +935,7 @@ static void buildgrammar (lua_State *L, TTree *grammar, int frule, int n) {
|
|
884
935
|
int rulesize;
|
885
936
|
TTree *rn = gettree(L, ridx, &rulesize);
|
886
937
|
nd->tag = TRule;
|
887
|
-
nd->key = 0;
|
938
|
+
nd->key = 0; /* will be fixed when rule is used */
|
888
939
|
nd->cap = i; /* rule number */
|
889
940
|
nd->u.ps = rulesize + 1; /* point to next rule */
|
890
941
|
memcpy(sib1(nd), rn, rulesize * sizeof(TTree)); /* copy rule */
|
@@ -918,6 +969,11 @@ static int checkloops (TTree *tree) {
|
|
918
969
|
}
|
919
970
|
|
920
971
|
|
972
|
+
/*
|
973
|
+
** Give appropriate error message for 'verifyrule'. If a rule appears
|
974
|
+
** twice in 'passed', there is path from it back to itself without
|
975
|
+
** advancing the subject.
|
976
|
+
*/
|
921
977
|
static int verifyerror (lua_State *L, int *passed, int npassed) {
|
922
978
|
int i, j;
|
923
979
|
for (i = npassed - 1; i >= 0; i--) { /* search for a repetition */
|
@@ -934,36 +990,42 @@ static int verifyerror (lua_State *L, int *passed, int npassed) {
|
|
934
990
|
|
935
991
|
/*
|
936
992
|
** Check whether a rule can be left recursive; raise an error in that
|
937
|
-
** case; otherwise return 1 iff pattern is nullable.
|
938
|
-
**
|
993
|
+
** case; otherwise return 1 iff pattern is nullable.
|
994
|
+
** The return value is used to check sequences, where the second pattern
|
995
|
+
** is only relevant if the first is nullable.
|
996
|
+
** Parameter 'nb' works as an accumulator, to allow tail calls in
|
997
|
+
** choices. ('nb' true makes function returns true.)
|
998
|
+
** Parameter 'passed' is a list of already visited rules, 'npassed'
|
999
|
+
** counts the elements in 'passed'.
|
1000
|
+
** Assume ktable at the top of the stack.
|
939
1001
|
*/
|
940
1002
|
static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed,
|
941
|
-
int
|
1003
|
+
int nb) {
|
942
1004
|
tailcall:
|
943
1005
|
switch (tree->tag) {
|
944
1006
|
case TChar: case TSet: case TAny:
|
945
1007
|
case TFalse:
|
946
|
-
return
|
1008
|
+
return nb; /* cannot pass from here */
|
947
1009
|
case TTrue:
|
948
1010
|
case TBehind: /* look-behind cannot have calls */
|
949
1011
|
return 1;
|
950
1012
|
case TNot: case TAnd: case TRep:
|
951
1013
|
/* return verifyrule(L, sib1(tree), passed, npassed, 1); */
|
952
|
-
tree = sib1(tree);
|
1014
|
+
tree = sib1(tree); nb = 1; goto tailcall;
|
953
1015
|
case TCapture: case TRunTime:
|
954
|
-
/* return verifyrule(L, sib1(tree), passed, npassed); */
|
1016
|
+
/* return verifyrule(L, sib1(tree), passed, npassed, nb); */
|
955
1017
|
tree = sib1(tree); goto tailcall;
|
956
1018
|
case TCall:
|
957
|
-
/* return verifyrule(L, sib2(tree), passed, npassed); */
|
1019
|
+
/* return verifyrule(L, sib2(tree), passed, npassed, nb); */
|
958
1020
|
tree = sib2(tree); goto tailcall;
|
959
|
-
case TSeq: /* only check 2nd child if first is
|
1021
|
+
case TSeq: /* only check 2nd child if first is nb */
|
960
1022
|
if (!verifyrule(L, sib1(tree), passed, npassed, 0))
|
961
|
-
return
|
962
|
-
/* else return verifyrule(L, sib2(tree), passed, npassed); */
|
1023
|
+
return nb;
|
1024
|
+
/* else return verifyrule(L, sib2(tree), passed, npassed, nb); */
|
963
1025
|
tree = sib2(tree); goto tailcall;
|
964
1026
|
case TChoice: /* must check both children */
|
965
|
-
|
966
|
-
/* return verifyrule(L, sib2(tree), passed, npassed,
|
1027
|
+
nb = verifyrule(L, sib1(tree), passed, npassed, nb);
|
1028
|
+
/* return verifyrule(L, sib2(tree), passed, npassed, nb); */
|
967
1029
|
tree = sib2(tree); goto tailcall;
|
968
1030
|
case TRule:
|
969
1031
|
if (npassed >= MAXRULES)
|
@@ -1006,7 +1068,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) {
|
|
1006
1068
|
*/
|
1007
1069
|
static void initialrulename (lua_State *L, TTree *grammar, int frule) {
|
1008
1070
|
if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */
|
1009
|
-
int n =
|
1071
|
+
int n = lua_rawlen(L, -1) + 1; /* index for name */
|
1010
1072
|
lua_pushvalue(L, frule); /* rule's name */
|
1011
1073
|
lua_rawseti(L, -2, n); /* ktable was on the top of the stack */
|
1012
1074
|
sib1(grammar)->key = n;
|
@@ -1022,9 +1084,9 @@ static TTree *newgrammar (lua_State *L, int arg) {
|
|
1022
1084
|
luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules");
|
1023
1085
|
g->tag = TGrammar; g->u.n = n;
|
1024
1086
|
lua_newtable(L); /* create 'ktable' */
|
1025
|
-
|
1087
|
+
lua_setuservalue(L, -2);
|
1026
1088
|
buildgrammar(L, g, frule, n);
|
1027
|
-
|
1089
|
+
lua_getuservalue(L, -1); /* get 'ktable' for new tree */
|
1028
1090
|
finalfix(L, frule - 1, g, sib1(g));
|
1029
1091
|
initialrulename(L, g, frule);
|
1030
1092
|
verifygrammar(L, g);
|
@@ -1037,8 +1099,8 @@ static TTree *newgrammar (lua_State *L, int arg) {
|
|
1037
1099
|
/* }====================================================== */
|
1038
1100
|
|
1039
1101
|
|
1040
|
-
static
|
1041
|
-
|
1102
|
+
static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) {
|
1103
|
+
lua_getuservalue(L, idx); /* push 'ktable' (may be used by 'finalfix') */
|
1042
1104
|
finalfix(L, 0, NULL, p->tree);
|
1043
1105
|
lua_pop(L, 1); /* remove 'ktable' */
|
1044
1106
|
return compile(L, p);
|
@@ -1049,7 +1111,7 @@ static int lp_printtree (lua_State *L) {
|
|
1049
1111
|
TTree *tree = getpatt(L, 1, NULL);
|
1050
1112
|
int c = lua_toboolean(L, 2);
|
1051
1113
|
if (c) {
|
1052
|
-
|
1114
|
+
lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */
|
1053
1115
|
finalfix(L, 0, NULL, tree);
|
1054
1116
|
lua_pop(L, 1); /* remove 'ktable' */
|
1055
1117
|
}
|
@@ -1096,14 +1158,14 @@ static int lp_match (lua_State *L) {
|
|
1096
1158
|
const char *r;
|
1097
1159
|
size_t l;
|
1098
1160
|
Pattern *p = (getpatt(L, 1, NULL), getpattern(L, 1));
|
1099
|
-
|
1161
|
+
Instruction *code = (p->code != NULL) ? p->code : prepcompile(L, p, 1);
|
1100
1162
|
const char *s = luaL_checklstring(L, SUBJIDX, &l);
|
1101
1163
|
size_t i = initposition(L, l);
|
1102
1164
|
int ptop = lua_gettop(L);
|
1103
1165
|
lua_pushnil(L); /* initialize subscache */
|
1104
1166
|
lua_pushlightuserdata(L, capture); /* initialize caplistidx */
|
1105
|
-
|
1106
|
-
r =
|
1167
|
+
lua_getuservalue(L, 1); /* initialize penvidx */
|
1168
|
+
r = match(L, s, s + i, s + l, code, capture, ptop);
|
1107
1169
|
if (r == NULL) {
|
1108
1170
|
lua_pushnil(L);
|
1109
1171
|
return 1;
|
@@ -1119,8 +1181,12 @@ static int lp_match (lua_State *L) {
|
|
1119
1181
|
** =======================================================
|
1120
1182
|
*/
|
1121
1183
|
|
1184
|
+
/* maximum limit for stack size */
|
1185
|
+
#define MAXLIM (INT_MAX / 100)
|
1186
|
+
|
1122
1187
|
static int lp_setmax (lua_State *L) {
|
1123
|
-
|
1188
|
+
lua_Integer lim = luaL_checkinteger(L, 1);
|
1189
|
+
luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range");
|
1124
1190
|
lua_settop(L, 1);
|
1125
1191
|
lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
|
1126
1192
|
return 0;
|
@@ -1144,8 +1210,7 @@ static int lp_type (lua_State *L) {
|
|
1144
1210
|
|
1145
1211
|
int lp_gc (lua_State *L) {
|
1146
1212
|
Pattern *p = getpattern(L, 1);
|
1147
|
-
|
1148
|
-
realloccode(L, p, 0);
|
1213
|
+
realloccode(L, p, 0); /* delete code block */
|
1149
1214
|
return 0;
|
1150
1215
|
}
|
1151
1216
|
|
@@ -1228,8 +1293,8 @@ int luaopen_lpeg (lua_State *L) {
|
|
1228
1293
|
luaL_newmetatable(L, PATTERN_T);
|
1229
1294
|
lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */
|
1230
1295
|
lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
|
1231
|
-
|
1232
|
-
|
1296
|
+
luaL_setfuncs(L, metareg, 0);
|
1297
|
+
luaL_newlib(L, pattreg);
|
1233
1298
|
lua_pushvalue(L, -1);
|
1234
1299
|
lua_setfield(L, -3, "__index");
|
1235
1300
|
return 1;
|