diff options
Diffstat (limited to 'lpcap.c')
-rw-r--r-- | lpcap.c | 64 |
1 files changed, 41 insertions, 23 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $ | 2 | ** $Id: lpcap.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 | ||
@@ -271,15 +271,15 @@ int finddyncap (Capture *cap, Capture *last) { | |||
271 | 271 | ||
272 | 272 | ||
273 | /* | 273 | /* |
274 | ** Calls a runtime capture. Returns number of captures removed by | 274 | ** Calls a runtime capture. Returns number of captures "removed" by the |
275 | ** the call, including the initial Cgroup. (Captures to be added are | 275 | ** call, that is, those inside the group capture. Captures to be added |
276 | ** on the Lua stack.) | 276 | ** are on the Lua stack. |
277 | */ | 277 | */ |
278 | int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { | 278 | int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { |
279 | int n, id; | 279 | int n, id; |
280 | lua_State *L = cs->L; | 280 | lua_State *L = cs->L; |
281 | int otop = lua_gettop(L); | 281 | int otop = lua_gettop(L); |
282 | Capture *open = findopen(close); | 282 | Capture *open = findopen(close); /* get open group capture */ |
283 | assert(captype(open) == Cgroup); | 283 | assert(captype(open) == Cgroup); |
284 | id = finddyncap(open, close); /* get first dynamic capture argument */ | 284 | id = finddyncap(open, close); /* get first dynamic capture argument */ |
285 | close->kind = Cclose; /* closes the group */ | 285 | close->kind = Cclose; /* closes the group */ |
@@ -299,7 +299,7 @@ int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) { | |||
299 | } | 299 | } |
300 | else | 300 | else |
301 | *rem = 0; /* no dynamic captures removed */ | 301 | *rem = 0; /* no dynamic captures removed */ |
302 | return close - open; /* number of captures of all kinds removed */ | 302 | return close - open - 1; /* number of captures to be removed */ |
303 | } | 303 | } |
304 | 304 | ||
305 | 305 | ||
@@ -441,70 +441,88 @@ static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) { | |||
441 | } | 441 | } |
442 | 442 | ||
443 | 443 | ||
444 | #if !defined(MAXRECLEVEL) | ||
445 | #define MAXRECLEVEL 200 | ||
446 | #endif | ||
447 | |||
448 | |||
444 | /* | 449 | /* |
445 | ** Push all values of the current capture into the stack; returns | 450 | ** Push all values of the current capture into the stack; returns |
446 | ** number of values pushed | 451 | ** number of values pushed |
447 | */ | 452 | */ |
448 | static int pushcapture (CapState *cs) { | 453 | static int pushcapture (CapState *cs) { |
449 | lua_State *L = cs->L; | 454 | lua_State *L = cs->L; |
455 | int res; | ||
450 | luaL_checkstack(L, 4, "too many captures"); | 456 | luaL_checkstack(L, 4, "too many captures"); |
457 | if (cs->reclevel++ > MAXRECLEVEL) | ||
458 | return luaL_error(L, "subcapture nesting too deep"); | ||
451 | switch (captype(cs->cap)) { | 459 | switch (captype(cs->cap)) { |
452 | case Cposition: { | 460 | case Cposition: { |
453 | lua_pushinteger(L, cs->cap->s - cs->s + 1); | 461 | lua_pushinteger(L, cs->cap->s - cs->s + 1); |
454 | cs->cap++; | 462 | cs->cap++; |
455 | return 1; | 463 | res = 1; |
464 | break; | ||
456 | } | 465 | } |
457 | case Cconst: { | 466 | case Cconst: { |
458 | pushluaval(cs); | 467 | pushluaval(cs); |
459 | cs->cap++; | 468 | cs->cap++; |
460 | return 1; | 469 | res = 1; |
470 | break; | ||
461 | } | 471 | } |
462 | case Carg: { | 472 | case Carg: { |
463 | int arg = (cs->cap++)->idx; | 473 | int arg = (cs->cap++)->idx; |
464 | if (arg + FIXEDARGS > cs->ptop) | 474 | if (arg + FIXEDARGS > cs->ptop) |
465 | return luaL_error(L, "reference to absent extra argument #%d", arg); | 475 | return luaL_error(L, "reference to absent extra argument #%d", arg); |
466 | lua_pushvalue(L, arg + FIXEDARGS); | 476 | lua_pushvalue(L, arg + FIXEDARGS); |
467 | return 1; | 477 | res = 1; |
478 | break; | ||
468 | } | 479 | } |
469 | case Csimple: { | 480 | case Csimple: { |
470 | int k = pushnestedvalues(cs, 1); | 481 | int k = pushnestedvalues(cs, 1); |
471 | lua_insert(L, -k); /* make whole match be first result */ | 482 | lua_insert(L, -k); /* make whole match be first result */ |
472 | return k; | 483 | res = k; |
484 | break; | ||
473 | } | 485 | } |
474 | case Cruntime: { | 486 | case Cruntime: { |
475 | lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */ | 487 | lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */ |
476 | return 1; | 488 | res = 1; |
489 | break; | ||
477 | } | 490 | } |
478 | case Cstring: { | 491 | case Cstring: { |
479 | luaL_Buffer b; | 492 | luaL_Buffer b; |
480 | luaL_buffinit(L, &b); | 493 | luaL_buffinit(L, &b); |
481 | stringcap(&b, cs); | 494 | stringcap(&b, cs); |
482 | luaL_pushresult(&b); | 495 | luaL_pushresult(&b); |
483 | return 1; | 496 | res = 1; |
497 | break; | ||
484 | } | 498 | } |
485 | case Csubst: { | 499 | case Csubst: { |
486 | luaL_Buffer b; | 500 | luaL_Buffer b; |
487 | luaL_buffinit(L, &b); | 501 | luaL_buffinit(L, &b); |
488 | substcap(&b, cs); | 502 | substcap(&b, cs); |
489 | luaL_pushresult(&b); | 503 | luaL_pushresult(&b); |
490 | return 1; | 504 | res = 1; |
505 | break; | ||
491 | } | 506 | } |
492 | case Cgroup: { | 507 | case Cgroup: { |
493 | if (cs->cap->idx == 0) /* anonymous group? */ | 508 | if (cs->cap->idx == 0) /* anonymous group? */ |
494 | return pushnestedvalues(cs, 0); /* add all nested values */ | 509 | res = pushnestedvalues(cs, 0); /* add all nested values */ |
495 | else { /* named group: add no values */ | 510 | else { /* named group: add no values */ |
496 | nextcap(cs); /* skip capture */ | 511 | nextcap(cs); /* skip capture */ |
497 | return 0; | 512 | res = 0; |
498 | } | 513 | } |
514 | break; | ||
499 | } | 515 | } |
500 | case Cbackref: return backrefcap(cs); | 516 | case Cbackref: res = backrefcap(cs); break; |
501 | case Ctable: return tablecap(cs); | 517 | case Ctable: res = tablecap(cs); break; |
502 | case Cfunction: return functioncap(cs); | 518 | case Cfunction: res = functioncap(cs); break; |
503 | case Cnum: return numcap(cs); | 519 | case Cnum: res = numcap(cs); break; |
504 | case Cquery: return querycap(cs); | 520 | case Cquery: res = querycap(cs); break; |
505 | case Cfold: return foldcap(cs); | 521 | case Cfold: res = foldcap(cs); break; |
506 | default: assert(0); return 0; | 522 | default: assert(0); res = 0; |
507 | } | 523 | } |
524 | cs->reclevel--; | ||
525 | return res; | ||
508 | } | 526 | } |
509 | 527 | ||
510 | 528 | ||
@@ -521,7 +539,7 @@ int getcaptures (lua_State *L, const char *s, const char *r, int ptop) { | |||
521 | int n = 0; | 539 | int n = 0; |
522 | if (!isclosecap(capture)) { /* is there any capture? */ | 540 | if (!isclosecap(capture)) { /* is there any capture? */ |
523 | CapState cs; | 541 | CapState cs; |
524 | cs.ocap = cs.cap = capture; cs.L = L; | 542 | cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0; |
525 | cs.s = s; cs.valuecached = 0; cs.ptop = ptop; | 543 | cs.s = s; cs.valuecached = 0; cs.ptop = ptop; |
526 | do { /* collect their values */ | 544 | do { /* collect their values */ |
527 | n += pushcapture(&cs); | 545 | n += pushcapture(&cs); |