Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_regexp_executor.c File Reference
#include "duk_internal.h"

Go to the source code of this file.

Functions

DUK_LOCAL duk_uint32_t duk__bc_get_u32 (duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
 
DUK_LOCAL duk_int32_t duk__bc_get_i32 (duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
 
DUK_LOCAL const duk_uint8_t * duk__utf8_backtrack (duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)
 
DUK_LOCAL const duk_uint8_t * duk__utf8_advance (duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)
 
DUK_LOCAL duk_codepoint_t duk__inp_get_cp (duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp)
 
DUK_LOCAL const duk_uint8_t * duk__inp_backtrack (duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count)
 
DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp (duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp)
 
DUK_LOCAL const duk_uint8_t * duk__match_regexp (duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp)
 
DUK_LOCAL void duk__regexp_match_helper (duk_hthread *thr, duk_small_int_t force_global)
 
DUK_INTERNAL void duk_regexp_match (duk_hthread *thr)
 
DUK_INTERNAL void duk_regexp_match_force_global (duk_hthread *thr)
 

Function Documentation

◆ duk__bc_get_i32()

DUK_LOCAL duk_int32_t duk__bc_get_i32 ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t ** pc )

Definition at line 32 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

32 {
33 duk_uint32_t t;
34
35 /* signed integer encoding needed to work with UTF-8 */
36 t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
37 if (t & 1) {
38 return -((duk_int32_t) (t >> 1));
39 } else {
40 return (duk_int32_t) (t >> 1);
41 }
42}
DUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end)

References duk_re_matcher_ctx::bytecode, duk_re_matcher_ctx::bytecode_end, duk_unicode_decode_xutf8_checked(), and duk_re_matcher_ctx::thr.

Referenced by duk__match_regexp().

◆ duk__bc_get_u32()

DUK_LOCAL duk_uint32_t duk__bc_get_u32 ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t ** pc )

◆ duk__inp_backtrack()

DUK_LOCAL const duk_uint8_t * duk__inp_backtrack ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t ** sp,
duk_uint_fast32_t count )

Definition at line 121 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

121 {
122 return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
123}
DUK_LOCAL const duk_uint8_t * duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)

References duk__utf8_backtrack(), duk_re_matcher_ctx::input, duk_re_matcher_ctx::input_end, and duk_re_matcher_ctx::thr.

Referenced by duk__inp_get_prev_cp(), and duk__match_regexp().

◆ duk__inp_get_cp()

DUK_LOCAL duk_codepoint_t duk__inp_get_cp ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t ** sp )

◆ duk__inp_get_prev_cp()

DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t * sp )

Definition at line 126 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

126 {
127 /* note: caller 'sp' is intentionally not updated here */
128 (void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
129 return duk__inp_get_cp(re_ctx, &sp);
130}
duk_uint32_t duk_uint_fast32_t
DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp)
DUK_LOCAL const duk_uint8_t * duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count)

References duk__inp_backtrack(), and duk__inp_get_cp().

Referenced by duk__match_regexp().

◆ duk__match_regexp()

DUK_LOCAL const duk_uint8_t * duk__match_regexp ( duk_re_matcher_ctx * re_ctx,
const duk_uint8_t * pc,
const duk_uint8_t * sp )

Definition at line 143 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

