aboutsummaryrefslogtreecommitdiff
path: root/lpvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpvm.c')
-rw-r--r--lpvm.c88
1 files changed, 49 insertions, 39 deletions
diff --git a/lpvm.c b/lpvm.c
index 0c70766..a791c44 100644
--- a/lpvm.c
+++ b/lpvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lpvm.c,v 1.9 2016/06/03 20:11:18 roberto Exp $ 2** $Id: lpvm.c $
3** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license) 3** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
4*/ 4*/
5 5
@@ -47,18 +47,29 @@ typedef struct Stack {
47 47
48 48
49/* 49/*
50** Make the size of the array of captures 'cap' twice as large as needed 50** Ensures the size of array 'capture' (with size '*capsize' and
51** (which is 'captop'). ('n' is the number of new elements.) 51** 'captop' elements being used) is enough to accomodate 'n' extra
52** elements plus one. (Because several opcodes add stuff to the capture
53** array, it is simpler to ensure the array always has at least one free
54** slot upfront and check its size later.)
52*/ 55*/
53static Capture *doublecap (lua_State *L, Capture *cap, int captop, 56static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
54 int n, int ptop) { 57 int captop, int n, int ptop) {
55 Capture *newc; 58 if (*capsize - captop > n)
56 if (captop >= INT_MAX/((int)sizeof(Capture) * 2)) 59 return capture; /* no need to grow array */
57 luaL_error(L, "too many captures"); 60 else { /* must grow */
58 newc = (Capture *)lua_newuserdata(L, captop * 2 * sizeof(Capture)); 61 Capture *newc;
59 memcpy(newc, cap, (captop - n) * sizeof(Capture)); 62 int newsize = captop + n + 1; /* minimum size needed */
60 lua_replace(L, caplistidx(ptop)); 63 if (newsize < INT_MAX/((int)sizeof(Capture) * 2))
61 return newc; 64 newsize *= 2; /* twice that size, if not too big */
65 else if (newsize >= INT_MAX/((int)sizeof(Capture)))
66 luaL_error(L, "too many captures");
67 newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
68 memcpy(newc, capture, captop * sizeof(Capture));
69 *capsize = newsize;
70 lua_replace(L, caplistidx(ptop));
71 return newc;
72 }
62} 73}
63 74
64 75
@@ -111,24 +122,24 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
111 122
112 123
113/* 124/*
114** Add capture values returned by a dynamic capture to the capture list 125** Add capture values returned by a dynamic capture to the list
115** 'base', nested inside a group capture. 'fd' indexes the first capture 126** 'capture', nested inside a group. 'fd' indexes the first capture
116** value, 'n' is the number of values (at least 1). 127** value, 'n' is the number of values (at least 1). The open group
128** capture is already in 'capture', before the place for the new entries.
117*/ 129*/
118static void adddyncaptures (const char *s, Capture *base, int n, int fd) { 130static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {
119 int i; 131 int i;
120 base[0].kind = Cgroup; /* create group capture */ 132 assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);
121 base[0].siz = 0; 133 capture[-1].idx = 0; /* make group capture an anonymous group */
122 base[0].idx = 0; /* make it an anonymous group */ 134 for (i = 0; i < n; i++) { /* add runtime captures */
123 for (i = 1; i <= n; i++) { /* add runtime captures */ 135 capture[i].kind = Cruntime;
124 base[i].kind = Cruntime; 136 capture[i].siz = 1; /* mark it as closed */
125 base[i].siz = 1; /* mark it as closed */ 137 capture[i].idx = fd + i; /* stack index of capture value */
126 base[i].idx = fd + i - 1; /* stack index of capture value */ 138 capture[i].s = s;
127 base[i].s = s;
128 } 139 }
129 base[i].kind = Cclose; /* close group */ 140 capture[n].kind = Cclose; /* close group */
130 base[i].siz = 1; 141 capture[n].siz = 1;
131 base[i].s = s; 142 capture[n].s = s;
132} 143}
133 144
134 145
@@ -374,7 +385,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
374 CapState cs; 385 CapState cs;
375 int rem, res, n; 386 int rem, res, n;
376 int fr = lua_gettop(L) + 1; /* stack index of first result */ 387 int fr = lua_gettop(L) + 1; /* stack index of first result */
377 cs.s = o; cs.L = L; cs.ocap = capture; cs.ptop = ptop; 388 cs.reclevel = 0; cs.L = L;
389 cs.s = o; cs.ocap = capture; cs.ptop = ptop;
378 n = runtimecap(&cs, capture + captop, s, &rem); /* call function */ 390 n = runtimecap(&cs, capture + captop, s, &rem); /* call function */
379 captop -= n; /* remove nested captures */ 391 captop -= n; /* remove nested captures */
380 ndyncap -= rem; /* update number of dynamic captures */ 392 ndyncap -= rem; /* update number of dynamic captures */
@@ -388,15 +400,15 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
388 s = o + res; /* else update current position */ 400 s = o + res; /* else update current position */
389 n = lua_gettop(L) - fr + 1; /* number of new captures */ 401 n = lua_gettop(L) - fr + 1; /* number of new captures */
390 ndyncap += n; /* update number of dynamic captures */ 402 ndyncap += n; /* update number of dynamic captures */
391 if (n > 0) { /* any new capture? */ 403 if (n == 0) /* no new captures? */
404 captop--; /* remove open group */
405 else { /* new captures; keep original open group */
392 if (fr + n >= SHRT_MAX) 406 if (fr + n >= SHRT_MAX)
393 luaL_error(L, "too many results in match-time capture"); 407 luaL_error(L, "too many results in match-time capture");
394 if ((captop += n + 2) >= capsize) { 408 /* add new captures + close group to 'capture' list */
395 capture = doublecap(L, capture, captop, n + 2, ptop); 409 capture = growcap(L, capture, &capsize, captop, n + 1, ptop);
396 capsize = 2 * captop; 410 adddyncaptures(s, capture + captop, n, fr);
397 } 411 captop += n + 1; /* new captures + close group */
398 /* add new captures to 'capture' list */
399 adddyncaptures(s, capture + captop - n - 2, n, fr);
400 } 412 }
401 p++; 413 p++;
402 continue; 414 continue;
@@ -428,10 +440,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
428 pushcapture: { 440 pushcapture: {
429 capture[captop].idx = p->i.key; 441 capture[captop].idx = p->i.key;
430 capture[captop].kind = getkind(p); 442 capture[captop].kind = getkind(p);
431 if (++captop >= capsize) { 443 captop++;
432 capture = doublecap(L, capture, captop, 0, ptop); 444 capture = growcap(L, capture, &capsize, captop, 0, ptop);
433 capsize = 2 * captop;
434 }
435 p++; 445 p++;
436 continue; 446 continue;
437 } 447 }