@react-native-quickjs/quickjs 1.0.0-alpha.1 → 1.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +173 -15
- package/README.md +17 -0
- package/ReactNativeQuickJS.podspec +13 -1
- package/android/CMakeLists.txt +6 -0
- package/android/build.gradle +33 -6
- package/bin/qjsc/darwin-arm64/qjsc +0 -0
- package/bin/qjsc/darwin-x64/qjsc +0 -0
- package/bin/qjsc/linux-arm64/qjsc +0 -0
- package/bin/qjsc/linux-x64/qjsc +0 -0
- package/bin/qjsc/win32-x64/qjsc.exe +0 -0
- package/cmake/quickjs.cmake +9 -0
- package/engine/quickjs-rel/MANIFEST.json +118 -13
- package/engine/quickjs-rel/builtin-array-fromasync.h +100 -92
- package/engine/quickjs-rel/builtin-iterator-zip-keyed.h +288 -273
- package/engine/quickjs-rel/builtin-iterator-zip.h +293 -276
- package/engine/quickjs-rel/libregexp-backtrack.c.inc +583 -0
- package/engine/quickjs-rel/libregexp.c +1021 -573
- package/engine/quickjs-rel/libregexp.h +54 -2
- package/engine/quickjs-rel/libunicode-table.h +71 -84
- package/engine/quickjs-rel/libunicode.c +5 -0
- package/engine/quickjs-rel/quickjs-opcode.h +15 -6
- package/engine/quickjs-rel/quickjs.c +6581 -734
- package/engine/quickjs-rel/quickjs.h +43 -9
- package/package.json +15 -3
- package/src/runtime/QuickJSRuntime.cpp +18 -5
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
/* Runtime-width backtracking VM body, included once from libregexp.c. */
|
|
2
|
+
static intptr_t LRE_BT_FUNC(REExecContext *s, uint8_t **capture,
|
|
3
|
+
const uint8_t *pc, const uint8_t *cptr)
|
|
4
|
+
{
|
|
5
|
+
int opcode;
|
|
6
|
+
const int cbuf_type = LRE_CBUF_TYPE_INIT;
|
|
7
|
+
uint32_t val, c, idx;
|
|
8
|
+
const uint8_t *cbuf_end;
|
|
9
|
+
StackElem *sp, *bp, *stack_end;
|
|
10
|
+
#ifdef DUMP_EXEC
|
|
11
|
+
const uint8_t *pc_start = pc; /* TEST */
|
|
12
|
+
#endif
|
|
13
|
+
cbuf_end = s->cbuf_end;
|
|
14
|
+
|
|
15
|
+
sp = s->stack_buf;
|
|
16
|
+
bp = s->stack_buf;
|
|
17
|
+
stack_end = s->stack_buf + s->stack_size;
|
|
18
|
+
|
|
19
|
+
#define CHECK_STACK_SPACE(n) \
|
|
20
|
+
if (unlikely((stack_end - sp) < (n))) { \
|
|
21
|
+
size_t saved_sp = sp - s->stack_buf; \
|
|
22
|
+
size_t saved_bp = bp - s->stack_buf; \
|
|
23
|
+
if (stack_realloc(s, sp - s->stack_buf + (n))) \
|
|
24
|
+
return LRE_RET_MEMORY_ERROR; \
|
|
25
|
+
stack_end = s->stack_buf + s->stack_size; \
|
|
26
|
+
sp = s->stack_buf + saved_sp; \
|
|
27
|
+
bp = s->stack_buf + saved_bp; \
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* XXX: could test if the value was saved to reduce the stack size
|
|
31
|
+
but slower */
|
|
32
|
+
#define SAVE_CAPTURE(idx, value) \
|
|
33
|
+
{ \
|
|
34
|
+
CHECK_STACK_SPACE(2); \
|
|
35
|
+
sp[0].val = idx; \
|
|
36
|
+
sp[1].ptr = capture[idx]; \
|
|
37
|
+
sp += 2; \
|
|
38
|
+
capture[idx] = (value); \
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* avoid saving the previous value if already saved */
|
|
42
|
+
#define SAVE_CAPTURE_CHECK(idx, value) \
|
|
43
|
+
{ \
|
|
44
|
+
StackElem *sp1; \
|
|
45
|
+
sp1 = sp; \
|
|
46
|
+
for(;;) { \
|
|
47
|
+
if (sp1 > bp) { \
|
|
48
|
+
if (sp1[-2].val == idx) \
|
|
49
|
+
break; \
|
|
50
|
+
sp1 -= 2; \
|
|
51
|
+
} else { \
|
|
52
|
+
CHECK_STACK_SPACE(2); \
|
|
53
|
+
sp[0].val = idx; \
|
|
54
|
+
sp[1].ptr = capture[idx]; \
|
|
55
|
+
sp += 2; \
|
|
56
|
+
break; \
|
|
57
|
+
} \
|
|
58
|
+
} \
|
|
59
|
+
capture[idx] = (value); \
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
#ifdef DUMP_EXEC
|
|
64
|
+
#define LRE_DUMP_OP() \
|
|
65
|
+
printf("%5ld %5ld %5ld %5ld %s\n", \
|
|
66
|
+
(long)(pc - 1 - pc_start), \
|
|
67
|
+
(long)(cbuf_type == 0 ? cptr - s->cbuf : (cptr - s->cbuf) / 2), \
|
|
68
|
+
(long)(bp - s->stack_buf), \
|
|
69
|
+
(long)(sp - s->stack_buf), \
|
|
70
|
+
reopcode_info[opcode].name)
|
|
71
|
+
#else
|
|
72
|
+
#define LRE_DUMP_OP()
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
/* Threaded-code dispatch: on compilers with the GCC label-as-value
|
|
76
|
+
extension, jump directly from one opcode handler to the next via a
|
|
77
|
+
table instead of returning to a central switch. Falls back to a plain
|
|
78
|
+
switch elsewhere (MSVC, Emscripten). */
|
|
79
|
+
#if !LRE_DIRECT_DISPATCH
|
|
80
|
+
#define SWITCH(pc) opcode = *pc++; LRE_DUMP_OP(); switch(opcode)
|
|
81
|
+
#define CASE(op) case op
|
|
82
|
+
#define DEFAULT default
|
|
83
|
+
#define BREAK break
|
|
84
|
+
#else
|
|
85
|
+
static const void * const dispatch_table[256] = {
|
|
86
|
+
#define DEF(id, size) [REOP_ ## id] = && case_REOP_ ## id,
|
|
87
|
+
#include "libregexp-opcode.h"
|
|
88
|
+
#undef DEF
|
|
89
|
+
[REOP_COUNT ... 255] = && case_default,
|
|
90
|
+
};
|
|
91
|
+
/* Wrapped in a statement-expression with a trailing ';' so that BREAK is a
|
|
92
|
+
single statement usable in unbraced contexts like 'if (cond) BREAK;'. */
|
|
93
|
+
#define SWITCH(pc) __extension__ ({ opcode = *pc++; LRE_DUMP_OP(); goto *dispatch_table[opcode]; });
|
|
94
|
+
#define CASE(op) case_ ## op
|
|
95
|
+
#define DEFAULT case_default
|
|
96
|
+
#define BREAK SWITCH(pc)
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
#ifdef DUMP_EXEC
|
|
100
|
+
printf("%5s %5s %5s %5s %s\n", "PC", "CP", "BP", "SP", "OPCODE");
|
|
101
|
+
#endif
|
|
102
|
+
for(;;) {
|
|
103
|
+
SWITCH(pc) {
|
|
104
|
+
CASE(REOP_match):
|
|
105
|
+
return 1;
|
|
106
|
+
no_match:
|
|
107
|
+
for(;;) {
|
|
108
|
+
REExecStateEnum type;
|
|
109
|
+
if (bp == s->stack_buf)
|
|
110
|
+
return 0;
|
|
111
|
+
/* undo the modifications to capture[] */
|
|
112
|
+
while (sp > bp) {
|
|
113
|
+
capture[sp[-2].val] = sp[-1].ptr;
|
|
114
|
+
sp -= 2;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
pc = sp[-3].ptr;
|
|
118
|
+
cptr = sp[-2].ptr;
|
|
119
|
+
type = sp[-1].bp.type;
|
|
120
|
+
bp = s->stack_buf + sp[-1].bp.val;
|
|
121
|
+
sp -= 3;
|
|
122
|
+
if (type != RE_EXEC_STATE_LOOKAHEAD)
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
if (lre_poll_timeout(s))
|
|
126
|
+
return LRE_RET_TIMEOUT;
|
|
127
|
+
BREAK;
|
|
128
|
+
CASE(REOP_lookahead_match):
|
|
129
|
+
/* pop all the saved states until reaching the start of
|
|
130
|
+
the lookahead and keep the updated captures and
|
|
131
|
+
variables and the corresponding undo info. */
|
|
132
|
+
{
|
|
133
|
+
StackElem *sp1, *sp_top, *next_sp;
|
|
134
|
+
REExecStateEnum type;
|
|
135
|
+
|
|
136
|
+
sp_top = sp;
|
|
137
|
+
for(;;) {
|
|
138
|
+
sp1 = sp;
|
|
139
|
+
sp = bp;
|
|
140
|
+
pc = sp[-3].ptr;
|
|
141
|
+
cptr = sp[-2].ptr;
|
|
142
|
+
type = sp[-1].bp.type;
|
|
143
|
+
bp = s->stack_buf + sp[-1].bp.val;
|
|
144
|
+
sp[-1].ptr = (void *)sp1; /* save the next value for the copy step */
|
|
145
|
+
sp -= 3;
|
|
146
|
+
if (type == RE_EXEC_STATE_LOOKAHEAD)
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
if (sp != s->stack_buf) {
|
|
150
|
+
/* keep the undo info if there is a saved state */
|
|
151
|
+
sp1 = sp;
|
|
152
|
+
while (sp1 < sp_top) {
|
|
153
|
+
next_sp = (void *)sp1[2].ptr;
|
|
154
|
+
sp1 += 3;
|
|
155
|
+
while (sp1 < next_sp)
|
|
156
|
+
*sp++ = *sp1++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
BREAK;
|
|
161
|
+
CASE(REOP_negative_lookahead_match):
|
|
162
|
+
/* pop all the saved states until reaching start of the negative lookahead */
|
|
163
|
+
for(;;) {
|
|
164
|
+
REExecStateEnum type;
|
|
165
|
+
type = bp[-1].bp.type;
|
|
166
|
+
/* undo the modifications to capture[] */
|
|
167
|
+
while (sp > bp) {
|
|
168
|
+
capture[sp[-2].val] = sp[-1].ptr;
|
|
169
|
+
sp -= 2;
|
|
170
|
+
}
|
|
171
|
+
pc = sp[-3].ptr;
|
|
172
|
+
cptr = sp[-2].ptr;
|
|
173
|
+
type = sp[-1].bp.type;
|
|
174
|
+
bp = s->stack_buf + sp[-1].bp.val;
|
|
175
|
+
sp -= 3;
|
|
176
|
+
if (type == RE_EXEC_STATE_NEGATIVE_LOOKAHEAD)
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
goto no_match;
|
|
180
|
+
CASE(REOP_char32):
|
|
181
|
+
CASE(REOP_char32_i):
|
|
182
|
+
val = get_u32(pc);
|
|
183
|
+
pc += 4;
|
|
184
|
+
goto test_char;
|
|
185
|
+
CASE(REOP_char):
|
|
186
|
+
CASE(REOP_char_i):
|
|
187
|
+
val = get_u16(pc);
|
|
188
|
+
pc += 2;
|
|
189
|
+
test_char:
|
|
190
|
+
if (cptr >= cbuf_end)
|
|
191
|
+
goto no_match;
|
|
192
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
193
|
+
if (opcode == REOP_char_i || opcode == REOP_char32_i) {
|
|
194
|
+
c = lre_canonicalize(c, s->is_unicode);
|
|
195
|
+
}
|
|
196
|
+
if (val != c)
|
|
197
|
+
goto no_match;
|
|
198
|
+
BREAK;
|
|
199
|
+
CASE(REOP_split_goto_first):
|
|
200
|
+
CASE(REOP_split_next_first):
|
|
201
|
+
{
|
|
202
|
+
const uint8_t *pc1;
|
|
203
|
+
|
|
204
|
+
val = get_u32(pc);
|
|
205
|
+
pc += 4;
|
|
206
|
+
if (opcode == REOP_split_next_first) {
|
|
207
|
+
pc1 = pc + (int)val;
|
|
208
|
+
} else {
|
|
209
|
+
pc1 = pc;
|
|
210
|
+
pc = pc + (int)val;
|
|
211
|
+
}
|
|
212
|
+
CHECK_STACK_SPACE(3);
|
|
213
|
+
sp[0].ptr = (uint8_t *)pc1;
|
|
214
|
+
sp[1].ptr = (uint8_t *)cptr;
|
|
215
|
+
sp[2].bp.val = bp - s->stack_buf;
|
|
216
|
+
sp[2].bp.type = RE_EXEC_STATE_SPLIT;
|
|
217
|
+
sp += 3;
|
|
218
|
+
bp = sp;
|
|
219
|
+
}
|
|
220
|
+
BREAK;
|
|
221
|
+
CASE(REOP_lookahead):
|
|
222
|
+
CASE(REOP_negative_lookahead):
|
|
223
|
+
val = get_u32(pc);
|
|
224
|
+
pc += 4;
|
|
225
|
+
CHECK_STACK_SPACE(3);
|
|
226
|
+
sp[0].ptr = (uint8_t *)(pc + (int)val);
|
|
227
|
+
sp[1].ptr = (uint8_t *)cptr;
|
|
228
|
+
sp[2].bp.val = bp - s->stack_buf;
|
|
229
|
+
sp[2].bp.type = RE_EXEC_STATE_LOOKAHEAD + opcode - REOP_lookahead;
|
|
230
|
+
sp += 3;
|
|
231
|
+
bp = sp;
|
|
232
|
+
BREAK;
|
|
233
|
+
CASE(REOP_goto):
|
|
234
|
+
val = get_u32(pc);
|
|
235
|
+
pc += 4 + (int)val;
|
|
236
|
+
if (lre_poll_timeout(s))
|
|
237
|
+
return LRE_RET_TIMEOUT;
|
|
238
|
+
BREAK;
|
|
239
|
+
CASE(REOP_line_start):
|
|
240
|
+
CASE(REOP_line_start_m):
|
|
241
|
+
if (cptr == s->cbuf)
|
|
242
|
+
BREAK;
|
|
243
|
+
if (opcode == REOP_line_start)
|
|
244
|
+
goto no_match;
|
|
245
|
+
PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
|
|
246
|
+
if (!is_line_terminator(c))
|
|
247
|
+
goto no_match;
|
|
248
|
+
BREAK;
|
|
249
|
+
CASE(REOP_line_end):
|
|
250
|
+
CASE(REOP_line_end_m):
|
|
251
|
+
if (cptr == cbuf_end)
|
|
252
|
+
BREAK;
|
|
253
|
+
if (opcode == REOP_line_end)
|
|
254
|
+
goto no_match;
|
|
255
|
+
PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
256
|
+
if (!is_line_terminator(c))
|
|
257
|
+
goto no_match;
|
|
258
|
+
BREAK;
|
|
259
|
+
CASE(REOP_dot):
|
|
260
|
+
if (cptr == cbuf_end)
|
|
261
|
+
goto no_match;
|
|
262
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
263
|
+
if (is_line_terminator(c))
|
|
264
|
+
goto no_match;
|
|
265
|
+
BREAK;
|
|
266
|
+
CASE(REOP_any):
|
|
267
|
+
if (cptr == cbuf_end)
|
|
268
|
+
goto no_match;
|
|
269
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
270
|
+
BREAK;
|
|
271
|
+
CASE(REOP_space):
|
|
272
|
+
if (cptr == cbuf_end)
|
|
273
|
+
goto no_match;
|
|
274
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
275
|
+
if (!lre_is_space(c))
|
|
276
|
+
goto no_match;
|
|
277
|
+
BREAK;
|
|
278
|
+
CASE(REOP_not_space):
|
|
279
|
+
if (cptr == cbuf_end)
|
|
280
|
+
goto no_match;
|
|
281
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
282
|
+
if (lre_is_space(c))
|
|
283
|
+
goto no_match;
|
|
284
|
+
BREAK;
|
|
285
|
+
CASE(REOP_save_start):
|
|
286
|
+
CASE(REOP_save_end):
|
|
287
|
+
val = *pc++;
|
|
288
|
+
if (val >= (uint32_t)s->capture_count)
|
|
289
|
+
return LRE_RET_BYTECODE_ERROR;
|
|
290
|
+
idx = 2 * val + opcode - REOP_save_start;
|
|
291
|
+
SAVE_CAPTURE(idx, (uint8_t *)cptr);
|
|
292
|
+
BREAK;
|
|
293
|
+
CASE(REOP_save_reset):
|
|
294
|
+
{
|
|
295
|
+
uint32_t val2;
|
|
296
|
+
val = pc[0];
|
|
297
|
+
val2 = pc[1];
|
|
298
|
+
pc += 2;
|
|
299
|
+
if (val2 >= (uint32_t)s->capture_count)
|
|
300
|
+
return LRE_RET_BYTECODE_ERROR;
|
|
301
|
+
CHECK_STACK_SPACE(2 * (val2 - val + 1));
|
|
302
|
+
while (val <= val2) {
|
|
303
|
+
idx = 2 * val;
|
|
304
|
+
SAVE_CAPTURE(idx, NULL);
|
|
305
|
+
idx = 2 * val + 1;
|
|
306
|
+
SAVE_CAPTURE(idx, NULL);
|
|
307
|
+
val++;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
BREAK;
|
|
311
|
+
CASE(REOP_set_i32):
|
|
312
|
+
idx = 2 * s->capture_count + pc[0];
|
|
313
|
+
val = get_u32(pc + 1);
|
|
314
|
+
pc += 5;
|
|
315
|
+
SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val);
|
|
316
|
+
BREAK;
|
|
317
|
+
CASE(REOP_loop):
|
|
318
|
+
{
|
|
319
|
+
uint32_t val2;
|
|
320
|
+
idx = 2 * s->capture_count + pc[0];
|
|
321
|
+
val = get_u32(pc + 1);
|
|
322
|
+
pc += 5;
|
|
323
|
+
|
|
324
|
+
val2 = (uintptr_t)capture[idx] - 1;
|
|
325
|
+
SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2);
|
|
326
|
+
if (val2 != 0) {
|
|
327
|
+
pc += (int)val;
|
|
328
|
+
if (lre_poll_timeout(s))
|
|
329
|
+
return LRE_RET_TIMEOUT;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
BREAK;
|
|
333
|
+
CASE(REOP_loop_split_goto_first):
|
|
334
|
+
CASE(REOP_loop_split_next_first):
|
|
335
|
+
CASE(REOP_loop_check_adv_split_goto_first):
|
|
336
|
+
CASE(REOP_loop_check_adv_split_next_first):
|
|
337
|
+
{
|
|
338
|
+
const uint8_t *pc1;
|
|
339
|
+
uint32_t val2, limit;
|
|
340
|
+
idx = 2 * s->capture_count + pc[0];
|
|
341
|
+
limit = get_u32(pc + 1);
|
|
342
|
+
val = get_u32(pc + 5);
|
|
343
|
+
pc += 9;
|
|
344
|
+
|
|
345
|
+
/* decrement the counter */
|
|
346
|
+
val2 = (uintptr_t)capture[idx] - 1;
|
|
347
|
+
SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2);
|
|
348
|
+
|
|
349
|
+
if (val2 > limit) {
|
|
350
|
+
/* normal loop if counter > limit */
|
|
351
|
+
pc += (int)val;
|
|
352
|
+
if (lre_poll_timeout(s))
|
|
353
|
+
return LRE_RET_TIMEOUT;
|
|
354
|
+
} else {
|
|
355
|
+
/* check advance */
|
|
356
|
+
if ((opcode == REOP_loop_check_adv_split_goto_first ||
|
|
357
|
+
opcode == REOP_loop_check_adv_split_next_first) &&
|
|
358
|
+
capture[idx + 1] == cptr &&
|
|
359
|
+
val2 != limit) {
|
|
360
|
+
goto no_match;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* otherwise conditional split */
|
|
364
|
+
if (val2 != 0) {
|
|
365
|
+
if (opcode == REOP_loop_split_next_first ||
|
|
366
|
+
opcode == REOP_loop_check_adv_split_next_first) {
|
|
367
|
+
pc1 = pc + (int)val;
|
|
368
|
+
} else {
|
|
369
|
+
pc1 = pc;
|
|
370
|
+
pc = pc + (int)val;
|
|
371
|
+
}
|
|
372
|
+
CHECK_STACK_SPACE(3);
|
|
373
|
+
sp[0].ptr = (uint8_t *)pc1;
|
|
374
|
+
sp[1].ptr = (uint8_t *)cptr;
|
|
375
|
+
sp[2].bp.val = bp - s->stack_buf;
|
|
376
|
+
sp[2].bp.type = RE_EXEC_STATE_SPLIT;
|
|
377
|
+
sp += 3;
|
|
378
|
+
bp = sp;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
BREAK;
|
|
383
|
+
CASE(REOP_set_char_pos):
|
|
384
|
+
idx = 2 * s->capture_count + pc[0];
|
|
385
|
+
pc++;
|
|
386
|
+
SAVE_CAPTURE_CHECK(idx, (uint8_t *)cptr);
|
|
387
|
+
BREAK;
|
|
388
|
+
CASE(REOP_check_advance):
|
|
389
|
+
idx = 2 * s->capture_count + pc[0];
|
|
390
|
+
pc++;
|
|
391
|
+
if (capture[idx] == cptr)
|
|
392
|
+
goto no_match;
|
|
393
|
+
BREAK;
|
|
394
|
+
CASE(REOP_word_boundary):
|
|
395
|
+
CASE(REOP_word_boundary_i):
|
|
396
|
+
CASE(REOP_not_word_boundary):
|
|
397
|
+
CASE(REOP_not_word_boundary_i):
|
|
398
|
+
{
|
|
399
|
+
bool v1, v2;
|
|
400
|
+
int ignore_case = (opcode == REOP_word_boundary_i || opcode == REOP_not_word_boundary_i);
|
|
401
|
+
bool is_boundary = (opcode == REOP_word_boundary || opcode == REOP_word_boundary_i);
|
|
402
|
+
/* char before */
|
|
403
|
+
if (cptr == s->cbuf) {
|
|
404
|
+
v1 = false;
|
|
405
|
+
} else {
|
|
406
|
+
PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
|
|
407
|
+
if (c < 256) {
|
|
408
|
+
v1 = (lre_is_word_byte(c) != 0);
|
|
409
|
+
} else {
|
|
410
|
+
v1 = ignore_case && (c == 0x017f || c == 0x212a);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/* current char */
|
|
414
|
+
if (cptr >= cbuf_end) {
|
|
415
|
+
v2 = false;
|
|
416
|
+
} else {
|
|
417
|
+
PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
418
|
+
if (c < 256) {
|
|
419
|
+
v2 = (lre_is_word_byte(c) != 0);
|
|
420
|
+
} else {
|
|
421
|
+
v2 = ignore_case && (c == 0x017f || c == 0x212a);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (v1 ^ v2 ^ is_boundary)
|
|
425
|
+
goto no_match;
|
|
426
|
+
}
|
|
427
|
+
BREAK;
|
|
428
|
+
CASE(REOP_back_reference):
|
|
429
|
+
CASE(REOP_back_reference_i):
|
|
430
|
+
CASE(REOP_backward_back_reference):
|
|
431
|
+
CASE(REOP_backward_back_reference_i):
|
|
432
|
+
{
|
|
433
|
+
const uint8_t *cptr1, *cptr1_end, *cptr1_start;
|
|
434
|
+
const uint8_t *pc1;
|
|
435
|
+
uint32_t c1, c2;
|
|
436
|
+
int i, n;
|
|
437
|
+
|
|
438
|
+
n = *pc++;
|
|
439
|
+
pc1 = pc;
|
|
440
|
+
pc += n;
|
|
441
|
+
|
|
442
|
+
for(i = 0; i < n; i++) {
|
|
443
|
+
val = pc1[i];
|
|
444
|
+
if (val >= s->capture_count)
|
|
445
|
+
goto no_match;
|
|
446
|
+
cptr1_start = capture[2 * val];
|
|
447
|
+
cptr1_end = capture[2 * val + 1];
|
|
448
|
+
/* test the first not empty capture */
|
|
449
|
+
if (cptr1_start && cptr1_end) {
|
|
450
|
+
if (opcode == REOP_back_reference ||
|
|
451
|
+
opcode == REOP_back_reference_i) {
|
|
452
|
+
cptr1 = cptr1_start;
|
|
453
|
+
while (cptr1 < cptr1_end) {
|
|
454
|
+
if (cptr >= cbuf_end)
|
|
455
|
+
goto no_match;
|
|
456
|
+
GET_CHAR(c1, cptr1, cptr1_end, cbuf_type);
|
|
457
|
+
GET_CHAR(c2, cptr, cbuf_end, cbuf_type);
|
|
458
|
+
if (opcode == REOP_back_reference_i) {
|
|
459
|
+
c1 = lre_canonicalize(c1, s->is_unicode);
|
|
460
|
+
c2 = lre_canonicalize(c2, s->is_unicode);
|
|
461
|
+
}
|
|
462
|
+
if (c1 != c2)
|
|
463
|
+
goto no_match;
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
cptr1 = cptr1_end;
|
|
467
|
+
while (cptr1 > cptr1_start) {
|
|
468
|
+
if (cptr == s->cbuf)
|
|
469
|
+
goto no_match;
|
|
470
|
+
GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type);
|
|
471
|
+
GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type);
|
|
472
|
+
if (opcode == REOP_backward_back_reference_i) {
|
|
473
|
+
c1 = lre_canonicalize(c1, s->is_unicode);
|
|
474
|
+
c2 = lre_canonicalize(c2, s->is_unicode);
|
|
475
|
+
}
|
|
476
|
+
if (c1 != c2)
|
|
477
|
+
goto no_match;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
BREAK;
|
|
485
|
+
CASE(REOP_range):
|
|
486
|
+
CASE(REOP_range_i):
|
|
487
|
+
{
|
|
488
|
+
int n;
|
|
489
|
+
uint32_t low, high, idx_min, idx_max, idx;
|
|
490
|
+
|
|
491
|
+
n = get_u16(pc); /* n must be >= 1 */
|
|
492
|
+
pc += 2;
|
|
493
|
+
if (cptr >= cbuf_end)
|
|
494
|
+
goto no_match;
|
|
495
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
496
|
+
if (opcode == REOP_range_i) {
|
|
497
|
+
c = lre_canonicalize(c, s->is_unicode);
|
|
498
|
+
}
|
|
499
|
+
idx_min = 0;
|
|
500
|
+
low = get_u16(pc + 0 * 4);
|
|
501
|
+
if (c < low)
|
|
502
|
+
goto no_match;
|
|
503
|
+
idx_max = n - 1;
|
|
504
|
+
high = get_u16(pc + idx_max * 4 + 2);
|
|
505
|
+
/* 0xffff in for last value means +infinity */
|
|
506
|
+
if (unlikely(c >= 0xffff) && high == 0xffff)
|
|
507
|
+
goto range_match;
|
|
508
|
+
if (c > high)
|
|
509
|
+
goto no_match;
|
|
510
|
+
while (idx_min <= idx_max) {
|
|
511
|
+
idx = (idx_min + idx_max) / 2;
|
|
512
|
+
low = get_u16(pc + idx * 4);
|
|
513
|
+
high = get_u16(pc + idx * 4 + 2);
|
|
514
|
+
if (c < low)
|
|
515
|
+
idx_max = idx - 1;
|
|
516
|
+
else if (c > high)
|
|
517
|
+
idx_min = idx + 1;
|
|
518
|
+
else
|
|
519
|
+
goto range_match;
|
|
520
|
+
}
|
|
521
|
+
goto no_match;
|
|
522
|
+
range_match:
|
|
523
|
+
pc += 4 * n;
|
|
524
|
+
}
|
|
525
|
+
BREAK;
|
|
526
|
+
CASE(REOP_range32):
|
|
527
|
+
CASE(REOP_range32_i):
|
|
528
|
+
{
|
|
529
|
+
int n;
|
|
530
|
+
uint32_t low, high, idx_min, idx_max, idx;
|
|
531
|
+
|
|
532
|
+
n = get_u16(pc); /* n must be >= 1 */
|
|
533
|
+
pc += 2;
|
|
534
|
+
if (cptr >= cbuf_end)
|
|
535
|
+
goto no_match;
|
|
536
|
+
GET_CHAR(c, cptr, cbuf_end, cbuf_type);
|
|
537
|
+
if (opcode == REOP_range32_i) {
|
|
538
|
+
c = lre_canonicalize(c, s->is_unicode);
|
|
539
|
+
}
|
|
540
|
+
idx_min = 0;
|
|
541
|
+
low = get_u32(pc + 0 * 8);
|
|
542
|
+
if (c < low)
|
|
543
|
+
goto no_match;
|
|
544
|
+
idx_max = n - 1;
|
|
545
|
+
high = get_u32(pc + idx_max * 8 + 4);
|
|
546
|
+
if (c > high)
|
|
547
|
+
goto no_match;
|
|
548
|
+
while (idx_min <= idx_max) {
|
|
549
|
+
idx = (idx_min + idx_max) / 2;
|
|
550
|
+
low = get_u32(pc + idx * 8);
|
|
551
|
+
high = get_u32(pc + idx * 8 + 4);
|
|
552
|
+
if (c < low)
|
|
553
|
+
idx_max = idx - 1;
|
|
554
|
+
else if (c > high)
|
|
555
|
+
idx_min = idx + 1;
|
|
556
|
+
else
|
|
557
|
+
goto range32_match;
|
|
558
|
+
}
|
|
559
|
+
goto no_match;
|
|
560
|
+
range32_match:
|
|
561
|
+
pc += 8 * n;
|
|
562
|
+
}
|
|
563
|
+
BREAK;
|
|
564
|
+
CASE(REOP_prev):
|
|
565
|
+
/* go to the previous char */
|
|
566
|
+
if (cptr == s->cbuf)
|
|
567
|
+
goto no_match;
|
|
568
|
+
PREV_CHAR(cptr, s->cbuf, cbuf_type);
|
|
569
|
+
BREAK;
|
|
570
|
+
CASE(REOP_invalid):
|
|
571
|
+
DEFAULT:
|
|
572
|
+
#ifdef DUMP_EXEC
|
|
573
|
+
printf("unknown opcode pc=%ld\n", (long)(pc - 1 - pc_start));
|
|
574
|
+
#endif
|
|
575
|
+
abort();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
#undef SWITCH
|
|
579
|
+
#undef CASE
|
|
580
|
+
#undef DEFAULT
|
|
581
|
+
#undef BREAK
|
|
582
|
+
#undef LRE_DUMP_OP
|
|
583
|
+
}
|