143 {
144 if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
146 }
147 re_ctx->recursion_depth++;
148
149 for (;;) {
151
152 if (re_ctx->steps_count >= re_ctx->steps_limit) {
154 }
155 re_ctx->steps_count++;
156
157 op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
158
159 DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
160 (long) re_ctx->recursion_depth,
161 (long) re_ctx->steps_count,
162 (long) (pc - re_ctx->bytecode),
163 (long) (sp - re_ctx->input),
164 (long) op));
165
166 switch (op) {
167 case DUK_REOP_MATCH: {
168 goto match;
169 }
170 case DUK_REOP_CHAR: {
171 /*
172 * Byte-based matching would be possible for case-sensitive
173 * matching but not for case-insensitive matching. So, we
174 * match by decoding the input and bytecode character normally.
175 *
176 * Bytecode characters are assumed to be already canonicalized.
177 * Input characters are canonicalized automatically by
178 * duk__inp_get_cp() if necessary.
179 *
180 * There is no opcode for matching multiple characters. The
181 * regexp compiler has trouble joining strings efficiently
182 * during compilation. See doc/regexp.rst for more discussion.
183 */
184 duk_codepoint_t c1, c2;
185
186 c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
188 c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1)); /* canonicalized by compiler */
189 if (sp >= re_ctx->input_end) {
190 goto fail;
191 }
192 c2 = duk__inp_get_cp(re_ctx, &sp);
193 DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
194 if (c1 != c2) {
195 goto fail;
196 }
197 break;
198 }
199 case DUK_REOP_PERIOD: {
201
202 if (sp >= re_ctx->input_end) {
203 goto fail;
204 }
205 c = duk__inp_get_cp(re_ctx, &sp);
207 /* E5 Sections 15.10.2.8, 7.3 */
208 goto fail;
209 }
210 break;
211 }
212 case DUK_REOP_RANGES:
213 case DUK_REOP_INVRANGES: {
214 duk_uint32_t n;
217
218 n = duk__bc_get_u32(re_ctx, &pc);
219 if (sp >= re_ctx->input_end) {
220 goto fail;
221 }
222 c = duk__inp_get_cp(re_ctx, &sp);
223
224 match = 0;
225 while (n) {
226 duk_codepoint_t r1, r2;
227 r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
228 r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
229 DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
230 (long) n, (long) r1, (long) r2, (long) c));
231 if (c >= r1 && c <= r2) {
232 /* Note: don't bail out early, we must read all the ranges from
233 * bytecode. Another option is to skip them efficiently after
234 * breaking out of here. Prefer smallest code.
235 */
236 match = 1;
237 }
238 n--;
239 }
240
241 if (op == DUK_REOP_RANGES) {
242 if (!match) {
243 goto fail;
244 }
245 } else {
247 if (match) {
248 goto fail;
249 }
250 }
251 break;
252 }
255
256 if (sp <= re_ctx->input) {
257 break;
258 }
259 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
260 goto fail;
261 }
262 c = duk__inp_get_prev_cp(re_ctx, sp);
264 /* E5 Sections 15.10.2.8, 7.3 */
265 break;
266 }
267 goto fail;
268 }
269 case DUK_REOP_ASSERT_END: {
271 const duk_uint8_t *tmp_sp;
272
273 if (sp >= re_ctx->input_end) {
274 break;
275 }
276 if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
277 goto fail;
278 }
279 tmp_sp = sp;
280 c = duk__inp_get_cp(re_ctx, &tmp_sp);
282 /* E5 Sections 15.10.2.8, 7.3 */
283 break;
284 }
285 goto fail;
286 }
289 /*
290 * E5 Section 15.10.2.6. The previous and current character
291 * should -not- be canonicalized as they are now. However,
292 * canonicalization does not affect the result of IsWordChar()
293 * (which depends on Unicode characters never canonicalizing
294 * into ASCII characters) so this does not matter.
295 */
296 duk_small_int_t w1, w2;
297
298 if (sp <= re_ctx->input) {
299 w1 = 0; /* not a wordchar */
300 } else {
302 c = duk__inp_get_prev_cp(re_ctx, sp);
304 }
305 if (sp >= re_ctx->input_end) {
306 w2 = 0; /* not a wordchar */
307 } else {
308 const duk_uint8_t *tmp_sp = sp; /* dummy so sp won't get updated */
310 c = duk__inp_get_cp(re_ctx, &tmp_sp);
312 }
313
315 if (w1 == w2) {
316 goto fail;
317 }
318 } else {
320 if (w1 != w2) {
321 goto fail;
322 }
323 }
324 break;
325 }
326 case DUK_REOP_JUMP: {
327 duk_int32_t skip;
328
329 skip = duk__bc_get_i32(re_ctx, &pc);
330 pc += skip;
331 break;
332 }
333 case DUK_REOP_SPLIT1: {
334 /* split1: prefer direct execution (no jump) */
335 const duk_uint8_t *sub_sp;
336 duk_int32_t skip;
337
338 skip = duk__bc_get_i32(re_ctx, &pc);
339 sub_sp = duk__match_regexp(re_ctx, pc, sp);
340 if (sub_sp) {
341 sp = sub_sp;
342 goto match;
343 }
344 pc += skip;
345 break;
346 }
347 case DUK_REOP_SPLIT2: {
348 /* split2: prefer jump execution (not direct) */
349 const duk_uint8_t *sub_sp;
350 duk_int32_t skip;
351
352 skip = duk__bc_get_i32(re_ctx, &pc);
353 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
354 if (sub_sp) {
355 sp = sub_sp;
356 goto match;
357 }
358 break;
359 }
360 case DUK_REOP_SQMINIMAL: {
361 duk_uint32_t q, qmin, qmax;
362 duk_int32_t skip;
363 const duk_uint8_t *sub_sp;
364
365 qmin = duk__bc_get_u32(re_ctx, &pc);
366 qmax = duk__bc_get_u32(re_ctx, &pc);
367 skip = duk__bc_get_i32(re_ctx, &pc);
368 DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
369 (unsigned long) qmin, (unsigned long) qmax, (long) skip));
370
371 q = 0;
372 while (q <= qmax) {
373 if (q >= qmin) {
374 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
375 if (sub_sp) {
376 sp = sub_sp;
377 goto match;
378 }
379 }
380 sub_sp = duk__match_regexp(re_ctx, pc, sp);
381 if (!sub_sp) {
382 break;
383 }
384 sp = sub_sp;
385 q++;
386 }
387 goto fail;
388 }
389 case DUK_REOP_SQGREEDY: {
390 duk_uint32_t q, qmin, qmax, atomlen;
391 duk_int32_t skip;
392 const duk_uint8_t *sub_sp;
393
394 qmin = duk__bc_get_u32(re_ctx, &pc);
395 qmax = duk__bc_get_u32(re_ctx, &pc);
396 atomlen = duk__bc_get_u32(re_ctx, &pc);
397 skip = duk__bc_get_i32(re_ctx, &pc);
398 DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
399 (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
400
401 q = 0;
402 while (q < qmax) {
403 sub_sp = duk__match_regexp(re_ctx, pc, sp);
404 if (!sub_sp) {
405 break;
406 }
407 sp = sub_sp;
408 q++;
409 }
410 while (q >= qmin) {
411 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
412 if (sub_sp) {
413 sp = sub_sp;
414 goto match;
415 }
416 if (q == qmin) {
417 break;
418 }
419
420 /* Note: if atom were to contain e.g. captures, we would need to
421 * re-match the atom to get correct captures. Simply quantifiers
422 * do not allow captures in their atom now, so this is not an issue.
423 */
424
425 DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
426 (long) atomlen));
427 sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
428 q--;
429 }
430 goto fail;
431 }
432 case DUK_REOP_SAVE: {
433 duk_uint32_t idx;
434 const duk_uint8_t *old;
435 const duk_uint8_t *sub_sp;
436
437 idx = duk__bc_get_u32(re_ctx, &pc);
438 if (idx >= re_ctx->nsaved) {
439 /* idx is unsigned, < 0 check is not necessary */
440 DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
441 goto internal_error;
442 }
443 old = re_ctx->saved[idx];
444 re_ctx->saved[idx] = sp;
445 sub_sp = duk__match_regexp(re_ctx, pc, sp);
446 if (sub_sp) {
447 sp = sub_sp;
448 goto match;
449 }
450 re_ctx->saved[idx] = old;
451 goto fail;
452 }
453 case DUK_REOP_WIPERANGE: {
454 /* Wipe capture range and save old values for backtracking.
455 *
456 * XXX: this typically happens with a relatively small idx_count.
457 * It might be useful to handle cases where the count is small
458 * (say <= 8) by saving the values in stack instead. This would
459 * reduce memory churn and improve performance, at the cost of a
460 * slightly higher code footprint.
461 */
462 duk_uint32_t idx_start, idx_count;
463#ifdef DUK_USE_EXPLICIT_NULL_INIT
464 duk_uint32_t idx_end, idx;
465#endif
466 duk_uint8_t **range_save;
467 const duk_uint8_t *sub_sp;
468
469 idx_start = duk__bc_get_u32(re_ctx, &pc);
470 idx_count = duk__bc_get_u32(re_ctx, &pc);
471 DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
472 (long) idx_start, (long) idx_count,
473 (long) idx_start, (long) (idx_start + idx_count - 1),
474 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
475 if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
476 /* idx is unsigned, < 0 check is not necessary */
477 DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
478 (long) idx_start, (long) idx_count));
479 goto internal_error;
480 }
481 DUK_ASSERT(idx_count > 0);
482
483 duk_require_stack((duk_context *) re_ctx->thr, 1);
484 range_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
485 sizeof(duk_uint8_t *) * idx_count);
486 DUK_ASSERT(range_save != NULL);
487 DUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
488#ifdef DUK_USE_EXPLICIT_NULL_INIT
489 idx_end = idx_start + idx_count;
490 for (idx = idx_start; idx < idx_end; idx++) {
491 re_ctx->saved[idx] = NULL;
492 }
493#else
494 DUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
495#endif
496
497 sub_sp = duk__match_regexp(re_ctx, pc, sp);
498 if (sub_sp) {
499 /* match: keep wiped/resaved values */
500 DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
501 (long) idx_start, (long) (idx_start + idx_count - 1),
502 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
503 duk_pop((duk_context *) re_ctx->thr);
504 sp = sub_sp;
505 goto match;
506 }
507
508 /* fail: restore saves */
509 DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
510 (long) idx_start, (long) (idx_start + idx_count - 1),
511 (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
512 DUK_MEMCPY((void *) (re_ctx->saved + idx_start),
513 (const void *) range_save,
514 sizeof(duk_uint8_t *) * idx_count);
515 duk_pop((duk_context *) re_ctx->thr);
516 goto fail;
517 }
518 case DUK_REOP_LOOKPOS:
519 case DUK_REOP_LOOKNEG: {
520 /*
521 * Needs a save of multiple saved[] entries depending on what range
522 * may be overwritten. Because the regexp parser does no such analysis,
523 * we currently save the entire saved array here. Lookaheads are thus
524 * a bit expensive. Note that the saved array is not needed for just
525 * the lookahead sub-match, but for the matching of the entire sequel.
526 *
527 * The temporary save buffer is pushed on to the valstack to handle
528 * errors correctly. Each lookahead causes a C recursion and pushes
529 * more stuff on the value stack. If the C recursion limit is less
530 * than the value stack spare, there is no need to check the stack.
531 * We do so regardless, just in case.
532 */
533
534 duk_int32_t skip;
535 duk_uint8_t **full_save;
536 const duk_uint8_t *sub_sp;
537
538 DUK_ASSERT(re_ctx->nsaved > 0);
539
540 duk_require_stack((duk_context *) re_ctx->thr, 1);
541 full_save = (duk_uint8_t **) duk_push_fixed_buffer((duk_context *) re_ctx->thr,
542 sizeof(duk_uint8_t *) * re_ctx->nsaved);
543 DUK_ASSERT(full_save != NULL);
544 DUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
545
546 skip = duk__bc_get_i32(re_ctx, &pc);
547 sub_sp = duk__match_regexp(re_ctx, pc, sp);
548 if (op == DUK_REOP_LOOKPOS) {
549 if (!sub_sp) {
550 goto lookahead_fail;
551 }
552 } else {
553 if (sub_sp) {
554 goto lookahead_fail;
555 }
556 }
557 sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
558 if (sub_sp) {
559 /* match: keep saves */
560 duk_pop((duk_context *) re_ctx->thr);
561 sp = sub_sp;
562 goto match;
563 }
564
565 /* fall through */
566
567 lookahead_fail:
568 /* fail: restore saves */
569 DUK_MEMCPY((void *) re_ctx->saved,
570 (const void *) full_save,
571 sizeof(duk_uint8_t *) * re_ctx->nsaved);
572 duk_pop((duk_context *) re_ctx->thr);
573 goto fail;
574 }
576 /*
577 * Byte matching for back-references would be OK in case-
578 * sensitive matching. In case-insensitive matching we need
579 * to canonicalize characters, so back-reference matching needs
580 * to be done with codepoints instead. So, we just decode
581 * everything normally here, too.
582 *
583 * Note: back-reference index which is 0 or higher than
584 * NCapturingParens (= number of capturing parens in the
585 * -entire- regexp) is a compile time error. However, a
586 * backreference referring to a valid capture which has
587 * not matched anything always succeeds! See E5 Section
588 * 15.10.2.9, step 5, sub-step 3.
589 */
590 duk_uint32_t idx;
591 const duk_uint8_t *p;
592
593 idx = duk__bc_get_u32(re_ctx, &pc);
594 idx = idx << 1; /* backref n -> saved indices [n*2, n*2+1] */
595 if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
596 /* regexp compiler should catch these */
597 DUK_D(DUK_DPRINT("internal error, backreference index insane"));
598 goto internal_error;
599 }
600 if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
601 /* capture is 'undefined', always matches! */
602 DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
603 (long) idx, (long) (idx + 1)));
604 break;
605 }
606 DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
607
608 p = re_ctx->saved[idx];
609 while (p < re_ctx->saved[idx+1]) {
610 duk_codepoint_t c1, c2;
611
612 /* Note: not necessary to check p against re_ctx->input_end:
613 * the memory access is checked by duk__inp_get_cp(), while
614 * valid compiled regexps cannot write a saved[] entry
615 * which points to outside the string.
616 */
617 if (sp >= re_ctx->input_end) {
618 goto fail;
619 }
620 c1 = duk__inp_get_cp(re_ctx, &p);
621 c2 = duk__inp_get_cp(re_ctx, &sp);
622 if (c1 != c2) {
623 goto fail;
624 }
625 }
626 break;
627 }
628 default: {
629 DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
630 goto internal_error;
631 }
632 }
633 }
634
635 match:
636 re_ctx->recursion_depth--;
637 return sp;
638
639 fail:
640 re_ctx->recursion_depth--;
641 return NULL;
642
643 internal_error:
645 return NULL; /* never here */
646}
#define DUK_MEMZERO(p, n)
#define DUK_ERROR_RANGE(thr, msg)
#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT
#define DUK_REOP_ASSERT_WORD_BOUNDARY
#define DUK_RE_FLAG_MULTILINE
DUK_EXTERNAL void duk_require_stack(duk_context *ctx, duk_idx_t extra)
#define DUK_ERROR_INTERNAL_DEFMSG(thr)
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp)
#define DUK_REOP_BACKREFERENCE
#define DUK_REOP_ASSERT_START
DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp)
DUK_EXTERNAL void duk_pop(duk_context *ctx)
#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY
#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT
#define duk_push_fixed_buffer(ctx, size)
DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
DUK_LOCAL const duk_uint8_t * duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp)
DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc)
DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp)
#define NULL
Definition gmacros.h:924
static const char * match(MatchState *ms, const char *s, const char *p)

