1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecma-globals.h"
17 #include "ecma-regexp-object.h"
18 #include "lit-strings.h"
19 #include "re-bytecode.h"
20
21 #if ENABLED (JERRY_BUILTIN_REGEXP)
22
23 /** \addtogroup parser Parser
24 * @{
25 *
26 * \addtogroup regexparser Regular expression
27 * @{
28 *
29 * \addtogroup regexparser_bytecode Bytecode
30 * @{
31 */
32
33 void
re_initialize_regexp_bytecode(re_compiler_ctx_t * re_ctx_p)34 re_initialize_regexp_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
35 {
36 const size_t initial_size = sizeof (re_compiled_code_t);
37 re_ctx_p->bytecode_start_p = jmem_heap_alloc_block (initial_size);
38 re_ctx_p->bytecode_size = initial_size;
39 } /* re_initialize_regexp_bytecode */
40
41 inline uint32_t JERRY_ATTR_ALWAYS_INLINE
re_bytecode_size(re_compiler_ctx_t * re_ctx_p)42 re_bytecode_size (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
43 {
44 return (uint32_t) re_ctx_p->bytecode_size;
45 } /* re_bytecode_size */
46
47 /**
48 * Append a new bytecode to the and of the bytecode container
49 */
50 static uint8_t *
re_bytecode_reserve(re_compiler_ctx_t * re_ctx_p,const size_t size)51 re_bytecode_reserve (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
52 const size_t size) /**< size */
53 {
54 const size_t old_size = re_ctx_p->bytecode_size;
55 const size_t new_size = old_size + size;
56 re_ctx_p->bytecode_start_p = jmem_heap_realloc_block (re_ctx_p->bytecode_start_p, old_size, new_size);
57 re_ctx_p->bytecode_size = new_size;
58 return re_ctx_p->bytecode_start_p + old_size;
59 } /* re_bytecode_reserve */
60
61 /**
62 * Insert a new bytecode to the bytecode container
63 */
64 static uint8_t *
re_bytecode_insert(re_compiler_ctx_t * re_ctx_p,const size_t offset,const size_t size)65 re_bytecode_insert (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
66 const size_t offset, /**< distance from the start of the container */
67 const size_t size) /**< size */
68 {
69 const size_t tail_size = re_ctx_p->bytecode_size - offset;
70 re_bytecode_reserve (re_ctx_p, size);
71
72 uint8_t *dest_p = re_ctx_p->bytecode_start_p + offset;
73 memmove (dest_p + size, dest_p, tail_size);
74
75 return dest_p;
76 } /* re_bytecode_insert */
77
78 /**
79 * Append a byte
80 */
81 void
re_append_byte(re_compiler_ctx_t * re_ctx_p,const uint8_t byte)82 re_append_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
83 const uint8_t byte) /**< byte value */
84 {
85 uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, sizeof (uint8_t));
86 *dest_p = byte;
87 } /* re_append_byte */
88
89 /**
90 * Insert a byte value
91 */
92 void
re_insert_byte(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const uint8_t byte)93 re_insert_byte (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
94 const uint32_t offset, /**< distance from the start of the container */
95 const uint8_t byte) /**< byte value */
96 {
97 uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, sizeof (uint8_t));
98 *dest_p = byte;
99 } /* re_insert_byte */
100
101 /**
102 * Get a single byte and icnrease bytecode position.
103 */
104 inline uint8_t JERRY_ATTR_ALWAYS_INLINE
re_get_byte(const uint8_t ** bc_p)105 re_get_byte (const uint8_t **bc_p) /**< pointer to bytecode start */
106 {
107 return *((*bc_p)++);
108 } /* re_get_byte */
109
110 /**
111 * Append a RegExp opcode
112 */
113 inline void JERRY_ATTR_ALWAYS_INLINE
re_append_opcode(re_compiler_ctx_t * re_ctx_p,const re_opcode_t opcode)114 re_append_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
115 const re_opcode_t opcode) /**< input opcode */
116 {
117 re_append_byte (re_ctx_p, (uint8_t) opcode);
118 } /* re_append_opcode */
119
120 /**
121 * Insert a RegExp opcode
122 */
123 inline void JERRY_ATTR_ALWAYS_INLINE
re_insert_opcode(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const re_opcode_t opcode)124 re_insert_opcode (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
125 const uint32_t offset, /**< distance from the start of the container */
126 const re_opcode_t opcode) /**< input opcode */
127 {
128 re_insert_byte (re_ctx_p, offset, (uint8_t) opcode);
129 } /* re_insert_opcode */
130
131 /**
132 * Get a RegExp opcode and increase the bytecode position
133 *
134 * @return current RegExp opcode
135 */
136 inline re_opcode_t JERRY_ATTR_ALWAYS_INLINE
re_get_opcode(const uint8_t ** bc_p)137 re_get_opcode (const uint8_t **bc_p) /**< pointer to bytecode start */
138 {
139 return (re_opcode_t) re_get_byte (bc_p);
140 } /* re_get_opcode */
141
142 /**
143 * Encode 2 byte unsigned integer into the bytecode
144 */
145 static void
re_encode_u16(uint8_t * dest_p,const uint16_t value)146 re_encode_u16 (uint8_t *dest_p, /**< destination */
147 const uint16_t value) /**< value */
148 {
149 *dest_p++ = (uint8_t) ((value >> 8) & 0xFF);
150 *dest_p = (uint8_t) (value & 0xFF);
151 } /* re_encode_u16 */
152
153 /**
154 * Encode 4 byte unsigned integer into the bytecode
155 */
156 static void
re_encode_u32(uint8_t * dest_p,const uint32_t value)157 re_encode_u32 (uint8_t *dest_p, /**< destination */
158 const uint32_t value) /**< value */
159 {
160 *dest_p++ = (uint8_t) ((value >> 24) & 0xFF);
161 *dest_p++ = (uint8_t) ((value >> 16) & 0xFF);
162 *dest_p++ = (uint8_t) ((value >> 8) & 0xFF);
163 *dest_p = (uint8_t) (value & 0xFF);
164 } /* re_encode_u32 */
165
166 /**
167 * Decode 2 byte unsigned integer from bytecode
168 *
169 * @return uint16_t value
170 */
171 static uint16_t
re_decode_u16(const uint8_t * src_p)172 re_decode_u16 (const uint8_t *src_p) /**< source */
173 {
174 uint16_t value = (uint16_t) (((uint16_t) *src_p++) << 8);
175 value = (uint16_t) (value + *src_p++);
176 return value;
177 } /* re_decode_u16 */
178
179 /**
180 * Decode 4 byte unsigned integer from bytecode
181 *
182 * @return uint32_t value
183 */
184 static uint32_t JERRY_ATTR_NOINLINE
re_decode_u32(const uint8_t * src_p)185 re_decode_u32 (const uint8_t *src_p) /**< source */
186 {
187 uint32_t value = (uint32_t) (((uint32_t) *src_p++) << 24);
188 value += (uint32_t) (((uint32_t) *src_p++) << 16);
189 value += (uint32_t) (((uint32_t) *src_p++) << 8);
190 value += (uint32_t) (*src_p++);
191 return value;
192 } /* re_decode_u32 */
193
194 /**
195 * Get the encoded size of an uint32_t value.
196 *
197 * @return encoded value size
198 */
199 inline static size_t JERRY_ATTR_ALWAYS_INLINE
re_get_encoded_value_size(uint32_t value)200 re_get_encoded_value_size (uint32_t value) /**< value */
201 {
202 if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
203 {
204 return 1;
205 }
206
207 return 5;
208 } /* re_get_encoded_value_size */
209
210 /*
211 * Encode a value to the specified position in the bytecode.
212 */
213 static void
re_encode_value(uint8_t * dest_p,const uint32_t value)214 re_encode_value (uint8_t *dest_p, /**< position in bytecode */
215 const uint32_t value) /**< value */
216 {
217 if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
218 {
219 *dest_p = (uint8_t) value;
220 return;
221 }
222
223 *dest_p++ = (uint8_t) (RE_VALUE_4BYTE_MARKER);
224 re_encode_u32 (dest_p, value);
225 } /* re_encode_value */
226
227 /**
228 * Append a value to the end of the bytecode.
229 */
230 void
re_append_value(re_compiler_ctx_t * re_ctx_p,const uint32_t value)231 re_append_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
232 const uint32_t value) /**< value */
233 {
234 const size_t size = re_get_encoded_value_size (value);
235 uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size);
236 re_encode_value (dest_p, value);
237 } /* re_append_value */
238
239 /**
240 * Insert a value into the bytecode at a specific offset.
241 */
242 void
re_insert_value(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const uint32_t value)243 re_insert_value (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
244 const uint32_t offset, /**< bytecode offset */
245 const uint32_t value) /**< value */
246 {
247 const size_t size = re_get_encoded_value_size (value);
248 uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size);
249 re_encode_value (dest_p, value);
250 } /* re_insert_value */
251
252 /**
253 * Read an encoded value from the bytecode.
254 *
255 * @return decoded value
256 */
257 uint32_t JERRY_ATTR_ALWAYS_INLINE
re_get_value(const uint8_t ** bc_p)258 re_get_value (const uint8_t **bc_p) /** refence to bytecode pointer */
259 {
260 uint32_t value = *(*bc_p)++;
261 if (JERRY_LIKELY (value <= RE_VALUE_1BYTE_MAX))
262 {
263 return value;
264 }
265
266 value = re_decode_u32 (*bc_p);
267 *bc_p += sizeof (uint32_t);
268 return value;
269 } /* re_get_value */
270
271 /**
272 * Append a character to the RegExp bytecode
273 */
274 void
re_append_char(re_compiler_ctx_t * re_ctx_p,const lit_code_point_t cp)275 re_append_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
276 const lit_code_point_t cp) /**< code point */
277 {
278 #if ENABLED (JERRY_ES2015)
279 const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t);
280 #else /* !ENABLED (JERRY_ES2015) */
281 JERRY_UNUSED (re_ctx_p);
282 const size_t size = sizeof (ecma_char_t);
283 #endif /* !ENABLED (JERRY_ES2015) */
284
285 uint8_t *dest_p = re_bytecode_reserve (re_ctx_p, size);
286
287 #if ENABLED (JERRY_ES2015)
288 if (re_ctx_p->flags & RE_FLAG_UNICODE)
289 {
290 re_encode_u32 (dest_p, cp);
291 return;
292 }
293 #endif /* ENABLED (JERRY_ES2015) */
294
295 JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX);
296 re_encode_u16 (dest_p, (ecma_char_t) cp);
297 } /* re_append_char */
298
299 /**
300 * Append a character to the RegExp bytecode
301 */
302 void
re_insert_char(re_compiler_ctx_t * re_ctx_p,const uint32_t offset,const lit_code_point_t cp)303 re_insert_char (re_compiler_ctx_t *re_ctx_p, /**< RegExp bytecode context */
304 const uint32_t offset, /**< bytecode offset */
305 const lit_code_point_t cp) /**< code point*/
306 {
307 #if ENABLED (JERRY_ES2015)
308 const size_t size = (re_ctx_p->flags & RE_FLAG_UNICODE) ? sizeof (lit_code_point_t) : sizeof (ecma_char_t);
309 #else /* !ENABLED (JERRY_ES2015) */
310 JERRY_UNUSED (re_ctx_p);
311 const size_t size = sizeof (ecma_char_t);
312 #endif /* !ENABLED (JERRY_ES2015) */
313
314 uint8_t *dest_p = re_bytecode_insert (re_ctx_p, offset, size);
315
316 #if ENABLED (JERRY_ES2015)
317 if (re_ctx_p->flags & RE_FLAG_UNICODE)
318 {
319 re_encode_u32 (dest_p, cp);
320 return;
321 }
322 #endif /* ENABLED (JERRY_ES2015) */
323
324 JERRY_ASSERT (cp <= LIT_UTF16_CODE_UNIT_MAX);
325 re_encode_u16 (dest_p, (ecma_char_t) cp);
326 } /* re_insert_char */
327
328 /**
329 * Decode a character from the bytecode.
330 *
331 * @return decoded character
332 */
333 inline lit_code_point_t JERRY_ATTR_ALWAYS_INLINE
re_get_char(const uint8_t ** bc_p,bool unicode)334 re_get_char (const uint8_t **bc_p, /**< reference to bytecode pointer */
335 bool unicode) /**< full unicode mode */
336 {
337 lit_code_point_t cp;
338
339 #if !ENABLED (JERRY_ES2015)
340 JERRY_UNUSED (unicode);
341 #else /* ENABLED (JERRY_ES2015) */
342 if (unicode)
343 {
344 cp = re_decode_u32 (*bc_p);
345 *bc_p += sizeof (lit_code_point_t);
346 }
347 else
348 #endif /* ENABLED (JERRY_ES2015) */
349 {
350 cp = re_decode_u16 (*bc_p);
351 *bc_p += sizeof (ecma_char_t);
352 }
353
354 return cp;
355 } /* re_get_char */
356
357 #if ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE)
358 static uint32_t
re_get_bytecode_offset(const uint8_t * start_p,const uint8_t * current_p)359 re_get_bytecode_offset (const uint8_t *start_p, /**< bytecode start pointer */
360 const uint8_t *current_p) /**< current bytecode pointer */
361 {
362 return (uint32_t) ((uintptr_t) current_p - (uintptr_t) start_p);
363 } /* re_get_bytecode_offset */
364
365 /**
366 * RegExp bytecode dumper
367 */
368 void
re_dump_bytecode(re_compiler_ctx_t * re_ctx_p)369 re_dump_bytecode (re_compiler_ctx_t *re_ctx_p) /**< RegExp bytecode context */
370 {
371 static const char escape_chars[] = {'d', 'D', 'w', 'W', 's', 'S'};
372
373 re_compiled_code_t *compiled_code_p = (re_compiled_code_t *) re_ctx_p->bytecode_start_p;
374 JERRY_DEBUG_MSG ("Flags: 0x%x ", compiled_code_p->header.status_flags);
375 JERRY_DEBUG_MSG ("Capturing groups: %d ", compiled_code_p->captures_count);
376 JERRY_DEBUG_MSG ("Non-capturing groups: %d\n", compiled_code_p->non_captures_count);
377
378 const uint8_t *bytecode_start_p = (const uint8_t *) (compiled_code_p + 1);
379 const uint8_t *bytecode_p = bytecode_start_p;
380
381 while (true)
382 {
383 JERRY_DEBUG_MSG ("[%3u] ", (uint32_t) ((uintptr_t) bytecode_p - (uintptr_t) bytecode_start_p));
384 re_opcode_t op = *bytecode_p++;
385 switch (op)
386 {
387 case RE_OP_ALTERNATIVE_START:
388 {
389 JERRY_DEBUG_MSG ("ALTERNATIVE_START ");
390 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
391 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
392 break;
393 }
394 case RE_OP_ALTERNATIVE_NEXT:
395 {
396 JERRY_DEBUG_MSG ("ALTERNATIVE_NEXT ");
397 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
398 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
399 break;
400 }
401 case RE_OP_NO_ALTERNATIVE:
402 {
403 JERRY_DEBUG_MSG ("NO_ALTERNATIVES\n");
404 break;
405 }
406 case RE_OP_CAPTURING_GROUP_START:
407 {
408 JERRY_DEBUG_MSG ("CAPTURING_GROUP_START ");
409 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
410 JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
411
412 const uint32_t qmin = re_get_value (&bytecode_p);
413 JERRY_DEBUG_MSG ("qmin: %u", qmin);
414 if (qmin == 0)
415 {
416 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
417 JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset);
418 }
419 else
420 {
421 JERRY_DEBUG_MSG ("\n");
422 }
423
424 break;
425 }
426 case RE_OP_NON_CAPTURING_GROUP_START:
427 {
428 JERRY_DEBUG_MSG ("NON_CAPTURING_GROUP_START ");
429 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
430 JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
431 JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
432
433 const uint32_t qmin = re_get_value (&bytecode_p);
434 JERRY_DEBUG_MSG ("qmin: %u", qmin);
435 if (qmin == 0)
436 {
437 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
438 JERRY_DEBUG_MSG (", tail offset: [%3u]\n", offset);
439 }
440 else
441 {
442 JERRY_DEBUG_MSG ("\n");
443 }
444
445 break;
446 }
447 case RE_OP_GREEDY_CAPTURING_GROUP_END:
448 {
449 JERRY_DEBUG_MSG ("GREEDY_CAPTURING_GROUP_END ");
450 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
451 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
452 JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
453 break;
454 }
455 case RE_OP_LAZY_CAPTURING_GROUP_END:
456 {
457 JERRY_DEBUG_MSG ("LAZY_CAPTURING_GROUP_END ");
458 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
459 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
460 JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
461 break;
462 }
463 case RE_OP_GREEDY_NON_CAPTURING_GROUP_END:
464 {
465 JERRY_DEBUG_MSG ("GREEDY_NON_CAPTURING_GROUP_END ");
466 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
467 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
468 JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
469 break;
470 }
471 case RE_OP_LAZY_NON_CAPTURING_GROUP_END:
472 {
473 JERRY_DEBUG_MSG ("LAZY_NON_CAPTURING_GROUP_END ");
474 JERRY_DEBUG_MSG ("idx: %u, ", re_get_value (&bytecode_p));
475 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
476 JERRY_DEBUG_MSG ("qmax: %u\n", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
477 break;
478 }
479 case RE_OP_GREEDY_ITERATOR:
480 {
481 JERRY_DEBUG_MSG ("GREEDY_ITERATOR ");
482 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
483 JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
484 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
485 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
486 break;
487 }
488 case RE_OP_LAZY_ITERATOR:
489 {
490 JERRY_DEBUG_MSG ("LAZY_ITERATOR ");
491 JERRY_DEBUG_MSG ("qmin: %u, ", re_get_value (&bytecode_p));
492 JERRY_DEBUG_MSG ("qmax: %u, ", re_get_value (&bytecode_p) - RE_QMAX_OFFSET);
493 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
494 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
495 break;
496 }
497 case RE_OP_ITERATOR_END:
498 {
499 JERRY_DEBUG_MSG ("ITERATOR_END\n");
500 break;
501 }
502 case RE_OP_BACKREFERENCE:
503 {
504 JERRY_DEBUG_MSG ("BACKREFERENCE ");
505 JERRY_DEBUG_MSG ("idx: %d\n", re_get_value (&bytecode_p));
506 break;
507 }
508 case RE_OP_ASSERT_LINE_START:
509 {
510 JERRY_DEBUG_MSG ("ASSERT_LINE_START\n");
511 break;
512 }
513 case RE_OP_ASSERT_LINE_END:
514 {
515 JERRY_DEBUG_MSG ("ASSERT_LINE_END\n");
516 break;
517 }
518 case RE_OP_ASSERT_LOOKAHEAD_POS:
519 {
520 JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_POS ");
521 JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++);
522 JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
523 JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
524 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
525 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
526 break;
527 }
528 case RE_OP_ASSERT_LOOKAHEAD_NEG:
529 {
530 JERRY_DEBUG_MSG ("ASSERT_LOOKAHEAD_NEG ");
531 JERRY_DEBUG_MSG ("qmin: %u, ", *bytecode_p++);
532 JERRY_DEBUG_MSG ("capture start: %u, ", re_get_value (&bytecode_p));
533 JERRY_DEBUG_MSG ("capture count: %u, ", re_get_value (&bytecode_p));
534 const uint32_t offset = re_get_value (&bytecode_p) + re_get_bytecode_offset (bytecode_start_p, bytecode_p);
535 JERRY_DEBUG_MSG ("tail offset: [%3u]\n", offset);
536 break;
537 }
538 case RE_OP_ASSERT_END:
539 {
540 JERRY_DEBUG_MSG ("ASSERT_END\n");
541 break;
542 }
543 case RE_OP_ASSERT_WORD_BOUNDARY:
544 {
545 JERRY_DEBUG_MSG ("ASSERT_WORD_BOUNDARY\n");
546 break;
547 }
548 case RE_OP_ASSERT_NOT_WORD_BOUNDARY:
549 {
550 JERRY_DEBUG_MSG ("ASSERT_NOT_WORD_BOUNDARY\n");
551 break;
552 }
553 case RE_OP_CLASS_ESCAPE:
554 {
555 ecma_class_escape_t escape = (ecma_class_escape_t) *bytecode_p++;
556 JERRY_DEBUG_MSG ("CLASS_ESCAPE \\%c\n", escape_chars[escape]);
557 break;
558 }
559 case RE_OP_CHAR_CLASS:
560 {
561 JERRY_DEBUG_MSG ("CHAR_CLASS ");
562 uint8_t flags = *bytecode_p++;
563 uint32_t char_count = (flags & RE_CLASS_HAS_CHARS) ? re_get_value (&bytecode_p) : 0;
564 uint32_t range_count = (flags & RE_CLASS_HAS_RANGES) ? re_get_value (&bytecode_p) : 0;
565
566 if (flags & RE_CLASS_INVERT)
567 {
568 JERRY_DEBUG_MSG ("inverted ");
569 }
570
571 JERRY_DEBUG_MSG ("escapes: ");
572 uint8_t escape_count = flags & RE_CLASS_ESCAPE_COUNT_MASK;
573 while (escape_count--)
574 {
575 JERRY_DEBUG_MSG ("\\%c, ", escape_chars[*bytecode_p++]);
576 }
577
578 JERRY_DEBUG_MSG ("chars: ");
579 while (char_count--)
580 {
581 JERRY_DEBUG_MSG ("\\u%04x, ", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE));
582 }
583
584 JERRY_DEBUG_MSG ("ranges: ");
585 while (range_count--)
586 {
587 const lit_code_point_t begin = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE);
588 const lit_code_point_t end = re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE);
589 JERRY_DEBUG_MSG ("\\u%04x-\\u%04x, ", begin, end);
590 }
591
592 JERRY_DEBUG_MSG ("\n");
593 break;
594 }
595 #if ENABLED (JERRY_ES2015)
596 case RE_OP_UNICODE_PERIOD:
597 {
598 JERRY_DEBUG_MSG ("UNICODE_PERIOD\n");
599 break;
600 }
601 #endif /* ENABLED (JERRY_ES2015) */
602 case RE_OP_PERIOD:
603 {
604 JERRY_DEBUG_MSG ("PERIOD\n");
605 break;
606 }
607 case RE_OP_CHAR:
608 {
609 JERRY_DEBUG_MSG ("CHAR \\u%04x\n", re_get_char (&bytecode_p, re_ctx_p->flags & RE_FLAG_UNICODE));
610 break;
611 }
612 case RE_OP_BYTE:
613 {
614 const uint8_t ch = *bytecode_p++;
615 JERRY_DEBUG_MSG ("BYTE \\u%04x '%c'\n", ch, (char) ch);
616 break;
617 }
618 case RE_OP_EOF:
619 {
620 JERRY_DEBUG_MSG ("EOF\n");
621 return;
622 }
623 default:
624 {
625 JERRY_DEBUG_MSG ("UNKNOWN(%d)\n", (uint32_t) op);
626 break;
627 }
628 }
629 }
630 } /* re_dump_bytecode */
631 #endif /* ENABLED (JERRY_REGEXP_DUMP_BYTE_CODE) */
632
633 /**
634 * @}
635 * @}
636 * @}
637 */
638
639 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
640