upgrade lpeg to 1.1.0 (#1766)

* upgrade lpeg to 1.1.0

* fix lpeg compiler error
This commit is contained in:
Jin Xiao
2023-06-27 16:28:21 +08:00
committed by GitHub
parent 2f9d0c805a
commit 69420bdfde
21 changed files with 1388 additions and 735 deletions

View File

@@ -1,7 +1,3 @@
/*
** $Id: lpvm.c $
** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
*/
#include <limits.h>
#include <string.h>
@@ -24,7 +20,46 @@
#define getoffset(p) (((p) + 1)->offset)
static const Instruction giveup = {{IGiveup, 0, 0}};
static const Instruction giveup = {{IGiveup, 0, {0}}};
int charinset (const Instruction *i, const byte *buff, uint c) {
c -= i->i.aux2.set.offset;
if (c >= ((uint)i->i.aux2.set.size /* size in instructions... */
* (uint)sizeof(Instruction) /* in bytes... */
* 8u)) /* in bits */
return i->i.aux1; /* out of range; return default value */
return testchar(buff, c);
}
/*
** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
*/
static const char *utf8_decode (const char *o, int *val) {
static const uint limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFFu};
const unsigned char *s = (const unsigned char *)o;
uint c = s[0]; /* first byte */
uint res = 0; /* final result */
if (c < 0x80) /* ascii? */
res = c;
else {
int count = 0; /* to count number of continuation bytes */
while (c & 0x40) { /* still have continuation bytes? */
int cc = s[++count]; /* read next byte */
if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
return NULL; /* invalid byte sequence */
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
c <<= 1; /* to test next bit */
}
res |= (c & 0x7F) << (count * 5); /* add first byte */
if (count > 3 || res > 0x10FFFFu || res <= limits[count])
return NULL; /* invalid byte sequence */
s += count; /* skip continuation bytes read */
}
*val = res;
return (const char *)s + 1; /* +1 to include first byte */
}
/*
@@ -51,16 +86,25 @@ typedef struct Stack {
** array, it is simpler to ensure the array always has at least one free
** slot upfront and check its size later.)
*/
/* new size in number of elements cannot overflow integers, and new
size in bytes cannot overflow size_t. */
#define MAXNEWSIZE \
(((size_t)INT_MAX) <= (~(size_t)0 / sizeof(Capture)) ? \
((size_t)INT_MAX) : (~(size_t)0 / sizeof(Capture)))
static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
int captop, int n, int ptop) {
if (*capsize - captop > n)
return capture; /* no need to grow array */
else { /* must grow */
Capture *newc;
int newsize = captop + n + 1; /* minimum size needed */
if (newsize < INT_MAX/((int)sizeof(Capture) * 2))
newsize *= 2; /* twice that size, if not too big */
else if (newsize >= INT_MAX/((int)sizeof(Capture)))
uint newsize = captop + n + 1; /* minimum size needed */
if (newsize < (MAXNEWSIZE / 3) * 2)
newsize += newsize / 2; /* 1.5 that size, if not too big */
else if (newsize < (MAXNEWSIZE / 9) * 8)
newsize += newsize / 8; /* else, try 9/8 that size */
else
luaL_error(L, "too many captures");
newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
memcpy(newc, capture, captop * sizeof(Capture));
@@ -125,7 +169,7 @@ static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
** value, 'n' is the number of values (at least 1). The open group
** capture is already in 'capture', before the place for the new entries.
*/
static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {
static void adddyncaptures (Index_t index, Capture *capture, int n, int fd) {
int i;
assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);
capture[-1].idx = 0; /* make group capture an anonymous group */
@@ -133,11 +177,11 @@ static void adddyncaptures (const char *s, Capture *capture, int n, int fd) {
capture[i].kind = Cruntime;
capture[i].siz = 1; /* mark it as closed */
capture[i].idx = fd + i; /* stack index of capture value */
capture[i].s = s;
capture[i].index = index;
}
capture[n].kind = Cclose; /* close group */
capture[n].siz = 1;
capture[n].s = s;
capture[n].index = index;
}
@@ -154,6 +198,32 @@ static int removedyncap (lua_State *L, Capture *capture,
}
/*
** Find the corresponding 'open' capture before 'cap', when that capture
** can become a full capture. If a full capture c1 is followed by an
** empty capture c2, there is no way to know whether c2 is inside
** c1. So, full captures can enclose only captures that start *before*
** its end.
*/
static Capture *findopen (Capture *cap, Index_t currindex) {
int i;
cap--; /* check last capture */
/* Must it be inside current one, but starts where current one ends? */
if (!isopencap(cap) && cap->index == currindex)
return NULL; /* current one cannot be a full capture */
/* else, look for an 'open' capture */
for (i = 0; i < MAXLOP; i++, cap--) {
if (currindex - cap->index >= UCHAR_MAX)
return NULL; /* capture too long for a full capture */
else if (isopencap(cap)) /* open capture? */
return cap; /* that's the one to be closed */
else if (cap->kind == Cclose)
return NULL; /* a full capture should not nest a non-full one */
}
return NULL; /* not found within allowed search limit */
}
/*
** Opcode interpreter
*/
@@ -181,7 +251,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
case IEnd: {
assert(stack == getstackbase(L, ptop) + 1);
capture[captop].kind = Cclose;
capture[captop].s = NULL;
capture[captop].index = MAXINDT;
return s;
}
case IGiveup: {
@@ -198,47 +268,58 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
else goto fail;
continue;
}
case IUTFR: {
int codepoint;
if (s >= e)
goto fail;
s = utf8_decode (s, &codepoint);
if (s && p[1].offset <= codepoint && codepoint <= utf_to(p))
p += 2;
else
goto fail;
continue;
}
case ITestAny: {
if (s < e) p += 2;
else p += getoffset(p);
continue;
}
case IChar: {
if ((byte)*s == p->i.aux && s < e) { p++; s++; }
if ((byte)*s == p->i.aux1 && s < e) { p++; s++; }
else goto fail;
continue;
}
case ITestChar: {
if ((byte)*s == p->i.aux && s < e) p += 2;
if ((byte)*s == p->i.aux1 && s < e) p += 2;
else p += getoffset(p);
continue;
}
case ISet: {
int c = (byte)*s;
if (testchar((p+1)->buff, c) && s < e)
{ p += CHARSETINSTSIZE; s++; }
uint c = (byte)*s;
if (charinset(p, (p+1)->buff, c) && s < e)
{ p += 1 + p->i.aux2.set.size; s++; }
else goto fail;
continue;
}
case ITestSet: {
int c = (byte)*s;
if (testchar((p + 2)->buff, c) && s < e)
p += 1 + CHARSETINSTSIZE;
uint c = (byte)*s;
if (charinset(p, (p + 2)->buff, c) && s < e)
p += 2 + p->i.aux2.set.size;
else p += getoffset(p);
continue;
}
case IBehind: {
int n = p->i.aux;
int n = p->i.aux1;
if (n > s - o) goto fail;
s -= n; p++;
continue;
}
case ISpan: {
for (; s < e; s++) {
int c = (byte)*s;
if (!testchar((p+1)->buff, c)) break;
uint c = (byte)*s;
if (!charinset(p, (p+1)->buff, c)) break;
}
p += CHARSETINSTSIZE;
p += 1 + p->i.aux2.set.size;
continue;
}
case IJmp: {
@@ -280,6 +361,8 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
case IBackCommit: {
assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
s = (--stack)->s;
if (ndyncap > 0) /* are there matchtime captures? */
ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
captop = stack->caplevel;
p += getoffset(p);
continue;
@@ -287,7 +370,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
case IFailTwice:
assert(stack > getstackbase(L, ptop));
stack--;
/* go through */
/* FALLTHROUGH */
case IFail:
fail: { /* pattern failed: try to backtrack */
do { /* remove pending calls */
@@ -326,38 +409,36 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
luaL_error(L, "too many results in match-time capture");
/* add new captures + close group to 'capture' list */
capture = growcap(L, capture, &capsize, captop, n + 1, ptop);
adddyncaptures(s, capture + captop, n, fr);
adddyncaptures(s - o, capture + captop, n, fr);
captop += n + 1; /* new captures + close group */
}
p++;
continue;
}
case ICloseCapture: {
const char *s1 = s;
Capture *open = findopen(capture + captop, s - o);
assert(captop > 0);
/* if possible, turn capture into a full capture */
if (capture[captop - 1].siz == 0 &&
s1 - capture[captop - 1].s < UCHAR_MAX) {
capture[captop - 1].siz = s1 - capture[captop - 1].s + 1;
if (open) { /* if possible, turn capture into a full capture */
open->siz = (s - o) - open->index + 1;
p++;
continue;
}
else {
else { /* must create a close capture */
capture[captop].siz = 1; /* mark entry as closed */
capture[captop].s = s;
capture[captop].index = s - o;
goto pushcapture;
}
}
case IOpenCapture:
capture[captop].siz = 0; /* mark entry as open */
capture[captop].s = s;
capture[captop].index = s - o;
goto pushcapture;
case IFullCapture:
capture[captop].siz = getoff(p) + 1; /* save capture size */
capture[captop].s = s - getoff(p);
capture[captop].index = s - o - getoff(p);
/* goto pushcapture; */
pushcapture: {
capture[captop].idx = p->i.key;
capture[captop].idx = p->i.aux2.key;
capture[captop].kind = getkind(p);
captop++;
capture = growcap(L, capture, &capsize, captop, 0, ptop);