References duk_re_matcher_ctx::bytecode, duk__bc_get_i32(), duk__bc_get_u32(), duk__inp_backtrack(), duk__inp_get_cp(), duk__inp_get_prev_cp(), duk__match_regexp(), DUK_ASSERT, DUK_D, DUK_DDD, DUK_DDDPRINT, DUK_DPRINT, DUK_ERROR_INTERNAL_DEFMSG, DUK_ERROR_RANGE, DUK_MEMCPY, DUK_MEMZERO, duk_pop(), duk_push_fixed_buffer, DUK_RE_FLAG_IGNORE_CASE, DUK_RE_FLAG_MULTILINE, DUK_REOP_ASSERT_END, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY, DUK_REOP_ASSERT_START, DUK_REOP_ASSERT_WORD_BOUNDARY, DUK_REOP_BACKREFERENCE, DUK_REOP_CHAR, DUK_REOP_INVRANGES, DUK_REOP_JUMP, DUK_REOP_LOOKNEG, DUK_REOP_LOOKPOS, DUK_REOP_MATCH, DUK_REOP_PERIOD, DUK_REOP_RANGES, DUK_REOP_SAVE, DUK_REOP_SPLIT1, DUK_REOP_SPLIT2, DUK_REOP_SQGREEDY, DUK_REOP_SQMINIMAL, DUK_REOP_WIPERANGE, duk_require_stack(), DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT, duk_unicode_is_line_terminator(), duk_unicode_re_canonicalize_char(), duk_unicode_re_is_wordchar(), duk_re_matcher_ctx::input, duk_re_matcher_ctx::input_end, match(), duk_re_matcher_ctx::nsaved, NULL, duk_re_matcher_ctx::re_flags, duk_re_matcher_ctx::recursion_depth, duk_re_matcher_ctx::recursion_limit, duk_re_matcher_ctx::saved, duk_re_matcher_ctx::steps_count, duk_re_matcher_ctx::steps_limit, and duk_re_matcher_ctx::thr.

