diff options
Diffstat (limited to 'lptree.c')
-rw-r--r-- | lptree.c | 104 |
1 files changed, 56 insertions, 48 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lptree.c,v 1.15 2015/03/04 17:23:00 roberto Exp $ | 2 | ** $Id: lptree.c,v 1.21 2015/09/28 17:01:25 roberto Exp $ |
3 | ** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license) | 3 | ** Copyright 2013, Lua.org & PUC-Rio (see 'lpeg.html' for license) |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -147,7 +147,7 @@ static void finalfix (lua_State *L, int postable, TTree *g, TTree *t) { | |||
147 | */ | 147 | */ |
148 | static void newktable (lua_State *L, int n) { | 148 | static void newktable (lua_State *L, int n) { |
149 | lua_createtable(L, n, 0); /* create a fresh table */ | 149 | lua_createtable(L, n, 0); /* create a fresh table */ |
150 | lua_setfenv(L, -2); /* set it as 'ktable' for pattern */ | 150 | lua_setuservalue(L, -2); /* set it as 'ktable' for pattern */ |
151 | } | 151 | } |
152 | 152 | ||
153 | 153 | ||
@@ -162,8 +162,8 @@ static int addtoktable (lua_State *L, int idx) { | |||
162 | return 0; | 162 | return 0; |
163 | else { | 163 | else { |
164 | int n; | 164 | int n; |
165 | lua_getfenv(L, -1); /* get ktable from pattern */ | 165 | lua_getuservalue(L, -1); /* get ktable from pattern */ |
166 | n = lua_objlen(L, -1); | 166 | n = lua_rawlen(L, -1); |
167 | if (n >= USHRT_MAX) | 167 | if (n >= USHRT_MAX) |
168 | luaL_error(L, "too many Lua values in pattern"); | 168 | luaL_error(L, "too many Lua values in pattern"); |
169 | lua_pushvalue(L, idx); /* element to be added */ | 169 | lua_pushvalue(L, idx); /* element to be added */ |
@@ -182,7 +182,7 @@ static int addtoktable (lua_State *L, int idx) { | |||
182 | */ | 182 | */ |
183 | static int ktablelen (lua_State *L, int idx) { | 183 | static int ktablelen (lua_State *L, int idx) { |
184 | if (!lua_istable(L, idx)) return 0; | 184 | if (!lua_istable(L, idx)) return 0; |
185 | else return lua_objlen(L, idx); | 185 | else return lua_rawlen(L, idx); |
186 | } | 186 | } |
187 | 187 | ||
188 | 188 | ||
@@ -245,18 +245,18 @@ static void correctkeys (TTree *tree, int n) { | |||
245 | */ | 245 | */ |
246 | static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { | 246 | static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { |
247 | int n1, n2; | 247 | int n1, n2; |
248 | lua_getfenv(L, p1); /* get ktables */ | 248 | lua_getuservalue(L, p1); /* get ktables */ |
249 | lua_getfenv(L, p2); | 249 | lua_getuservalue(L, p2); |
250 | n1 = ktablelen(L, -2); | 250 | n1 = ktablelen(L, -2); |
251 | n2 = ktablelen(L, -1); | 251 | n2 = ktablelen(L, -1); |
252 | if (n1 == 0 && n2 == 0) /* are both tables empty? */ | 252 | if (n1 == 0 && n2 == 0) /* are both tables empty? */ |
253 | lua_pop(L, 2); /* nothing to be done; pop tables */ | 253 | lua_pop(L, 2); /* nothing to be done; pop tables */ |
254 | else if (n2 == 0 || lua_equal(L, -2, -1)) { /* 2nd table empty or equal? */ | 254 | else if (n2 == 0 || lp_equal(L, -2, -1)) { /* 2nd table empty or equal? */ |
255 | lua_pop(L, 1); /* pop 2nd table */ | 255 | lua_pop(L, 1); /* pop 2nd table */ |
256 | lua_setfenv(L, -2); /* set 1st ktable into new pattern */ | 256 | lua_setuservalue(L, -2); /* set 1st ktable into new pattern */ |
257 | } | 257 | } |
258 | else if (n1 == 0) { /* first table is empty? */ | 258 | else if (n1 == 0) { /* first table is empty? */ |
259 | lua_setfenv(L, -3); /* set 2nd table into new pattern */ | 259 | lua_setuservalue(L, -3); /* set 2nd table into new pattern */ |
260 | lua_pop(L, 1); /* pop 1st table */ | 260 | lua_pop(L, 1); /* pop 1st table */ |
261 | } | 261 | } |
262 | else { | 262 | else { |
@@ -264,7 +264,7 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { | |||
264 | /* stack: new p; ktable p1; ktable p2; new ktable */ | 264 | /* stack: new p; ktable p1; ktable p2; new ktable */ |
265 | concattable(L, -3, -1); /* from p1 into new ktable */ | 265 | concattable(L, -3, -1); /* from p1 into new ktable */ |
266 | concattable(L, -2, -1); /* from p2 into new ktable */ | 266 | concattable(L, -2, -1); /* from p2 into new ktable */ |
267 | lua_setfenv(L, -4); /* new ktable becomes 'p' environment */ | 267 | lua_setuservalue(L, -4); /* new ktable becomes 'p' environment */ |
268 | lua_pop(L, 2); /* pop other ktables */ | 268 | lua_pop(L, 2); /* pop other ktables */ |
269 | correctkeys(t2, n1); /* correction for indices from p2 */ | 269 | correctkeys(t2, n1); /* correction for indices from p2 */ |
270 | } | 270 | } |
@@ -275,8 +275,8 @@ static void joinktables (lua_State *L, int p1, TTree *t2, int p2) { | |||
275 | ** copy 'ktable' of element 'idx' to new tree (on top of stack) | 275 | ** copy 'ktable' of element 'idx' to new tree (on top of stack) |
276 | */ | 276 | */ |
277 | static void copyktable (lua_State *L, int idx) { | 277 | static void copyktable (lua_State *L, int idx) { |
278 | lua_getfenv(L, idx); | 278 | lua_getuservalue(L, idx); |
279 | lua_setfenv(L, -2); | 279 | lua_setuservalue(L, -2); |
280 | } | 280 | } |
281 | 281 | ||
282 | 282 | ||
@@ -287,8 +287,8 @@ static void copyktable (lua_State *L, int idx) { | |||
287 | */ | 287 | */ |
288 | static void mergektable (lua_State *L, int idx, TTree *stree) { | 288 | static void mergektable (lua_State *L, int idx, TTree *stree) { |
289 | int n; | 289 | int n; |
290 | lua_getfenv(L, -1); /* get ktables */ | 290 | lua_getuservalue(L, -1); /* get ktables */ |
291 | lua_getfenv(L, idx); | 291 | lua_getuservalue(L, idx); |
292 | n = concattable(L, -1, -2); | 292 | n = concattable(L, -1, -2); |
293 | lua_pop(L, 2); /* remove both ktables */ | 293 | lua_pop(L, 2); /* remove both ktables */ |
294 | correctkeys(stree, n); | 294 | correctkeys(stree, n); |
@@ -339,7 +339,7 @@ static Pattern *getpattern (lua_State *L, int idx) { | |||
339 | 339 | ||
340 | 340 | ||
341 | static int getsize (lua_State *L, int idx) { | 341 | static int getsize (lua_State *L, int idx) { |
342 | return (lua_objlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1; | 342 | return (lua_rawlen(L, idx) - sizeof(Pattern)) / sizeof(TTree) + 1; |
343 | } | 343 | } |
344 | 344 | ||
345 | 345 | ||
@@ -352,12 +352,16 @@ static TTree *gettree (lua_State *L, int idx, int *len) { | |||
352 | 352 | ||
353 | 353 | ||
354 | /* | 354 | /* |
355 | ** create a pattern | 355 | ** create a pattern. Set its uservalue (the 'ktable') equal to its |
356 | ** metatable. (It could be any empty sequence; the metatable is at | ||
357 | ** hand here, so we use it.) | ||
356 | */ | 358 | */ |
357 | static TTree *newtree (lua_State *L, int len) { | 359 | static TTree *newtree (lua_State *L, int len) { |
358 | size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern); | 360 | size_t size = (len - 1) * sizeof(TTree) + sizeof(Pattern); |
359 | Pattern *p = (Pattern *)lua_newuserdata(L, size); | 361 | Pattern *p = (Pattern *)lua_newuserdata(L, size); |
360 | luaL_getmetatable(L, PATTERN_T); | 362 | luaL_getmetatable(L, PATTERN_T); |
363 | lua_pushvalue(L, -1); | ||
364 | lua_setuservalue(L, -3); | ||
361 | lua_setmetatable(L, -2); | 365 | lua_setmetatable(L, -2); |
362 | p->code = NULL; p->codesize = 0; | 366 | p->code = NULL; p->codesize = 0; |
363 | return p->tree; | 367 | return p->tree; |
@@ -688,7 +692,7 @@ static int lp_behind (lua_State *L) { | |||
688 | TTree *tree; | 692 | TTree *tree; |
689 | TTree *tree1 = getpatt(L, 1, NULL); | 693 | TTree *tree1 = getpatt(L, 1, NULL); |
690 | int n = fixedlen(tree1); | 694 | int n = fixedlen(tree1); |
691 | luaL_argcheck(L, n > 0, 1, "pattern may not have fixed length"); | 695 | luaL_argcheck(L, n >= 0, 1, "pattern may not have fixed length"); |
692 | luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures"); | 696 | luaL_argcheck(L, !hascaptures(tree1), 1, "pattern have captures"); |
693 | luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind"); | 697 | luaL_argcheck(L, n <= MAXBEHIND, 1, "pattern too long to look behind"); |
694 | tree = newroot1sib(L, TBehind); | 698 | tree = newroot1sib(L, TBehind); |
@@ -822,10 +826,8 @@ static int lp_tablecapture (lua_State *L) { | |||
822 | static int lp_groupcapture (lua_State *L) { | 826 | static int lp_groupcapture (lua_State *L) { |
823 | if (lua_isnoneornil(L, 2)) | 827 | if (lua_isnoneornil(L, 2)) |
824 | return capture_aux(L, Cgroup, 0); | 828 | return capture_aux(L, Cgroup, 0); |
825 | else { | 829 | else |
826 | luaL_checkstring(L, 2); | ||
827 | return capture_aux(L, Cgroup, 2); | 830 | return capture_aux(L, Cgroup, 2); |
828 | } | ||
829 | } | 831 | } |
830 | 832 | ||
831 | 833 | ||
@@ -856,7 +858,7 @@ static int lp_argcapture (lua_State *L) { | |||
856 | 858 | ||
857 | 859 | ||
858 | static int lp_backref (lua_State *L) { | 860 | static int lp_backref (lua_State *L) { |
859 | luaL_checkstring(L, 1); | 861 | luaL_checkany(L, 1); |
860 | newemptycapkey(L, Cbackref, 1); | 862 | newemptycapkey(L, Cbackref, 1); |
861 | return 1; | 863 | return 1; |
862 | } | 864 | } |
@@ -954,7 +956,7 @@ static int collectrules (lua_State *L, int arg, int *totalsize) { | |||
954 | lua_pushnil(L); /* prepare to traverse grammar table */ | 956 | lua_pushnil(L); /* prepare to traverse grammar table */ |
955 | while (lua_next(L, arg) != 0) { | 957 | while (lua_next(L, arg) != 0) { |
956 | if (lua_tonumber(L, -2) == 1 || | 958 | if (lua_tonumber(L, -2) == 1 || |
957 | lua_equal(L, -2, postab + 1)) { /* initial rule? */ | 959 | lp_equal(L, -2, postab + 1)) { /* initial rule? */ |
958 | lua_pop(L, 1); /* remove value (keep key for lua_next) */ | 960 | lua_pop(L, 1); /* remove value (keep key for lua_next) */ |
959 | continue; | 961 | continue; |
960 | } | 962 | } |
@@ -1031,36 +1033,40 @@ static int verifyerror (lua_State *L, int *passed, int npassed) { | |||
1031 | 1033 | ||
1032 | /* | 1034 | /* |
1033 | ** Check whether a rule can be left recursive; raise an error in that | 1035 | ** Check whether a rule can be left recursive; raise an error in that |
1034 | ** case; otherwise return 1 iff pattern is nullable. Assume ktable at | 1036 | ** case; otherwise return 1 iff pattern is nullable. |
1035 | ** the top of the stack. | 1037 | ** The return value is used to check sequences, where the second pattern |
1038 | ** is only relevant if the first is nullable. | ||
1039 | ** Parameter 'nb' works as an accumulator, to allow tail calls in | ||
1040 | ** choices. ('nb' true makes function returns true.) | ||
1041 | ** Assume ktable at the top of the stack. | ||
1036 | */ | 1042 | */ |
1037 | static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, | 1043 | static int verifyrule (lua_State *L, TTree *tree, int *passed, int npassed, |
1038 | int nullable) { | 1044 | int nb) { |
1039 | tailcall: | 1045 | tailcall: |
1040 | switch (tree->tag) { | 1046 | switch (tree->tag) { |
1041 | case TChar: case TSet: case TAny: | 1047 | case TChar: case TSet: case TAny: |
1042 | case TFalse: case TThrow: /* labeled failure */ | 1048 | case TFalse: case TThrow: /* labeled failure */ |
1043 | return nullable; /* cannot pass from here */ | 1049 | return nb; /* cannot pass from here */ |
1044 | case TTrue: | 1050 | case TTrue: |
1045 | case TBehind: /* look-behind cannot have calls */ | 1051 | case TBehind: /* look-behind cannot have calls */ |
1046 | return 1; | 1052 | return 1; |
1047 | case TNot: case TAnd: case TRep: | 1053 | case TNot: case TAnd: case TRep: |
1048 | /* return verifyrule(L, sib1(tree), passed, npassed, 1); */ | 1054 | /* return verifyrule(L, sib1(tree), passed, npassed, 1); */ |
1049 | tree = sib1(tree); nullable = 1; goto tailcall; | 1055 | tree = sib1(tree); nb = 1; goto tailcall; |
1050 | case TCapture: case TRunTime: | 1056 | case TCapture: case TRunTime: |
1051 | /* return verifyrule(L, sib1(tree), passed, npassed); */ | 1057 | /* return verifyrule(L, sib1(tree), passed, npassed, nb); */ |
1052 | tree = sib1(tree); goto tailcall; | 1058 | tree = sib1(tree); goto tailcall; |
1053 | case TCall: | 1059 | case TCall: |
1054 | /* return verifyrule(L, sib2(tree), passed, npassed); */ | 1060 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
1055 | tree = sib2(tree); goto tailcall; | 1061 | tree = sib2(tree); goto tailcall; |
1056 | case TSeq: /* only check 2nd child if first is nullable */ | 1062 | case TSeq: /* only check 2nd child if first is nb */ |
1057 | if (!verifyrule(L, sib1(tree), passed, npassed, 0)) | 1063 | if (!verifyrule(L, sib1(tree), passed, npassed, 0)) |
1058 | return nullable; | 1064 | return nb; |
1059 | /* else return verifyrule(L, sib2(tree), passed, npassed); */ | 1065 | /* else return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
1060 | tree = sib2(tree); goto tailcall; | 1066 | tree = sib2(tree); goto tailcall; |
1061 | case TChoice: case TLabChoice: /* must check both children */ /* labeled failure */ | 1067 | case TChoice: case TLabChoice: /* must check both children */ /* labeled failure */ |
1062 | nullable = verifyrule(L, sib1(tree), passed, npassed, nullable); | 1068 | nb = verifyrule(L, sib1(tree), passed, npassed, nb); |
1063 | /* return verifyrule(L, sib2(tree), passed, npassed, nullable); */ | 1069 | /* return verifyrule(L, sib2(tree), passed, npassed, nb); */ |
1064 | tree = sib2(tree); goto tailcall; | 1070 | tree = sib2(tree); goto tailcall; |
1065 | case TRule: | 1071 | case TRule: |
1066 | if (npassed >= MAXRULES) | 1072 | if (npassed >= MAXRULES) |
@@ -1103,7 +1109,7 @@ static void verifygrammar (lua_State *L, TTree *grammar) { | |||
1103 | */ | 1109 | */ |
1104 | static void initialrulename (lua_State *L, TTree *grammar, int frule) { | 1110 | static void initialrulename (lua_State *L, TTree *grammar, int frule) { |
1105 | if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */ | 1111 | if (sib1(grammar)->key == 0) { /* initial rule is not referenced? */ |
1106 | int n = lua_objlen(L, -1) + 1; /* index for name */ | 1112 | int n = lua_rawlen(L, -1) + 1; /* index for name */ |
1107 | lua_pushvalue(L, frule); /* rule's name */ | 1113 | lua_pushvalue(L, frule); /* rule's name */ |
1108 | lua_rawseti(L, -2, n); /* ktable was on the top of the stack */ | 1114 | lua_rawseti(L, -2, n); /* ktable was on the top of the stack */ |
1109 | sib1(grammar)->key = n; | 1115 | sib1(grammar)->key = n; |
@@ -1119,9 +1125,9 @@ static TTree *newgrammar (lua_State *L, int arg) { | |||
1119 | luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules"); | 1125 | luaL_argcheck(L, n <= MAXRULES, arg, "grammar has too many rules"); |
1120 | g->tag = TGrammar; g->u.n = n; | 1126 | g->tag = TGrammar; g->u.n = n; |
1121 | lua_newtable(L); /* create 'ktable' */ | 1127 | lua_newtable(L); /* create 'ktable' */ |
1122 | lua_setfenv(L, -2); | 1128 | lua_setuservalue(L, -2); |
1123 | buildgrammar(L, g, frule, n); | 1129 | buildgrammar(L, g, frule, n); |
1124 | lua_getfenv(L, -1); /* get 'ktable' for new tree */ | 1130 | lua_getuservalue(L, -1); /* get 'ktable' for new tree */ |
1125 | finalfix(L, frule - 1, g, sib1(g)); | 1131 | finalfix(L, frule - 1, g, sib1(g)); |
1126 | initialrulename(L, g, frule); | 1132 | initialrulename(L, g, frule); |
1127 | verifygrammar(L, g); | 1133 | verifygrammar(L, g); |
@@ -1135,7 +1141,7 @@ static TTree *newgrammar (lua_State *L, int arg) { | |||
1135 | 1141 | ||
1136 | 1142 | ||
1137 | static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) { | 1143 | static Instruction *prepcompile (lua_State *L, Pattern *p, int idx) { |
1138 | lua_getfenv(L, idx); /* push 'ktable' (may be used by 'finalfix') */ | 1144 | lua_getuservalue(L, idx); /* push 'ktable' (may be used by 'finalfix') */ |
1139 | finalfix(L, 0, NULL, p->tree); | 1145 | finalfix(L, 0, NULL, p->tree); |
1140 | lua_pop(L, 1); /* remove 'ktable' */ | 1146 | lua_pop(L, 1); /* remove 'ktable' */ |
1141 | return compile(L, p); | 1147 | return compile(L, p); |
@@ -1146,7 +1152,7 @@ static int lp_printtree (lua_State *L) { | |||
1146 | TTree *tree = getpatt(L, 1, NULL); | 1152 | TTree *tree = getpatt(L, 1, NULL); |
1147 | int c = lua_toboolean(L, 2); | 1153 | int c = lua_toboolean(L, 2); |
1148 | if (c) { | 1154 | if (c) { |
1149 | lua_getfenv(L, 1); /* push 'ktable' (may be used by 'finalfix') */ | 1155 | lua_getuservalue(L, 1); /* push 'ktable' (may be used by 'finalfix') */ |
1150 | finalfix(L, 0, NULL, tree); | 1156 | finalfix(L, 0, NULL, tree); |
1151 | lua_pop(L, 1); /* remove 'ktable' */ | 1157 | lua_pop(L, 1); /* remove 'ktable' */ |
1152 | } | 1158 | } |
@@ -1201,9 +1207,8 @@ static int lp_match (lua_State *L) { | |||
1201 | const char *sfail = NULL; /* labeled failure */ | 1207 | const char *sfail = NULL; /* labeled failure */ |
1202 | lua_pushnil(L); /* initialize subscache */ | 1208 | lua_pushnil(L); /* initialize subscache */ |
1203 | lua_pushlightuserdata(L, capture); /* initialize caplistidx */ | 1209 | lua_pushlightuserdata(L, capture); /* initialize caplistidx */ |
1204 | lua_getfenv(L, 1); /* initialize penvidx */ | 1210 | lua_getuservalue(L, 1); /* initialize penvidx */ |
1205 | r = match(L, s, s + i, s + l, code, capture, ptop, &labelf, &sfail); /* labeled failure */ | 1211 | r = match(L, s, s + i, s + l, code, capture, ptop, &labelf, &sfail); /* labeled failure */ |
1206 | /*printf("sfail = %s\n", sfail);*/ | ||
1207 | if (r == NULL) { /* labeled failure begin */ | 1212 | if (r == NULL) { /* labeled failure begin */ |
1208 | long long int j = 0; | 1213 | long long int j = 0; |
1209 | int n = 1; | 1214 | int n = 1; |
@@ -1230,8 +1235,12 @@ static int lp_match (lua_State *L) { | |||
1230 | ** ======================================================= | 1235 | ** ======================================================= |
1231 | */ | 1236 | */ |
1232 | 1237 | ||
1238 | /* maximum limit for stack size */ | ||
1239 | #define MAXLIM (INT_MAX / 100) | ||
1240 | |||
1233 | static int lp_setmax (lua_State *L) { | 1241 | static int lp_setmax (lua_State *L) { |
1234 | luaL_optinteger(L, 1, -1); | 1242 | lua_Integer lim = luaL_checkinteger(L, 1); |
1243 | luaL_argcheck(L, 0 < lim && lim <= MAXLIM, 1, "out of range"); | ||
1235 | lua_settop(L, 1); | 1244 | lua_settop(L, 1); |
1236 | lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); | 1245 | lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); |
1237 | return 0; | 1246 | return 0; |
@@ -1255,8 +1264,7 @@ static int lp_type (lua_State *L) { | |||
1255 | 1264 | ||
1256 | int lp_gc (lua_State *L) { | 1265 | int lp_gc (lua_State *L) { |
1257 | Pattern *p = getpattern(L, 1); | 1266 | Pattern *p = getpattern(L, 1); |
1258 | if (p->codesize > 0) | 1267 | realloccode(L, p, 0); /* delete code block */ |
1259 | realloccode(L, p, 0); | ||
1260 | return 0; | 1268 | return 0; |
1261 | } | 1269 | } |
1262 | 1270 | ||
@@ -1336,13 +1344,13 @@ static struct luaL_Reg metareg[] = { | |||
1336 | }; | 1344 | }; |
1337 | 1345 | ||
1338 | 1346 | ||
1339 | int luaopen_lpeglabel (lua_State *L); /* labeld failure */ | 1347 | int luaopen_lpeglabel (lua_State *L); /* labeled failure */ |
1340 | int luaopen_lpeglabel (lua_State *L) { /* labeled failure */ | 1348 | int luaopen_lpeglabel (lua_State *L) { /* labeled failure */ |
1341 | luaL_newmetatable(L, PATTERN_T); | 1349 | luaL_newmetatable(L, PATTERN_T); |
1342 | lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */ | 1350 | lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */ |
1343 | lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); | 1351 | lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX); |
1344 | luaL_register(L, NULL, metareg); | 1352 | luaL_setfuncs(L, metareg, 0); |
1345 | luaL_register(L, "lpeglabel", pattreg); /* labeled failure */ | 1353 | luaL_newlib(L, pattreg); |
1346 | lua_pushvalue(L, -1); | 1354 | lua_pushvalue(L, -1); |
1347 | lua_setfield(L, -3, "__index"); | 1355 | lua_setfield(L, -3, "__index"); |
1348 | return 1; | 1356 | return 1; |