diff options
Diffstat (limited to 'lpvm.c')
-rw-r--r-- | lpvm.c | 26 |
1 files changed, 22 insertions, 4 deletions
@@ -164,7 +164,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
164 | const Instruction *p = op; /* current instruction */ | 164 | const Instruction *p = op; /* current instruction */ |
165 | Labelset lsfail; | 165 | Labelset lsfail; |
166 | setlabelfail(&lsfail); | 166 | setlabelfail(&lsfail); |
167 | stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++; | 167 | stack->p = &giveup; stack->s = s; stack->ls = &lsfail; stack->caplevel = 0; stack++; /* labeled failure */ |
168 | lua_pushlightuserdata(L, stackbase); | 168 | lua_pushlightuserdata(L, stackbase); |
169 | for (;;) { | 169 | for (;;) { |
170 | #if defined(DEBUG) | 170 | #if defined(DEBUG) |
@@ -280,17 +280,31 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
280 | p += (CHARSETINSTSIZE - 1) + 2; | 280 | p += (CHARSETINSTSIZE - 1) + 2; |
281 | continue; | 281 | continue; |
282 | } | 282 | } |
283 | case IRecov: { /* labeled failure */ | ||
284 | if (stack == stacklimit) | ||
285 | stack = doublestack(L, &stacklimit, ptop); | ||
286 | stack->p = p + getoffset(p); | ||
287 | stack->s = NULL; | ||
288 | stack->ls = (const Labelset *) ((p + 2)->buff); | ||
289 | stack->caplevel = captop; | ||
290 | stack++; | ||
291 | p += (CHARSETINSTSIZE - 1) + 2; | ||
292 | continue; | ||
293 | } | ||
294 | |||
283 | case ICall: { | 295 | case ICall: { |
284 | if (stack == stacklimit) | 296 | if (stack == stacklimit) |
285 | stack = doublestack(L, &stacklimit, ptop); | 297 | stack = doublestack(L, &stacklimit, ptop); |
286 | stack->s = NULL; | 298 | stack->s = NULL; |
287 | stack->p = p + 2; /* save return address */ | 299 | stack->p = p + 2; /* save return address */ |
300 | stack->ls = NULL; | ||
288 | stack++; | 301 | stack++; |
289 | p += getoffset(p); | 302 | p += getoffset(p); |
290 | continue; | 303 | continue; |
291 | } | 304 | } |
292 | case ICommit: { | 305 | case ICommit: { |
293 | assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL); | 306 | assert(stack > getstackbase(L, ptop) && (stack - 1)->ls != NULL); /* labeled failure */ |
307 | /* assert((stack - 1)->s != NULL); labeled failure: IRecov does not push s onto the stack */ | ||
294 | stack--; | 308 | stack--; |
295 | p += getoffset(p); | 309 | p += getoffset(p); |
296 | continue; | 310 | continue; |
@@ -322,10 +336,14 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
322 | *labelf = LFAIL; /* labeled failure */ | 336 | *labelf = LFAIL; /* labeled failure */ |
323 | *sfail = s; | 337 | *sfail = s; |
324 | fail: { /* pattern failed: try to backtrack */ | 338 | fail: { /* pattern failed: try to backtrack */ |
339 | const Labelset *auxlab = NULL; | ||
325 | do { /* remove pending calls */ | 340 | do { /* remove pending calls */ |
326 | assert(stack > getstackbase(L, ptop)); | 341 | assert(stack > getstackbase(L, ptop)); |
327 | s = (--stack)->s; | 342 | auxlab = (--stack)->ls; |
328 | } while (s == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf))); | 343 | } while (auxlab == NULL || (stack->p != &giveup && !testlabel(stack->ls->cs, *labelf))); |
344 | if (stack->p == &giveup || stack->s != NULL) { /* labeled failure */ | ||
345 | s = stack->s; | ||
346 | } | ||
329 | if (ndyncap > 0) /* is there matchtime captures? */ | 347 | if (ndyncap > 0) /* is there matchtime captures? */ |
330 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); | 348 | ndyncap -= removedyncap(L, capture, stack->caplevel, captop); |
331 | captop = stack->caplevel; | 349 | captop = stack->caplevel; |