Referenced by duk__match_regexp(), and duk__regexp_match_helper().

◆ duk__regexp_match_helper()

DUK_LOCAL void duk__regexp_match_helper ( duk_hthread * thr,
duk_small_int_t force_global )

Definition at line 660 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

660 {
661 duk_context *ctx = (duk_context *) thr;
662 duk_re_matcher_ctx re_ctx;
663 duk_hobject *h_regexp;
664 duk_hstring *h_bytecode;
665 duk_hstring *h_input;
666 duk_uint8_t *p_buf;
667 const duk_uint8_t *pc;
668 const duk_uint8_t *sp;
670 duk_small_int_t global;
672 double d;
673 duk_uint32_t char_offset;
674
675 DUK_ASSERT(thr != NULL);
676 DUK_ASSERT(ctx != NULL);
677
678 DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
679 (duk_tval *) duk_get_tval(ctx, -2),
680 (duk_tval *) duk_get_tval(ctx, -1)));
681
682 /*
683 * Regexp instance check, bytecode check, input coercion.
684 *
685 * See E5 Section 15.10.6.
686 */
687
688 /* TypeError if wrong; class check, see E5 Section 15.10.6 */
690 DUK_ASSERT(h_regexp != NULL);
692 DUK_UNREF(h_regexp);
693
694 duk_to_string(ctx, -1);
695 h_input = duk_get_hstring(ctx, -1);
696 DUK_ASSERT(h_input != NULL);
697
698 duk_get_prop_stridx(ctx, -2, DUK_STRIDX_INT_BYTECODE); /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
699 h_bytecode = duk_require_hstring(ctx, -1); /* no regexp instance should exist without a non-configurable bytecode property */
700 DUK_ASSERT(h_bytecode != NULL);
701
702 /*
703 * Basic context initialization.
704 *
705 * Some init values are read from the bytecode header
706 * whose format is (UTF-8 codepoints):
707 *
708 * uint flags
709 * uint nsaved (even, 2n+2 where n = num captures)
710 */
711
712 /* [ ... re_obj input bc ] */
713
714 DUK_MEMZERO(&re_ctx, sizeof(re_ctx));
715
716 re_ctx.thr = thr;
717 re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
718 re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
719 re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
720 re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
721 re_ctx.saved = NULL;
724
725 /* read header */
726 pc = re_ctx.bytecode;
727 re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
728 re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
729 re_ctx.bytecode = pc;
730
731 DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL); /* must fit into duk_small_int_t */
732 global = (duk_small_int_t) (force_global | (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
733
734 DUK_ASSERT(re_ctx.nsaved >= 2);
735 DUK_ASSERT((re_ctx.nsaved % 2) == 0);
736
737 p_buf = (duk_uint8_t *) duk_push_fixed_buffer(ctx, sizeof(duk_uint8_t *) * re_ctx.nsaved);
738 DUK_UNREF(p_buf);
739 re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(ctx, -1, NULL);
740 DUK_ASSERT(re_ctx.saved != NULL);
741
742 /* [ ... re_obj input bc saved_buf ] */
743
744#if defined(DUK_USE_EXPLICIT_NULL_INIT)
745 for (i = 0; i < re_ctx.nsaved; i++) {
746 re_ctx.saved[i] = (duk_uint8_t *) NULL;
747 }
748#elif defined(DUK_USE_ZERO_BUFFER_DATA)
749 /* buffer is automatically zeroed */
750#else
751 DUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
752#endif
753
754 DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
755 (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
756 (long) re_ctx.steps_limit));
757
758 /*
759 * Get starting character offset for match, and initialize 'sp' based on it.
760 *
761 * Note: lastIndex is non-configurable so it must be present (we check the
762 * internal class of the object above, so we know it is). User code can set
763 * its value to an arbitrary (garbage) value though; E5 requires that lastIndex
764 * be coerced to a number before using. The code below works even if the
765 * property is missing: the value will then be coerced to zero.
766 *
767 * Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
768 * For instance, ToInteger(+Infinity) = +Infinity. We track the match offset
769 * as an integer, but pre-check it to be inside the 32-bit range before the loop.
770 * If not, the check in E5 Section 15.10.6.2, step 9.a applies.
771 */
772
773 /* XXX: lastIndex handling produces a lot of asm */
774
775 /* [ ... re_obj input bc saved_buf ] */
776
777 duk_get_prop_stridx(ctx, -4, DUK_STRIDX_LAST_INDEX); /* -> [ ... re_obj input bc saved_buf lastIndex ] */
778 (void) duk_to_int(ctx, -1); /* ToInteger(lastIndex) */
779 d = duk_get_number(ctx, -1); /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
780 duk_pop(ctx);
781
782 if (global) {
783 if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
784 /* match fail */
785 char_offset = 0; /* not really necessary */
786 DUK_ASSERT(match == 0);
787 goto match_over;
788 }
789 char_offset = (duk_uint32_t) d;
790 } else {
791 /* lastIndex must be ignored for non-global regexps, but get the
792 * value for (theoretical) side effects. No side effects can
793 * really occur, because lastIndex is a normal property and is
794 * always non-configurable for RegExp instances.
795 */
796 char_offset = (duk_uint32_t) 0;
797 }
798
799 sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
800
801 /*
802 * Match loop.
803 *
804 * Try matching at different offsets until match found or input exhausted.
805 */
806
807 /* [ ... re_obj input bc saved_buf ] */
808
809 DUK_ASSERT(match == 0);
810
811 for (;;) {
812 /* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
813 DUK_ASSERT_DISABLE(char_offset >= 0);
814 DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
815
816 /* Note: ctx.steps is intentionally not reset, it applies to the entire unanchored match */
817 DUK_ASSERT(re_ctx.recursion_depth == 0);
818
819 DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
820 (long) char_offset, (const void *) sp,
821 (const void *) re_ctx.input, (const void *) re_ctx.input_end));
822
823 /*
824 * Note:
825 *
826 * - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
827 * conditions; a longjmp() will terminate the entire matching process.
828 *
829 * - Clearing saved[] is not necessary because backtracking does it
830 *
831 * - Backtracking also rewinds ctx.recursion back to zero, unless an
832 * internal/limit error occurs (which causes a longjmp())
833 *
834 * - If we supported anchored matches, we would break out here
835 * unconditionally; however, Ecmascript regexps don't have anchored
836 * matches. It might make sense to implement a fast bail-out if
837 * the regexp begins with '^' and sp is not 0: currently we'll just
838 * run through the entire input string, trivially failing the match
839 * at every non-zero offset.
840 */
841
842 if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
843 DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
844 match = 1;
845 break;
846 }
847
848 /* advance by one character (code point) and one char_offset */
849 char_offset++;
850 if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
851 /*
852 * Note:
853 *
854 * - Intentionally attempt (empty) match at char_offset == k_input->clen
855 *
856 * - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
857 * -> no need or use for a negative check
858 */
859
860 DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
861 break;
862 }
863
864 /* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
865 (void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
866 }
867
868 match_over:
869
870 /*
871 * Matching complete, create result array or return a 'null'. Update lastIndex
872 * if necessary. See E5 Section 15.10.6.2.
873 *
874 * Because lastIndex is a character (not byte) offset, we need the character
875 * length of the match which we conveniently get as a side effect of interning
876 * the matching substring (0th index of result array).
877 *
878 * saved[0] start pointer (~ byte offset) of current match
879 * saved[1] end pointer (~ byte offset) of current match (exclusive)
880 * char_offset start character offset of current match (-> .index of result)
881 * char_end_offset end character offset (computed below)
882 */
883
884 /* [ ... re_obj input bc saved_buf ] */
885
886 if (match) {
887#ifdef DUK_USE_ASSERTIONS
888 duk_hobject *h_res;
889#endif
890 duk_uint32_t char_end_offset = 0;
891
892 DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
893
894 DUK_ASSERT(re_ctx.nsaved >= 2); /* must have start and end */
895 DUK_ASSERT((re_ctx.nsaved % 2) == 0); /* and even number */
896
897 /* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
898 * advantage of now. The array is not compacted either, as regexp match
899 * objects are usually short lived.
900 */
901
902 duk_push_array(ctx);
903
904#ifdef DUK_USE_ASSERTIONS
905 h_res = duk_require_hobject(ctx, -1);
909#endif
910
911 /* [ ... re_obj input bc saved_buf res_obj ] */
912
913 duk_push_u32(ctx, char_offset);
915
916 duk_dup(ctx, -4);
918
919 for (i = 0; i < re_ctx.nsaved; i += 2) {
920 /* Captures which are undefined have NULL pointers and are returned
921 * as 'undefined'. The same is done when saved[] pointers are insane
922 * (this should, of course, never happen in practice).
923 */
924 if (re_ctx.saved[i] && re_ctx.saved[i+1] && re_ctx.saved[i+1] >= re_ctx.saved[i]) {
925 duk_hstring *h_saved;
926
928 (const char *) re_ctx.saved[i],
929 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
930 h_saved = duk_get_hstring(ctx, -1);
931 DUK_ASSERT(h_saved != NULL);
932
933 if (i == 0) {
934 /* Assumes that saved[0] and saved[1] are always
935 * set by regexp bytecode (if not, char_end_offset
936 * will be zero). Also assumes clen reflects the
937 * correct char length.
938 */
939 char_end_offset = char_offset + DUK_HSTRING_GET_CHARLEN(h_saved);
940 }
941 } else {
943 }
944
945 /* [ ... re_obj input bc saved_buf res_obj val ] */
946 duk_put_prop_index(ctx, -2, i / 2);
947 }
948
949 /* [ ... re_obj input bc saved_buf res_obj ] */
950
951 /* NB: 'length' property is automatically updated by the array setup loop */
952
953 if (global) {
954 /* global regexp: lastIndex updated on match */
955 duk_push_u32(ctx, char_end_offset);
957 } else {
958 /* non-global regexp: lastIndex never updated on match */
959 ;
960 }
961 } else {
962 /*
963 * No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
964 * of 'global' flag of the RegExp. In particular, if lastIndex is invalid
965 * initially, it is reset to zero.
966 */
967
968 DUK_DDD(DUK_DDDPRINT("regexp does not match"));
969
970 duk_push_null(ctx);
971
972 /* [ ... re_obj input bc saved_buf res_obj ] */
973
974 duk_push_int(ctx, 0);
976 }
977
978 /* [ ... re_obj input bc saved_buf res_obj ] */
979
980 duk_insert(ctx, -5);
981
982 /* [ ... res_obj re_obj input bc saved_buf ] */
983
984 duk_pop_n(ctx, 4);
985
986 /* [ ... res_obj ] */
987
988 /* XXX: these last tricks are unnecessary if the function is made
989 * a genuine native function.
990 */
991}
#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT
#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)
#define DUK_HSTRING_GET_DATA(x)
#define DUK_HOBJECT_CLASS_REGEXP
DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_context *ctx, duk_idx_t obj_index, duk_small_int_t stridx)
#define DUK_RE_EXECUTE_STEPS_LIMIT
DUK_EXTERNAL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t index)
#define duk_xdef_prop_stridx_wec(ctx, obj_index, stridx)
DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx)
DUK_EXTERNAL void * duk_get_buffer(duk_context *ctx, duk_idx_t index, duk_size_t *out_size)
DUK_INTERNAL_DECL duk_hobject * duk_require_hobject_with_class(duk_context *ctx, duk_idx_t index, duk_small_uint_t classnum)
#define DUK_HSTRING_GET_CHARLEN(x)
#define DUK_HOBJECT_CLASS_ARRAY
DUK_EXTERNAL const char * duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len)
#define DUK_ASSERT_DISABLE(x)
DUK_EXTERNAL void duk_push_null(duk_context *ctx)
DUK_EXTERNAL void duk_push_int(duk_context *ctx, duk_int_t val)
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset)
#define DUK_HSTRING_GET_BYTELEN(x)
DUK_EXTERNAL void duk_dup(duk_context *ctx, duk_idx_t from_index)
DUK_EXTERNAL void duk_insert(duk_context *ctx, duk_idx_t to_index)
#define DUK_STRIDX_LAST_INDEX
DUK_EXTERNAL void duk_push_undefined(duk_context *ctx)
DUK_EXTERNAL void duk_pop_n(duk_context *ctx, duk_idx_t count)
DUK_EXTERNAL const char * duk_to_string(duk_context *ctx, duk_idx_t index)
#define DUK_STRIDX_INT_BYTECODE
DUK_EXTERNAL duk_idx_t duk_push_array(duk_context *ctx)
#define DUK_HOBJECT_GET_CLASS_NUMBER(h)
DUK_INTERNAL_DECL duk_hstring * duk_get_hstring(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_hstring * duk_require_hstring(duk_context *ctx, duk_idx_t index)
#define DUK_HOBJECT_HAS_EXTENSIBLE(h)
#define duk_push_u32(ctx, val)
DUK_EXTERNAL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t index)
DUK_INTERNAL_DECL duk_tval * duk_get_tval(duk_context *ctx, duk_idx_t index)
DUK_LOCAL const duk_uint8_t * duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count)

