diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luapeg/lpeg.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luapeg/lpeg.c | 213 |
1 files changed, 112 insertions, 101 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luapeg/lpeg.c b/Build/source/texk/web2c/luatexdir/luapeg/lpeg.c index 12c7ea42d36..30f54522de5 100644 --- a/Build/source/texk/web2c/luatexdir/luapeg/lpeg.c +++ b/Build/source/texk/web2c/luatexdir/luapeg/lpeg.c @@ -1,20 +1,18 @@ - #include "lpeg.h" - /* -** $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) */ -/* #include <ctype.h>*/ -/* #include <limits.h>*/ -/* #include <stdio.h>*/ +/* #include <ctype.h> */ +/* #include <limits.h> */ +/* #include <stdio.h> */ -/* #include "lptypes.h"*/ -/* #include "lpprint.h"*/ -/* #include "lpcode.h"*/ +/* #include "lptypes.h" */ +/* #include "lpprint.h" */ +/* #include "lpcode.h" */ #if defined(LPEG_DEBUG) @@ -56,7 +54,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", @@ -225,10 +223,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); @@ -246,27 +244,28 @@ void printktable (lua_State *L, int idx) { /* }====================================================== */ #endif + /* -** $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) */ -/* #include <limits.h>*/ -/* #include <string.h>*/ +/* #include <limits.h> */ +/* #include <string.h> */ -/* #include "lua.h"*/ -/* #include "lauxlib.h"*/ +/* #include "lua.h" */ +/* #include "lauxlib.h" */ -/* #include "lpcap.h"*/ -/* #include "lptypes.h"*/ -/* #include "lpvm.h"*/ -/* #include "lpprint.h"*/ +/* #include "lpcap.h" */ +/* #include "lptypes.h" */ +/* #include "lpvm.h" */ +/* #include "lpprint.h" */ /* initial size for call/backtrack stack */ #if !defined(INITBACK) -#define INITBACK 100 +#define INITBACK MAXBACK #endif @@ -318,7 +317,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)); @@ -602,18 +601,18 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, /* -** $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) */ -/* #include <limits.h>*/ +/* #include <limits.h> */ -/* #include "lua.h"*/ -/* #include "lauxlib.h"*/ +/* #include "lua.h" */ +/* #include "lauxlib.h" */ -/* #include "lptypes.h"*/ -/* #include "lpcode.h"*/ +/* #include "lptypes.h" */ +/* #include "lpcode.h" */ /* signals a "no-instruction */ @@ -1034,11 +1033,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); @@ -1241,13 +1240,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, @@ -1274,7 +1273,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); @@ -1362,7 +1361,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); @@ -1587,16 +1586,18 @@ Instruction *compile (lua_State *L, Pattern *p) { /* }====================================================== */ + + /* -** $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) */ -/* #include "lua.h"*/ -/* #include "lauxlib.h"*/ +/* #include "lua.h" */ +/* #include "lauxlib.h" */ -/* #include "lpcap.h"*/ -/* #include "lptypes.h"*/ +/* #include "lpcap.h" */ +/* #include "lptypes.h" */ #define captype(cap) ((cap)->kind) @@ -1715,7 +1716,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; } @@ -2125,23 +2126,23 @@ int getcaptures (lua_State *L, const char *s, const char *r, int ptop) { /* -** $Id: lptree.c,v 1.15 2015/03/04 17:23:00 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) */ -/* #include <ctype.h>*/ -/* #include <limits.h>*/ -/* #include <string.h>*/ +/* #include <ctype.h> */ +/* #include <limits.h> */ +/* #include <string.h> */ -/* #include "lua.h"*/ -/* #include "lauxlib.h"*/ +/* #include "lua.h" */ +/* #include "lauxlib.h" */ -/* #include "lptypes.h"*/ -/* #include "lpcap.h"*/ -/* #include "lpcode.h"*/ -/* #include "lpprint.h"*/ -/* #include "lptree.h"*/ +/* #include "lptypes.h" */ +/* #include "lpcap.h" */ +/* #include "lpcode.h" */ +/* #include "lpprint.h" */ +/* #include "lptree.h" */ /* number of siblings for each tree */ @@ -2272,7 +2273,7 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) { */ static void newktable (lua_State *L, int n) { lua_createtable(L, n, 0); /* create a fresh table */ - lua_setfenv(L, -2); /* set it as 'ktable' for pattern */ + lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */ } @@ -2287,8 +2288,8 @@ static int addtoktable (lua_State *L, int idx) { return 0; else { int n; - lua_getfenv(L, -1); /* get ktable from pattern */ - n = lua_objlen(L, -1); + 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 */ @@ -2307,7 +2308,7 @@ static int addtoktable (lua_State *L, int idx) { */ static int ktablelen (lua_State *L, int idx) { if (!lua_istable(L, idx)) return 0; - else return lua_objlen(L, idx); + else return lua_rawlen(L, idx); } @@ -2370,18 +2371,18 @@ static void correctkeys (TTree *tree, int n) { */ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { int n1, n2; - lua_getfenv(L, p1); /* get ktables */ - lua_getfenv(L, p2); + 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 || lua_equal(L, -2, -1)) { /* 2nd table empty or equal? */ + else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */ lua_pop(L, 1); /* pop 2nd table */ - lua_setfenv(L, -2); /* set 1st ktable into new pattern */ + lua_setuservalue(L, -2); /* set 1st ktable into new pattern */ } else if (n1 == 0) { /* first table is empty? */ - lua_setfenv(L, -3); /* set 2nd table into new pattern */ + lua_setuservalue(L, -3); /* set 2nd table into new pattern */ lua_pop(L, 1); /* pop 1st table */ } else { @@ -2389,7 +2390,7 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { /* 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' environment */ + lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */ lua_pop(L, 2); /* pop other ktables */ correctkeys(t2, n1); /* correction for indices from p2 */ } @@ -2400,8 +2401,8 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { ** 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); + lua_getuservalue(L, idx); + lua_setuservalue(L, -2); } @@ -2412,8 +2413,8 @@ static void copyktable (lua_State *L, int idx) { */ static void mergektable (lua_State *L, int idx, TTree *stree) { int n; - lua_getfenv(L, -1); /* get ktables */ - lua_getfenv(L, idx); + 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); @@ -2464,7 +2465,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; } @@ -2477,12 +2478,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; @@ -2803,7 +2808,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); @@ -2900,10 +2905,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); - } } @@ -2934,7 +2937,7 @@ static int lp_argcapture (lua_State *L) { static int lp_backref (lua_State *L) { - luaL_checkstring(L, 1); + luaL_checkany(L, 1); newemptycapkey(L, Cbackref, 1); return 1; } @@ -3032,7 +3035,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; } @@ -3109,36 +3112,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) @@ -3181,7 +3188,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; @@ -3197,9 +3204,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); @@ -3213,7 +3220,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); @@ -3224,7 +3231,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' */ } @@ -3277,7 +3284,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); @@ -3294,8 +3301,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; @@ -3319,8 +3330,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; } @@ -3403,11 +3413,12 @@ 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; } /* }====================================================== */ + |