References duk_re_matcher_ctx::bytecode, duk_re_matcher_ctx::bytecode_end, duk__bc_get_u32(), duk__match_regexp(), duk__utf8_advance(), DUK_ASSERT, DUK_ASSERT_DISABLE, DUK_DD, DUK_DDD, DUK_DDDPRINT, DUK_DDPRINT, duk_dup(), duk_get_buffer(), duk_get_hstring(), duk_get_number(), duk_get_prop_stridx(), duk_get_tval(), duk_heap_strcache_offset_char2byte(), DUK_HOBJECT_CLASS_ARRAY, DUK_HOBJECT_CLASS_REGEXP, DUK_HOBJECT_GET_CLASS_NUMBER, DUK_HOBJECT_HAS_EXOTIC_ARRAY, DUK_HOBJECT_HAS_EXTENSIBLE, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_CHARLEN, DUK_HSTRING_GET_DATA, duk_insert(), DUK_MEMZERO, duk_pop(), duk_pop_n(), duk_push_array(), duk_push_fixed_buffer, duk_push_int(), duk_push_lstring(), duk_push_null(), duk_push_u32, duk_push_undefined(), duk_put_prop_index(), duk_put_prop_stridx(), DUK_RE_EXECUTE_STEPS_LIMIT, DUK_RE_FLAG_GLOBAL, duk_require_hobject(), duk_require_hobject_with_class(), duk_require_hstring(), DUK_STRIDX_INDEX, DUK_STRIDX_INPUT, DUK_STRIDX_INT_BYTECODE, DUK_STRIDX_LAST_INDEX, duk_to_int(), duk_to_string(), DUK_UNREF, DUK_USE_REGEXP_EXECUTOR_RECLIMIT, duk_xdef_prop_stridx_wec, duk_re_matcher_ctx::input, duk_re_matcher_ctx::input_end, match(), duk_re_matcher_ctx::nsaved, NULL, duk_re_matcher_ctx::re_flags, duk_re_matcher_ctx::recursion_depth, duk_re_matcher_ctx::recursion_limit, duk_re_matcher_ctx::saved, duk_re_matcher_ctx::steps_limit, and duk_re_matcher_ctx::thr.

Referenced by duk_regexp_match(), and duk_regexp_match_force_global().

◆ duk__utf8_advance()

DUK_LOCAL const duk_uint8_t * duk__utf8_advance ( duk_hthread * thr,
const duk_uint8_t ** ptr,
const duk_uint8_t * ptr_start,
const duk_uint8_t * ptr_end,
duk_uint_fast32_t count )

Definition at line 74 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

74 {
75 const duk_uint8_t *p;
76
77 p = *ptr;
78 if (p < ptr_start || p >= ptr_end) {
79 goto fail;
80 }
81
82 while (count > 0) {
83 for (;;) {
84 p++;
85
86 /* Note: if encoding ends by hitting end of input, we don't check that
87 * the encoding is valid, we just assume it is.
88 */
89 if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
90 /* utf-8 continuation bytes have the form 10xx xxxx */
91 break;
92 }
93 }
94 count--;
95 }
96
97 *ptr = p;
98 return p;
99
100 fail:
102 return NULL; /* never here */
103}

References DUK_ERROR_INTERNAL_DEFMSG, and NULL.

Referenced by duk__regexp_match_helper().

◆ duk__utf8_backtrack()

DUK_LOCAL const duk_uint8_t * duk__utf8_backtrack ( duk_hthread * thr,
const duk_uint8_t ** ptr,
const duk_uint8_t * ptr_start,
const duk_uint8_t * ptr_end,
duk_uint_fast32_t count )

Definition at line 44 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

44 {
45 const duk_uint8_t *p;
46
47 /* Note: allow backtracking from p == ptr_end */
48 p = *ptr;
49 if (p < ptr_start || p > ptr_end) {
50 goto fail;
51 }
52
53 while (count > 0) {
54 for (;;) {
55 p--;
56 if (p < ptr_start) {
57 goto fail;
58 }
59 if ((*p & 0xc0) != 0x80) {
60 /* utf-8 continuation bytes have the form 10xx xxxx */
61 break;
62 }
63 }
64 count--;
65 }
66 *ptr = p;
67 return p;
68
69 fail:
71 return NULL; /* never here */
72}

References DUK_ERROR_INTERNAL_DEFMSG, and NULL.

Referenced by duk__inp_backtrack().

◆ duk_regexp_match()

DUK_INTERNAL void duk_regexp_match ( duk_hthread * thr)

Definition at line 993 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

993 {
994 duk__regexp_match_helper(thr, 0 /*force_global*/);
995}
DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global)

References duk__regexp_match_helper().

◆ duk_regexp_match_force_global()

DUK_INTERNAL void duk_regexp_match_force_global ( duk_hthread * thr)

Definition at line 1000 of file duktape-1.5.2/src-separate/duk_regexp_executor.c.

1000 {
1001 duk__regexp_match_helper(thr, 1 /*force_global*/);
1002}

References duk__regexp_match_helper().