~pythonregexp2.7/python/issue2636-01+09-02+17+18+19+20+21+26

« back to all changes in this revision

Viewing changes to Modules/_sre.c

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-09-26 14:50:14 UTC
  • mfrom: (39047.2.1 Regexp-2.7)
  • Revision ID: darklord@timehorse.com-20080926145014-kf5v7xrxn97mtaz3
Merged in changes from the combined Atomic Grouping / Possessive Qualifiers, Matthew Barnett Engine, Variable Length Look-Behind and Reverse Match branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
 
49
49
#include <ctype.h>
50
50
 
 
51
#define UNLIMITED_REPEATS 0xFFFF
 
52
 
 
53
typedef struct SRE_OpInfo {
 
54
    int type;
 
55
    int direction;
 
56
    int end_marker;
 
57
} SRE_OpInfo;
 
58
 
 
59
#define SRE_TYPE_INVALID 0
 
60
#define SRE_TYPE_ASSERT 1
 
61
#define SRE_TYPE_ATOMIC 2
 
62
#define SRE_TYPE_BIGCHARSET 3
 
63
#define SRE_TYPE_BRANCH 4
 
64
#define SRE_TYPE_CATEGORY 5
 
65
#define SRE_TYPE_CHARSET 6
 
66
#define SRE_TYPE_GROUPREF 7
 
67
#define SRE_TYPE_GROUPREF_EXISTS 8
 
68
#define SRE_TYPE_IN 9
 
69
#define SRE_TYPE_LITERAL 10
 
70
#define SRE_TYPE_LITERAL_STRING 11
 
71
#define SRE_TYPE_MARK 12
 
72
#define SRE_TYPE_POSITION 13
 
73
#define SRE_TYPE_RANGE 14
 
74
#define SRE_TYPE_REPEAT 15
 
75
#define SRE_TYPE_REPEAT_ONE 16
 
76
 
 
77
static SRE_OpInfo op_info[] = {
 
78
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_FAILURE
 
79
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_SUCCESS
 
80
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_ANY
 
81
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_ANY_ALL
 
82
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_ANY_ALL_REV
 
83
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_ANY_REV
 
84
    {SRE_TYPE_ASSERT, 0, SRE_OP_END_ASSERT}, // SRE_OP_ASSERT
 
85
    {SRE_TYPE_ASSERT, 0, SRE_OP_END_ASSERT_NOT}, // SRE_OP_ASSERT_NOT
 
86
    {SRE_TYPE_ATOMIC, 0, SRE_OP_END_ATOMIC}, // SRE_OP_ATOMIC
 
87
    {SRE_TYPE_BIGCHARSET, 1, 0}, // SRE_OP_BIGCHARSET
 
88
    {SRE_TYPE_BIGCHARSET, 1, 0}, // SRE_OP_BIGCHARSET_IGNORE
 
89
    {SRE_TYPE_BIGCHARSET, -1, 0}, // SRE_OP_BIGCHARSET_IGNORE_REV
 
90
    {SRE_TYPE_BIGCHARSET, -1, 0}, // SRE_OP_BIGCHARSET_REV
 
91
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_BOUNDARY
 
92
    {SRE_TYPE_BRANCH, 0, 0}, // SRE_OP_BRANCH
 
93
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_CALL
 
94
    {SRE_TYPE_CHARSET, 1, 0}, // SRE_OP_CHARSET
 
95
    {SRE_TYPE_CHARSET, 1, 0}, // SRE_OP_CHARSET_IGNORE
 
96
    {SRE_TYPE_CHARSET, -1, 0}, // SRE_OP_CHARSET_IGNORE_REV
 
97
    {SRE_TYPE_CHARSET, -1, 0}, // SRE_OP_CHARSET_REV
 
98
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_DIGIT
 
99
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_DIGIT_REV
 
100
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_ASSERT
 
101
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_ASSERT_NOT
 
102
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_ATOMIC
 
103
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_END_OF_LINE
 
104
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_END_OF_STRING
 
105
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_END_OF_STRING_2
 
106
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_MAX
 
107
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_MAX_REV
 
108
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_MIN
 
109
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_MIN_REV
 
110
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_POSS
 
111
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_END_REPEAT_POSS_REV
 
112
    {SRE_TYPE_GROUPREF, 1, 0}, // SRE_OP_GROUPREF
 
113
    {SRE_TYPE_GROUPREF_EXISTS, 0, 0}, // SRE_OP_GROUPREF_EXISTS
 
114
    {SRE_TYPE_GROUPREF, 1, 0}, // SRE_OP_GROUPREF_IGNORE
 
115
    {SRE_TYPE_GROUPREF, -1, 0}, // SRE_OP_GROUPREF_IGNORE_REV
 
116
    {SRE_TYPE_GROUPREF, -1, 0}, // SRE_OP_GROUPREF_REV
 
117
    {SRE_TYPE_IN, 1, 0}, // SRE_OP_IN
 
118
    {SRE_TYPE_IN, 1, 0}, // SRE_OP_IN_IGNORE
 
119
    {SRE_TYPE_IN, -1, 0}, // SRE_OP_IN_IGNORE_REV
 
120
    {SRE_TYPE_IN, -1, 0}, // SRE_OP_IN_REV
 
121
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_JUMP
 
122
    {SRE_TYPE_LITERAL, 1, 0}, // SRE_OP_LITERAL
 
123
    {SRE_TYPE_LITERAL, 1, 0}, // SRE_OP_LITERAL_IGNORE
 
124
    {SRE_TYPE_LITERAL, -1, 0}, // SRE_OP_LITERAL_IGNORE_REV
 
125
    {SRE_TYPE_LITERAL, -1, 0}, // SRE_OP_LITERAL_REV
 
126
    {SRE_TYPE_LITERAL_STRING, 1, 0}, // SRE_OP_LITERAL_STRING
 
127
    {SRE_TYPE_LITERAL_STRING, 1, 0}, // SRE_OP_LITERAL_STRING_IGNORE
 
128
    {SRE_TYPE_LITERAL_STRING, -1, 0}, // SRE_OP_LITERAL_STRING_IGNORE_REV
 
129
    {SRE_TYPE_LITERAL_STRING, -1, 0}, // SRE_OP_LITERAL_STRING_REV
 
130
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_LOC_BOUNDARY
 
131
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_LOC_NOT_BOUNDARY
 
132
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_LOC_NOT_WORD
 
133
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_LOC_NOT_WORD_REV
 
134
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_LOC_WORD
 
135
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_LOC_WORD_REV
 
136
    {SRE_TYPE_MARK, 0, 0}, // SRE_OP_MARK
 
137
    {SRE_TYPE_BIGCHARSET, 1, 0}, // SRE_OP_NOT_BIGCHARSET
 
138
    {SRE_TYPE_BIGCHARSET, 1, 0}, // SRE_OP_NOT_BIGCHARSET_IGNORE
 
139
    {SRE_TYPE_BIGCHARSET, -1, 0}, // SRE_OP_NOT_BIGCHARSET_IGNORE_REV
 
140
    {SRE_TYPE_BIGCHARSET, -1, 0}, // SRE_OP_NOT_BIGCHARSET_REV
 
141
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_NOT_BOUNDARY
 
142
    {SRE_TYPE_CHARSET, 1, 0}, // SRE_OP_NOT_CHARSET
 
143
    {SRE_TYPE_CHARSET, 1, 0}, // SRE_OP_NOT_CHARSET_IGNORE
 
144
    {SRE_TYPE_CHARSET, -1, 0}, // SRE_OP_NOT_CHARSET_IGNORE_REV
 
145
    {SRE_TYPE_CHARSET, -1, 0}, // SRE_OP_NOT_CHARSET_REV
 
146
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_NOT_DIGIT
 
147
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_NOT_DIGIT_REV
 
148
    {SRE_TYPE_IN, 1, 0}, // SRE_OP_NOT_IN
 
149
    {SRE_TYPE_IN, 1, 0}, // SRE_OP_NOT_IN_IGNORE
 
150
    {SRE_TYPE_IN, -1, 0}, // SRE_OP_NOT_IN_IGNORE_REV
 
151
    {SRE_TYPE_IN, -1, 0}, // SRE_OP_NOT_IN_REV
 
152
    {SRE_TYPE_LITERAL, 1, 0}, // SRE_OP_NOT_LITERAL
 
153
    {SRE_TYPE_LITERAL, 1, 0}, // SRE_OP_NOT_LITERAL_IGNORE
 
154
    {SRE_TYPE_LITERAL, -1, 0}, // SRE_OP_NOT_LITERAL_IGNORE_REV
 
155
    {SRE_TYPE_LITERAL, -1, 0}, // SRE_OP_NOT_LITERAL_REV
 
156
    {SRE_TYPE_RANGE, 1, 0}, // SRE_OP_NOT_RANGE
 
157
    {SRE_TYPE_RANGE, 1, 0}, // SRE_OP_NOT_RANGE_IGNORE
 
158
    {SRE_TYPE_RANGE, -1, 0}, // SRE_OP_NOT_RANGE_IGNORE_REV
 
159
    {SRE_TYPE_RANGE, -1, 0}, // SRE_OP_NOT_RANGE_REV
 
160
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_NOT_WHITESPACE
 
161
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_NOT_WHITESPACE_REV
 
162
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_NOT_WORD
 
163
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_NOT_WORD_REV
 
164
    {SRE_TYPE_RANGE, 1, 0}, // SRE_OP_RANGE
 
165
    {SRE_TYPE_RANGE, 1, 0}, // SRE_OP_RANGE_IGNORE
 
166
    {SRE_TYPE_RANGE, -1, 0}, // SRE_OP_RANGE_IGNORE_REV
 
167
    {SRE_TYPE_RANGE, -1, 0}, // SRE_OP_RANGE_REV
 
168
    {SRE_TYPE_REPEAT, 1, SRE_OP_END_REPEAT_MAX}, // SRE_OP_REPEAT_MAX
 
169
    {SRE_TYPE_REPEAT, -1, SRE_OP_END_REPEAT_MAX_REV}, // SRE_OP_REPEAT_MAX_REV
 
170
    {SRE_TYPE_REPEAT, 1, SRE_OP_END_REPEAT_MIN}, // SRE_OP_REPEAT_MIN
 
171
    {SRE_TYPE_REPEAT, -1, SRE_OP_END_REPEAT_MIN_REV}, // SRE_OP_REPEAT_MIN_REV
 
172
    {SRE_TYPE_REPEAT_ONE, 1, 0}, // SRE_OP_REPEAT_ONE_MAX
 
173
    {SRE_TYPE_REPEAT_ONE, -1, 0}, // SRE_OP_REPEAT_ONE_MAX_REV
 
174
    {SRE_TYPE_REPEAT_ONE, 1, 0}, // SRE_OP_REPEAT_ONE_MIN
 
175
    {SRE_TYPE_REPEAT_ONE, -1, 0}, // SRE_OP_REPEAT_ONE_MIN_REV
 
176
    {SRE_TYPE_REPEAT_ONE, 1, 0}, // SRE_OP_REPEAT_ONE_POSS
 
177
    {SRE_TYPE_REPEAT_ONE, -1, 0}, // SRE_OP_REPEAT_ONE_POSS_REV
 
178
    {SRE_TYPE_REPEAT, 1, SRE_OP_END_REPEAT_POSS}, // SRE_OP_REPEAT_POSS
 
179
    {SRE_TYPE_REPEAT, -1, SRE_OP_END_REPEAT_POSS_REV}, // SRE_OP_REPEAT_POSS_REV
 
180
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_START_OF_LINE
 
181
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_START_OF_STRING
 
182
    {SRE_TYPE_INVALID, 0, 0}, // SRE_OP_SUBPATTERN
 
183
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_UNI_BOUNDARY
 
184
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_DIGIT
 
185
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_DIGIT_REV
 
186
    {SRE_TYPE_POSITION, 0, 0}, // SRE_OP_UNI_NOT_BOUNDARY
 
187
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_NOT_DIGIT
 
188
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_NOT_DIGIT_REV
 
189
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_NOT_WHITESPACE
 
190
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_NOT_WHITESPACE_REV
 
191
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_NOT_WORD
 
192
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_NOT_WORD_REV
 
193
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_WHITESPACE
 
194
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_WHITESPACE_REV
 
195
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_UNI_WORD
 
196
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_UNI_WORD_REV
 
197
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_WHITESPACE
 
198
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_WHITESPACE_REV
 
199
    {SRE_TYPE_CATEGORY, 1, 0}, // SRE_OP_WORD
 
200
    {SRE_TYPE_CATEGORY, -1, 0}, // SRE_OP_WORD_REV
 
201
};
 
202
 
51
203
/* name of this module, minus the leading underscore */
52
204
#if !defined(SRE_MODULE)
53
205
#define SRE_MODULE "sre"
68
220
/* -------------------------------------------------------------------- */
69
221
/* optional features */
70
222
 
71
 
/* enables fast searching */
72
 
#define USE_FAST_SEARCH
73
 
 
74
223
/* enables aggressive inlining (always on for Visual C) */
75
224
#undef USE_INLINE
76
225
 
94
243
#define LOCAL(type) static type
95
244
#endif
96
245
 
 
246
#ifdef Py_UNICODE_WIDE
 
247
#define SRE_BYTES_PER_CODE 4
 
248
#define SRE_BITES_PER_CODE 32
 
249
#else
 
250
#define SRE_BYTES_PER_CODE 2
 
251
#define SRE_BITS_PER_CODE 16
 
252
#endif
 
253
 
 
254
LOCAL(int) in_charset(SRE_CODE* charset, SRE_CODE ch) {
 
255
    return charset[ch / SRE_BITS_PER_CODE] & (1 << (ch % SRE_BITS_PER_CODE));
 
256
}
 
257
 
 
258
LOCAL(SRE_CODE*) skip_charset(SRE_CODE* charset) {
 
259
    return charset + 256 / SRE_BITS_PER_CODE;
 
260
}
 
261
 
 
262
LOCAL(int) in_bigcharset(SRE_CODE* charset, SRE_CODE ch) {
 
263
    int hi_byte = ch / 256;
 
264
    int lo_byte = ch % 256;
 
265
    int index;
 
266
    charset++;
 
267
    index = (charset[hi_byte / SRE_BYTES_PER_CODE] >> ((hi_byte % SRE_BYTES_PER_CODE) * 8)) & 0xFF;
 
268
    charset += 256 / SRE_BYTES_PER_CODE;
 
269
    return charset[lo_byte / SRE_BITS_PER_CODE] & (1 << (lo_byte % SRE_BITS_PER_CODE));
 
270
}
 
271
 
 
272
LOCAL(SRE_CODE*) skip_bigcharset(SRE_CODE* charset) {
 
273
    return charset + charset[0];
 
274
}
 
275
 
97
276
/* error codes */
98
277
#define SRE_ERROR_ILLEGAL -1 /* illegal opcode */
99
278
#define SRE_ERROR_STATE -2 /* illegal state */
113
292
/* default character predicates (run sre_chars.py to regenerate tables) */
114
293
 
115
294
#define SRE_DIGIT_MASK 1
116
 
#define SRE_SPACE_MASK 2
 
295
#define SRE_WHITESPACE_MASK 2
117
296
#define SRE_LINEBREAK_MASK 4
118
297
#define SRE_ALNUM_MASK 8
119
298
#define SRE_WORD_MASK 16
140
319
 
141
320
#define SRE_IS_DIGIT(ch)\
142
321
    ((ch) < 128 ? (sre_char_info[(ch)] & SRE_DIGIT_MASK) : 0)
143
 
#define SRE_IS_SPACE(ch)\
144
 
    ((ch) < 128 ? (sre_char_info[(ch)] & SRE_SPACE_MASK) : 0)
 
322
#define SRE_IS_WHITESPACE(ch)\
 
323
    ((ch) < 128 ? (sre_char_info[(ch)] & SRE_WHITESPACE_MASK) : 0)
145
324
#define SRE_IS_LINEBREAK(ch)\
146
325
    ((ch) < 128 ? (sre_char_info[(ch)] & SRE_LINEBREAK_MASK) : 0)
147
326
#define SRE_IS_ALNUM(ch)\
158
337
/* !(c & ~N) == (c < N+1) for any unsigned c, this avoids
159
338
 * warnings when c's type supports only numbers < N+1 */
160
339
#define SRE_LOC_IS_DIGIT(ch) (!((ch) & ~255) ? isdigit((ch)) : 0)
161
 
#define SRE_LOC_IS_SPACE(ch) (!((ch) & ~255) ? isspace((ch)) : 0)
 
340
#define SRE_LOC_IS_WHITESPACE(ch) (!((ch) & ~255) ? isspace((ch)) : 0)
162
341
#define SRE_LOC_IS_LINEBREAK(ch) ((ch) == '\n')
163
342
#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? isalnum((ch)) : 0)
164
343
#define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_')
173
352
#if defined(HAVE_UNICODE)
174
353
 
175
354
#define SRE_UNI_IS_DIGIT(ch) Py_UNICODE_ISDIGIT((Py_UNICODE)(ch))
176
 
#define SRE_UNI_IS_SPACE(ch) Py_UNICODE_ISSPACE((Py_UNICODE)(ch))
 
355
#define SRE_UNI_IS_WHITESPACE(ch) Py_UNICODE_ISSPACE((Py_UNICODE)(ch))
177
356
#define SRE_UNI_IS_LINEBREAK(ch) Py_UNICODE_ISLINEBREAK((Py_UNICODE)(ch))
178
357
#define SRE_UNI_IS_ALNUM(ch) Py_UNICODE_ISALNUM((Py_UNICODE)(ch))
179
358
#define SRE_UNI_IS_WORD(ch) (SRE_UNI_IS_ALNUM((ch)) || (ch) == '_')
185
364
 
186
365
#endif
187
366
 
188
 
LOCAL(int)
189
 
sre_category(SRE_CODE category, unsigned int ch)
190
 
{
191
 
    switch (category) {
192
 
 
193
 
    case SRE_CATEGORY_DIGIT:
194
 
        return SRE_IS_DIGIT(ch);
195
 
    case SRE_CATEGORY_NOT_DIGIT:
196
 
        return !SRE_IS_DIGIT(ch);
197
 
    case SRE_CATEGORY_SPACE:
198
 
        return SRE_IS_SPACE(ch);
199
 
    case SRE_CATEGORY_NOT_SPACE:
200
 
        return !SRE_IS_SPACE(ch);
201
 
    case SRE_CATEGORY_WORD:
202
 
        return SRE_IS_WORD(ch);
203
 
    case SRE_CATEGORY_NOT_WORD:
204
 
        return !SRE_IS_WORD(ch);
205
 
    case SRE_CATEGORY_LINEBREAK:
206
 
        return SRE_IS_LINEBREAK(ch);
207
 
    case SRE_CATEGORY_NOT_LINEBREAK:
208
 
        return !SRE_IS_LINEBREAK(ch);
209
 
 
210
 
    case SRE_CATEGORY_LOC_WORD:
211
 
        return SRE_LOC_IS_WORD(ch);
212
 
    case SRE_CATEGORY_LOC_NOT_WORD:
213
 
        return !SRE_LOC_IS_WORD(ch);
214
 
 
215
 
#if defined(HAVE_UNICODE)
216
 
    case SRE_CATEGORY_UNI_DIGIT:
217
 
        return SRE_UNI_IS_DIGIT(ch);
218
 
    case SRE_CATEGORY_UNI_NOT_DIGIT:
219
 
        return !SRE_UNI_IS_DIGIT(ch);
220
 
    case SRE_CATEGORY_UNI_SPACE:
221
 
        return SRE_UNI_IS_SPACE(ch);
222
 
    case SRE_CATEGORY_UNI_NOT_SPACE:
223
 
        return !SRE_UNI_IS_SPACE(ch);
224
 
    case SRE_CATEGORY_UNI_WORD:
225
 
        return SRE_UNI_IS_WORD(ch);
226
 
    case SRE_CATEGORY_UNI_NOT_WORD:
227
 
        return !SRE_UNI_IS_WORD(ch);
228
 
    case SRE_CATEGORY_UNI_LINEBREAK:
229
 
        return SRE_UNI_IS_LINEBREAK(ch);
230
 
    case SRE_CATEGORY_UNI_NOT_LINEBREAK:
231
 
        return !SRE_UNI_IS_LINEBREAK(ch);
232
 
#else
233
 
    case SRE_CATEGORY_UNI_DIGIT:
234
 
        return SRE_IS_DIGIT(ch);
235
 
    case SRE_CATEGORY_UNI_NOT_DIGIT:
236
 
        return !SRE_IS_DIGIT(ch);
237
 
    case SRE_CATEGORY_UNI_SPACE:
238
 
        return SRE_IS_SPACE(ch);
239
 
    case SRE_CATEGORY_UNI_NOT_SPACE:
240
 
        return !SRE_IS_SPACE(ch);
241
 
    case SRE_CATEGORY_UNI_WORD:
242
 
        return SRE_LOC_IS_WORD(ch);
243
 
    case SRE_CATEGORY_UNI_NOT_WORD:
244
 
        return !SRE_LOC_IS_WORD(ch);
245
 
    case SRE_CATEGORY_UNI_LINEBREAK:
246
 
        return SRE_IS_LINEBREAK(ch);
247
 
    case SRE_CATEGORY_UNI_NOT_LINEBREAK:
248
 
        return !SRE_IS_LINEBREAK(ch);
249
 
#endif
250
 
    }
251
 
    return 0;
252
 
}
253
 
 
254
 
/* helpers */
255
 
 
256
 
static void
257
 
data_stack_dealloc(SRE_STATE* state)
258
 
{
259
 
    if (state->data_stack) {
260
 
        PyMem_FREE(state->data_stack);
261
 
        state->data_stack = NULL;
262
 
    }
263
 
    state->data_stack_size = state->data_stack_base = 0;
264
 
}
265
 
 
266
 
static int
267
 
data_stack_grow(SRE_STATE* state, Py_ssize_t size)
268
 
{
269
 
    Py_ssize_t minsize, cursize;
270
 
    minsize = state->data_stack_base+size;
271
 
    cursize = state->data_stack_size;
272
 
    if (cursize < minsize) {
273
 
        void* stack;
274
 
        cursize = minsize+minsize/4+1024;
275
 
        TRACE(("allocate/grow stack %d\n", cursize));
276
 
        stack = PyMem_REALLOC(state->data_stack, cursize);
277
 
        if (!stack) {
278
 
            data_stack_dealloc(state);
279
 
            return SRE_ERROR_MEMORY;
280
 
        }
281
 
        state->data_stack = (char *)stack;
282
 
        state->data_stack_size = cursize;
283
 
    }
284
 
    return 0;
 
367
LOCAL(int) sre_repeat_limit(int repeats, int limit) {
 
368
    if (repeats > limit || repeats == UNLIMITED_REPEATS)
 
369
        return limit;
 
370
    return repeats;
285
371
}
286
372
 
287
373
/* generate 8-bit version */
288
374
 
289
375
#define SRE_CHAR unsigned char
290
 
#define SRE_AT sre_at
291
 
#define SRE_COUNT sre_count
292
 
#define SRE_CHARSET sre_charset
293
 
#define SRE_INFO sre_info
 
376
#define SRE_IN sre_in
294
377
#define SRE_MATCH sre_match
295
 
#define SRE_MATCH_CONTEXT sre_match_context
296
378
#define SRE_SEARCH sre_search
297
379
#define SRE_LITERAL_TEMPLATE sre_literal_template
 
380
#define SRE_IN_RANGE sre_in_range
 
381
#define SRE_AT_BOUNDARY sre_at_boundary
 
382
#define SRE_LOC_AT_BOUNDARY sre_loc_at_boundary
 
383
#define SRE_UNI_AT_BOUNDARY sre_uni_at_boundary
 
384
#define SRE_CONTEXT sre_context
 
385
#define SRE_SAVE_BACKTRACK sre_save_backtrack
 
386
#define SRE_DISCARD_BACKTRACK sre_discard_backtrack
 
387
#define SRE_SAVE_MARKS sre_save_marks
 
388
#define SRE_RESTORE_MARKS sre_restore_marks
 
389
#define SRE_DISCARD_SAVED_MARKS sre_discard_saved_marks
 
390
#define SRE_DISCARD_UNTIL_OP sre_discard_until_op
 
391
#define SRE_CLEANUP sre_cleanup
 
392
#define SRE_LOOK_AHEAD_ONE sre_look_ahead_one
 
393
#define SRE_LOOK_AHEAD_ONE_REV sre_look_ahead_one_rev
 
394
#define SRE_LOOK_AHEAD_MANY sre_look_ahead_many
 
395
#define SRE_LOOK_AHEAD_MANY_REV sre_look_ahead_many_rev
 
396
#define SRE_LOOK_LITERAL sre_look_literal
298
397
 
299
398
#if defined(HAVE_UNICODE)
300
399
 
301
400
#define SRE_RECURSIVE
302
401
#include "_sre.c"
 
402
#undef SRE_LOOK_LITERAL
 
403
#undef SRE_LOOK_AHEAD_MANY_REV
 
404
#undef SRE_LOOK_AHEAD_MANY
 
405
#undef SRE_LOOK_AHEAD_ONE_REV
 
406
#undef SRE_LOOK_AHEAD_ONE
 
407
#undef SRE_CLEANUP
 
408
#undef SRE_DISCARD_UNTIL_OP
 
409
#undef SRE_DISCARD_SAVED_MARKS
 
410
#undef SRE_RESTORE_MARKS
 
411
#undef SRE_SAVE_MARKS
 
412
#undef SRE_DISCARD_BACKTRACK
 
413
#undef SRE_SAVE_BACKTRACK
 
414
#undef SRE_CONTEXT
303
415
#undef SRE_RECURSIVE
304
 
 
 
416
#undef SRE_UNI_AT_BOUNDARY
 
417
#undef SRE_LOC_AT_BOUNDARY
 
418
#undef SRE_AT_BOUNDARY
 
419
#undef SRE_IN_RANGE
305
420
#undef SRE_LITERAL_TEMPLATE
306
421
#undef SRE_SEARCH
307
422
#undef SRE_MATCH
308
 
#undef SRE_MATCH_CONTEXT
309
 
#undef SRE_INFO
310
 
#undef SRE_CHARSET
311
 
#undef SRE_COUNT
312
 
#undef SRE_AT
 
423
#undef SRE_IN
313
424
#undef SRE_CHAR
314
425
 
315
426
/* generate 16-bit unicode version */
316
427
 
317
428
#define SRE_CHAR Py_UNICODE
318
 
#define SRE_AT sre_uat
319
 
#define SRE_COUNT sre_ucount
320
 
#define SRE_CHARSET sre_ucharset
321
 
#define SRE_INFO sre_uinfo
 
429
#define SRE_IN sre_uin
322
430
#define SRE_MATCH sre_umatch
323
 
#define SRE_MATCH_CONTEXT sre_umatch_context
324
431
#define SRE_SEARCH sre_usearch
325
432
#define SRE_LITERAL_TEMPLATE sre_uliteral_template
 
433
#define SRE_IN_RANGE sre_uin_range
 
434
#define SRE_AT_BOUNDARY sre_uat_boundary
 
435
#define SRE_LOC_AT_BOUNDARY sre_uloc_at_boundary
 
436
#define SRE_UNI_AT_BOUNDARY sre_uuni_at_boundary
 
437
#define SRE_CONTEXT sre_ucontext
 
438
#define SRE_SAVE_BACKTRACK sre_usave_backtrack
 
439
#define SRE_DISCARD_BACKTRACK sre_udiscard_backtrack
 
440
#define SRE_SAVE_MARKS sre_usave_marks
 
441
#define SRE_RESTORE_MARKS sre_urestore_marks
 
442
#define SRE_DISCARD_SAVED_MARKS sre_udiscard_saved_marks
 
443
#define SRE_DISCARD_UNTIL_OP sre_udiscard_until_op
 
444
#define SRE_CLEANUP sre_ucleanup
 
445
#define SRE_LOOK_AHEAD_ONE sre_ulook_ahead_one
 
446
#define SRE_LOOK_AHEAD_ONE_REV sre_ulook_ahead_one_rev
 
447
#define SRE_LOOK_AHEAD_MANY sre_ulook_ahead_many
 
448
#define SRE_LOOK_AHEAD_MANY_REV sre_ulook_ahead_many_rev
 
449
#define SRE_LOOK_LITERAL sre_ulook_literal
326
450
#endif
327
451
 
328
452
#endif /* SRE_RECURSIVE */
333
457
/* the following section is compiled twice, with different character
334
458
   settings */
335
459
 
336
 
LOCAL(int)
337
 
SRE_AT(SRE_STATE* state, SRE_CHAR* ptr, SRE_CODE at)
338
 
{
339
 
    /* check if pointer is at given position */
340
 
 
341
 
    Py_ssize_t thisp, thatp;
342
 
 
343
 
    switch (at) {
344
 
 
345
 
    case SRE_AT_BEGINNING:
346
 
    case SRE_AT_BEGINNING_STRING:
347
 
        return ((void*) ptr == state->beginning);
348
 
 
349
 
    case SRE_AT_BEGINNING_LINE:
350
 
        return ((void*) ptr == state->beginning ||
351
 
                SRE_IS_LINEBREAK((int) ptr[-1]));
352
 
 
353
 
    case SRE_AT_END:
354
 
        return (((void*) (ptr+1) == state->end &&
355
 
                 SRE_IS_LINEBREAK((int) ptr[0])) ||
356
 
                ((void*) ptr == state->end));
357
 
 
358
 
    case SRE_AT_END_LINE:
359
 
        return ((void*) ptr == state->end ||
360
 
                SRE_IS_LINEBREAK((int) ptr[0]));
361
 
 
362
 
    case SRE_AT_END_STRING:
363
 
        return ((void*) ptr == state->end);
364
 
 
365
 
    case SRE_AT_BOUNDARY:
366
 
        if (state->beginning == state->end)
367
 
            return 0;
368
 
        thatp = ((void*) ptr > state->beginning) ?
369
 
            SRE_IS_WORD((int) ptr[-1]) : 0;
370
 
        thisp = ((void*) ptr < state->end) ?
371
 
            SRE_IS_WORD((int) ptr[0]) : 0;
372
 
        return thisp != thatp;
373
 
 
374
 
    case SRE_AT_NON_BOUNDARY:
375
 
        if (state->beginning == state->end)
376
 
            return 0;
377
 
        thatp = ((void*) ptr > state->beginning) ?
378
 
            SRE_IS_WORD((int) ptr[-1]) : 0;
379
 
        thisp = ((void*) ptr < state->end) ?
380
 
            SRE_IS_WORD((int) ptr[0]) : 0;
381
 
        return thisp == thatp;
382
 
 
383
 
    case SRE_AT_LOC_BOUNDARY:
384
 
        if (state->beginning == state->end)
385
 
            return 0;
386
 
        thatp = ((void*) ptr > state->beginning) ?
387
 
            SRE_LOC_IS_WORD((int) ptr[-1]) : 0;
388
 
        thisp = ((void*) ptr < state->end) ?
389
 
            SRE_LOC_IS_WORD((int) ptr[0]) : 0;
390
 
        return thisp != thatp;
391
 
 
392
 
    case SRE_AT_LOC_NON_BOUNDARY:
393
 
        if (state->beginning == state->end)
394
 
            return 0;
395
 
        thatp = ((void*) ptr > state->beginning) ?
396
 
            SRE_LOC_IS_WORD((int) ptr[-1]) : 0;
397
 
        thisp = ((void*) ptr < state->end) ?
398
 
            SRE_LOC_IS_WORD((int) ptr[0]) : 0;
399
 
        return thisp == thatp;
400
 
 
401
 
#if defined(HAVE_UNICODE)
402
 
    case SRE_AT_UNI_BOUNDARY:
403
 
        if (state->beginning == state->end)
404
 
            return 0;
405
 
        thatp = ((void*) ptr > state->beginning) ?
406
 
            SRE_UNI_IS_WORD((int) ptr[-1]) : 0;
407
 
        thisp = ((void*) ptr < state->end) ?
408
 
            SRE_UNI_IS_WORD((int) ptr[0]) : 0;
409
 
        return thisp != thatp;
410
 
 
411
 
    case SRE_AT_UNI_NON_BOUNDARY:
412
 
        if (state->beginning == state->end)
413
 
            return 0;
414
 
        thatp = ((void*) ptr > state->beginning) ?
415
 
            SRE_UNI_IS_WORD((int) ptr[-1]) : 0;
416
 
        thisp = ((void*) ptr < state->end) ?
417
 
            SRE_UNI_IS_WORD((int) ptr[0]) : 0;
418
 
        return thisp == thatp;
419
 
#endif
420
 
 
421
 
    }
422
 
 
423
 
    return 0;
 
460
LOCAL(int) SRE_IN_RANGE(SRE_CODE ch, SRE_CODE lower, SRE_CODE upper) {
 
461
    return lower <= ch && ch <= upper;
424
462
}
425
463
 
426
 
LOCAL(int)
427
 
SRE_CHARSET(SRE_CODE* set, SRE_CODE ch)
428
 
{
429
 
    /* check if character is a member of the given set */
430
 
 
431
 
    int ok = 1;
432
 
 
433
 
    for (;;) {
434
 
        switch (*set++) {
435
 
 
436
 
        case SRE_OP_FAILURE:
437
 
            return !ok;
438
 
 
 
464
LOCAL(int) SRE_IN(SRE_CODE* charset, SRE_CODE ch) {
 
465
    // Check if character is a member of the given set.
 
466
    SRE_CODE* charset_end = charset + charset[0];
 
467
 
 
468
    charset++;
 
469
 
 
470
    do {
 
471
        switch (*charset++) {
 
472
        case SRE_OP_BIGCHARSET:
 
473
            // <BIGCHARSET> <set>
 
474
            if (in_bigcharset(charset, ch))
 
475
                return 1;
 
476
            charset = skip_bigcharset(charset);
 
477
            break;
 
478
        case SRE_OP_CHARSET:
 
479
            // <CHARSET> <set>
 
480
            if (in_charset(charset, ch))
 
481
                return 1;
 
482
            charset = skip_charset(charset);
 
483
            break;
 
484
        case SRE_OP_DIGIT:
 
485
            // <DIGIT>
 
486
            if (SRE_IS_DIGIT(ch))
 
487
                return 1;
 
488
            break;
439
489
        case SRE_OP_LITERAL:
440
 
            /* <LITERAL> <code> */
441
 
            if (ch == set[0])
442
 
                return ok;
443
 
            set++;
444
 
            break;
445
 
 
446
 
        case SRE_OP_CATEGORY:
447
 
            /* <CATEGORY> <code> */
448
 
            if (sre_category(set[0], (int) ch))
449
 
                return ok;
450
 
            set += 1;
451
 
            break;
452
 
 
453
 
        case SRE_OP_CHARSET:
454
 
            if (sizeof(SRE_CODE) == 2) {
455
 
                /* <CHARSET> <bitmap> (16 bits per code word) */
456
 
                if (ch < 256 && (set[ch >> 4] & (1 << (ch & 15))))
457
 
                    return ok;
458
 
                set += 16;
459
 
            }
460
 
            else {
461
 
                /* <CHARSET> <bitmap> (32 bits per code word) */
462
 
                if (ch < 256 && (set[ch >> 5] & (1 << (ch & 31))))
463
 
                    return ok;
464
 
                set += 8;
465
 
            }
466
 
            break;
467
 
 
 
490
            // <LITERAL> <code>
 
491
            if (ch == charset[0])
 
492
                return 1;
 
493
            charset++;
 
494
            break;
 
495
        case SRE_OP_LOC_NOT_WORD:
 
496
            // <LOC_NOT_WORD>
 
497
            if (! SRE_LOC_IS_WORD(ch))
 
498
                return 1;
 
499
            break;
 
500
        case SRE_OP_LOC_WORD:
 
501
            // <LOC_WORD>
 
502
            if (SRE_LOC_IS_WORD(ch))
 
503
                return 1;
 
504
            break;
 
505
        case SRE_OP_NOT_DIGIT:
 
506
            // <NOT_DIGIT>
 
507
            if (!SRE_IS_DIGIT(ch))
 
508
                return 1;
 
509
            break;
 
510
        case SRE_OP_NOT_LITERAL:
 
511
            // <NOT_LITERAL> <code>
 
512
            if (ch != charset[0])
 
513
                return 1;
 
514
            charset++;
 
515
            break;
 
516
        case SRE_OP_NOT_WHITESPACE:
 
517
            // <NOT_WHITESPACE>
 
518
            if (!SRE_IS_WHITESPACE(ch))
 
519
                return 1;
 
520
            break;
 
521
        case SRE_OP_NOT_WORD:
 
522
            // <NOT_WORD>
 
523
            if (! SRE_IS_WORD(ch))
 
524
                return 1;
 
525
            break;
468
526
        case SRE_OP_RANGE:
469
 
            /* <RANGE> <lower> <upper> */
470
 
            if (set[0] <= ch && ch <= set[1])
471
 
                return ok;
472
 
            set += 2;
473
 
            break;
474
 
 
475
 
        case SRE_OP_NEGATE:
476
 
            ok = !ok;
477
 
            break;
478
 
 
479
 
        case SRE_OP_BIGCHARSET:
480
 
            /* <BIGCHARSET> <blockcount> <256 blockindices> <blocks> */
481
 
        {
482
 
            Py_ssize_t count, block;
483
 
            count = *(set++);
484
 
 
485
 
            if (sizeof(SRE_CODE) == 2) {
486
 
                block = ((unsigned char*)set)[ch >> 8];
487
 
                set += 128;
488
 
                if (set[block*16 + ((ch & 255)>>4)] & (1 << (ch & 15)))
489
 
                    return ok;
490
 
                set += count*16;
491
 
            }
492
 
            else {
493
 
                /* !(c & ~N) == (c < N+1) for any unsigned c, this avoids
494
 
                 * warnings when c's type supports only numbers < N+1 */
495
 
                if (!(ch & ~65535))
496
 
                    block = ((unsigned char*)set)[ch >> 8];
497
 
                else
498
 
                    block = -1;
499
 
                set += 64;
500
 
                if (block >=0 &&
501
 
                    (set[block*8 + ((ch & 255)>>5)] & (1 << (ch & 31))))
502
 
                    return ok;
503
 
                set += count*8;
504
 
            }
505
 
            break;
506
 
        }
507
 
 
 
527
            // <RANGE> <lower> <upper>
 
528
            if (SRE_IN_RANGE(ch, charset[0], charset[1]))
 
529
                return 1;
 
530
            charset += 2;
 
531
            break;
 
532
        case SRE_OP_UNI_DIGIT:
 
533
            // <UNI_DIGIT>
 
534
            if (SRE_UNI_IS_DIGIT(ch))
 
535
                return 1;
 
536
            break;
 
537
        case SRE_OP_UNI_NOT_DIGIT:
 
538
            // <UNI_NOT_DIGIT>
 
539
            if (!SRE_UNI_IS_DIGIT(ch))
 
540
                return 1;
 
541
            break;
 
542
        case SRE_OP_UNI_NOT_WHITESPACE:
 
543
            // <UNI_NOT_WHITESPACE>
 
544
            if (! SRE_UNI_IS_WHITESPACE(ch))
 
545
                return 1;
 
546
            break;
 
547
        case SRE_OP_UNI_NOT_WORD:
 
548
            // <UNI_NOT_WORD>
 
549
            if (! SRE_UNI_IS_WORD(ch))
 
550
                return 1;
 
551
            break;
 
552
        case SRE_OP_UNI_WHITESPACE:
 
553
            // <UNI_WHITESPACE>
 
554
            if (SRE_UNI_IS_WHITESPACE(ch))
 
555
                return 1;
 
556
            break;
 
557
        case SRE_OP_UNI_WORD:
 
558
            // <UNI_WORD>
 
559
            if (SRE_UNI_IS_WORD(ch))
 
560
                return 1;
 
561
            break;
 
562
        case SRE_OP_WHITESPACE:
 
563
            // <WHITESPACE>
 
564
            if (SRE_IS_WHITESPACE(ch))
 
565
                return 1;
 
566
            break;
 
567
        case SRE_OP_WORD:
 
568
            // <WORD>
 
569
            if (SRE_IS_WORD(ch))
 
570
                return 1;
 
571
            break;
508
572
        default:
509
573
            /* internal error -- there's not much we can do about it
510
574
               here, so let's just pretend it didn't match... */
511
575
            return 0;
512
576
        }
513
 
    }
514
 
}
515
 
 
516
 
LOCAL(Py_ssize_t) SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern);
517
 
 
518
 
LOCAL(Py_ssize_t)
519
 
SRE_COUNT(SRE_STATE* state, SRE_CODE* pattern, Py_ssize_t maxcount)
520
 
{
521
 
    SRE_CODE chr;
522
 
    SRE_CHAR* ptr = (SRE_CHAR *)state->ptr;
523
 
    SRE_CHAR* end = (SRE_CHAR *)state->end;
524
 
    Py_ssize_t i;
525
 
 
526
 
    /* adjust end */
527
 
    if (maxcount < end - ptr && maxcount != 65535)
528
 
        end = ptr + maxcount;
529
 
 
530
 
    switch (pattern[0]) {
531
 
 
532
 
    case SRE_OP_IN:
533
 
        /* repeated set */
534
 
        TRACE(("|%p|%p|COUNT IN\n", pattern, ptr));
535
 
        while (ptr < end && SRE_CHARSET(pattern + 2, *ptr))
536
 
            ptr++;
537
 
        break;
538
 
 
539
 
    case SRE_OP_ANY:
540
 
        /* repeated dot wildcard. */
541
 
        TRACE(("|%p|%p|COUNT ANY\n", pattern, ptr));
542
 
        while (ptr < end && !SRE_IS_LINEBREAK(*ptr))
543
 
            ptr++;
544
 
        break;
545
 
 
546
 
    case SRE_OP_ANY_ALL:
547
 
        /* repeated dot wildcard.  skip to the end of the target
548
 
           string, and backtrack from there */
549
 
        TRACE(("|%p|%p|COUNT ANY_ALL\n", pattern, ptr));
550
 
        ptr = end;
551
 
        break;
552
 
 
553
 
    case SRE_OP_LITERAL:
554
 
        /* repeated literal */
555
 
        chr = pattern[1];
556
 
        TRACE(("|%p|%p|COUNT LITERAL %d\n", pattern, ptr, chr));
557
 
        while (ptr < end && (SRE_CODE) *ptr == chr)
558
 
            ptr++;
559
 
        break;
560
 
 
561
 
    case SRE_OP_LITERAL_IGNORE:
562
 
        /* repeated literal */
563
 
        chr = pattern[1];
564
 
        TRACE(("|%p|%p|COUNT LITERAL_IGNORE %d\n", pattern, ptr, chr));
565
 
        while (ptr < end && (SRE_CODE) state->lower(*ptr) == chr)
566
 
            ptr++;
567
 
        break;
568
 
 
569
 
    case SRE_OP_NOT_LITERAL:
570
 
        /* repeated non-literal */
571
 
        chr = pattern[1];
572
 
        TRACE(("|%p|%p|COUNT NOT_LITERAL %d\n", pattern, ptr, chr));
573
 
        while (ptr < end && (SRE_CODE) *ptr != chr)
574
 
            ptr++;
575
 
        break;
576
 
 
577
 
    case SRE_OP_NOT_LITERAL_IGNORE:
578
 
        /* repeated non-literal */
579
 
        chr = pattern[1];
580
 
        TRACE(("|%p|%p|COUNT NOT_LITERAL_IGNORE %d\n", pattern, ptr, chr));
581
 
        while (ptr < end && (SRE_CODE) state->lower(*ptr) != chr)
582
 
            ptr++;
583
 
        break;
584
 
 
585
 
    default:
586
 
        /* repeated single character pattern */
587
 
        TRACE(("|%p|%p|COUNT SUBPATTERN\n", pattern, ptr));
588
 
        while ((SRE_CHAR*) state->ptr < end) {
589
 
            i = SRE_MATCH(state, pattern);
590
 
            if (i < 0)
591
 
                return i;
592
 
            if (!i)
593
 
                break;
 
577
    } while (charset < charset_end);
 
578
 
 
579
    return 0;
 
580
}
 
581
 
 
582
typedef struct SRE_CONTEXT {
 
583
    SRE_CHAR* text_ptr;
 
584
    SRE_CHAR* text_start;
 
585
    SRE_CHAR* text_end;
 
586
    SRE_CHAR* final_linebreak;
 
587
    SRE_CODE* pattern_ptr;
 
588
    int* repeat_counter;
 
589
    SRE_CHAR** repeat_start;
 
590
    SRE_CHAR** mark;
 
591
    int mark_count;
 
592
    SRE_BACKTRACK_CHUNK* backtrack_chunk;
 
593
    SRE_SAVED_MARKS_CHUNK* saved_marks_chunk;
 
594
} SRE_CONTEXT;
 
595
 
 
596
LOCAL(int) SRE_CLEANUP(SRE_CONTEXT* context, SRE_STATE* state, int result) {
 
597
    while (context->backtrack_chunk->previous != NULL) {
 
598
        SRE_BACKTRACK_CHUNK* previous = context->backtrack_chunk->previous;
 
599
        PyMem_FREE(context->backtrack_chunk);
 
600
        context->backtrack_chunk = previous;
 
601
    }
 
602
    context->backtrack_chunk->count = 0;
 
603
 
 
604
    while (context->saved_marks_chunk->previous != NULL) {
 
605
        SRE_SAVED_MARKS_CHUNK* previous = context->saved_marks_chunk->previous;
 
606
        PyMem_FREE(context->saved_marks_chunk);
 
607
        context->saved_marks_chunk = previous;
 
608
    }
 
609
    context->saved_marks_chunk->count = 0;
 
610
 
 
611
    state->backtrack_chunk = context->backtrack_chunk;
 
612
    state->saved_marks_chunk = context->saved_marks_chunk;
 
613
 
 
614
    return result;
 
615
}
 
616
 
 
617
LOCAL(int) SRE_SAVE_BACKTRACK(SRE_CONTEXT* context, int op, SRE_CODE* pattern_ptr, int index) {
 
618
    SRE_BACKTRACK_ITEM* backtrack_item;
 
619
 
 
620
    if (context->backtrack_chunk->count >= SRE_BACKTRACK_CHUNK_SIZE) {
 
621
        SRE_BACKTRACK_CHUNK* new_backtrack_chunk = (SRE_BACKTRACK_CHUNK*)PyMem_MALLOC(sizeof(SRE_BACKTRACK_CHUNK));
 
622
        if (new_backtrack_chunk == NULL)
 
623
            return SRE_ERROR_MEMORY;
 
624
 
 
625
        new_backtrack_chunk->previous = context->backtrack_chunk;
 
626
        new_backtrack_chunk->count = 0;
 
627
        context->backtrack_chunk = new_backtrack_chunk;
 
628
    }
 
629
 
 
630
    backtrack_item = &context->backtrack_chunk->items[context->backtrack_chunk->count++];
 
631
    backtrack_item->op = op;
 
632
    backtrack_item->pattern_ptr = pattern_ptr;
 
633
    backtrack_item->text_ptr = context->text_ptr;
 
634
    backtrack_item->index = index;
 
635
    backtrack_item->repeat_counter = context->repeat_counter[index];
 
636
    backtrack_item->repeat_start = context->repeat_start[index];
 
637
 
 
638
    return 0;
 
639
}
 
640
 
 
641
LOCAL(void) SRE_DISCARD_BACKTRACK(SRE_CONTEXT* context) {
 
642
    SRE_BACKTRACK_ITEM* backtrack_item = &context->backtrack_chunk->items[--context->backtrack_chunk->count];
 
643
    if (backtrack_item->index >= 0) {
 
644
        context->repeat_counter[backtrack_item->index] = backtrack_item->repeat_counter;
 
645
        context->repeat_start[backtrack_item->index] = backtrack_item->repeat_start;
 
646
    }
 
647
 
 
648
    if (context->backtrack_chunk->count == 0 && context->backtrack_chunk->previous != NULL) {
 
649
        SRE_BACKTRACK_CHUNK* previous = context->backtrack_chunk->previous;
 
650
        PyMem_FREE(context->backtrack_chunk);
 
651
        context->backtrack_chunk = previous;
 
652
    }
 
653
}
 
654
 
 
655
LOCAL(int) SRE_SAVE_MARKS(SRE_CONTEXT* context) {
 
656
    if (context->saved_marks_chunk->count + context->mark_count > SRE_SAVED_MARKS_CHUNK_SIZE) {
 
657
        SRE_SAVED_MARKS_CHUNK* new_marks_chunk = (SRE_SAVED_MARKS_CHUNK*)PyMem_MALLOC(sizeof(SRE_SAVED_MARKS_CHUNK));
 
658
        if (new_marks_chunk == NULL)
 
659
            return SRE_ERROR_MEMORY;
 
660
 
 
661
        new_marks_chunk->previous = context->saved_marks_chunk;
 
662
        new_marks_chunk->count = 0;
 
663
        context->saved_marks_chunk = new_marks_chunk;
 
664
    }
 
665
 
 
666
    memmove(&context->saved_marks_chunk->marks[context->saved_marks_chunk->count], context->mark, context->mark_count * sizeof(SRE_CHAR*));
 
667
    context->saved_marks_chunk->count += context->mark_count;
 
668
 
 
669
    return 0;
 
670
}
 
671
 
 
672
LOCAL(void) SRE_RESTORE_MARKS(SRE_CONTEXT* context) {
 
673
    context->saved_marks_chunk->count -= context->mark_count;
 
674
    memmove(context->mark, &context->saved_marks_chunk->marks[context->saved_marks_chunk->count], context->mark_count * sizeof(SRE_CHAR*));
 
675
 
 
676
    if (context->saved_marks_chunk->count == 0 && context->saved_marks_chunk->previous != NULL) {
 
677
        SRE_SAVED_MARKS_CHUNK* previous = context->saved_marks_chunk->previous;
 
678
        PyMem_FREE(context->saved_marks_chunk);
 
679
        context->saved_marks_chunk = previous;
 
680
    }
 
681
}
 
682
 
 
683
LOCAL(void) SRE_DISCARD_SAVED_MARKS(SRE_CONTEXT* context) {
 
684
    context->saved_marks_chunk->count -= context->mark_count;
 
685
 
 
686
    if (context->saved_marks_chunk->count == 0 && context->saved_marks_chunk->previous != NULL) {
 
687
        SRE_SAVED_MARKS_CHUNK* previous = context->saved_marks_chunk->previous;
 
688
        PyMem_FREE(context->saved_marks_chunk);
 
689
        context->saved_marks_chunk = previous;
 
690
    }
 
691
}
 
692
 
 
693
LOCAL(void) SRE_DISCARD_UNTIL_OP(SRE_CONTEXT* context, int op) {
 
694
    for (;;) {
 
695
        SRE_BACKTRACK_ITEM* backtrack_item = &context->backtrack_chunk->items[context->backtrack_chunk->count - 1];
 
696
        if (backtrack_item->op == op)
 
697
            break;
 
698
 
 
699
        switch(backtrack_item->op) {
 
700
        case SRE_OP_BRANCH:
 
701
        case SRE_OP_END_REPEAT_MAX:
 
702
        case SRE_OP_END_REPEAT_MAX_REV:
 
703
        case SRE_OP_END_REPEAT_MIN:
 
704
        case SRE_OP_END_REPEAT_MIN_REV:
 
705
        case SRE_OP_END_REPEAT_POSS:
 
706
        case SRE_OP_END_REPEAT_POSS_REV:
 
707
        case SRE_OP_REPEAT_MAX:
 
708
        case SRE_OP_REPEAT_MAX_REV:
 
709
        case SRE_OP_REPEAT_MIN:
 
710
        case SRE_OP_REPEAT_MIN_REV:
 
711
        case SRE_OP_REPEAT_POSS:
 
712
        case SRE_OP_REPEAT_POSS_REV:
 
713
            SRE_DISCARD_SAVED_MARKS(context);
 
714
            break;
594
715
        }
595
 
        TRACE(("|%p|%p|COUNT %d\n", pattern, ptr,
596
 
               (SRE_CHAR*) state->ptr - ptr));
597
 
        return (SRE_CHAR*) state->ptr - ptr;
598
 
    }
599
 
 
600
 
    TRACE(("|%p|%p|COUNT %d\n", pattern, ptr, ptr - (SRE_CHAR*) state->ptr));
601
 
    return ptr - (SRE_CHAR*) state->ptr;
602
 
}
603
 
 
604
 
#if 0 /* not used in this release */
605
 
LOCAL(int)
606
 
SRE_INFO(SRE_STATE* state, SRE_CODE* pattern)
607
 
{
608
 
    /* check if an SRE_OP_INFO block matches at the current position.
609
 
       returns the number of SRE_CODE objects to skip if successful, 0
610
 
       if no match */
611
 
 
612
 
    SRE_CHAR* end = state->end;
613
 
    SRE_CHAR* ptr = state->ptr;
614
 
    Py_ssize_t i;
615
 
 
616
 
    /* check minimal length */
617
 
    if (pattern[3] && (end - ptr) < pattern[3])
618
 
        return 0;
619
 
 
620
 
    /* check known prefix */
621
 
    if (pattern[2] & SRE_INFO_PREFIX && pattern[5] > 1) {
622
 
        /* <length> <skip> <prefix data> <overlap data> */
623
 
        for (i = 0; i < pattern[5]; i++)
624
 
            if ((SRE_CODE) ptr[i] != pattern[7 + i])
625
 
                return 0;
626
 
        return pattern[0] + 2 * pattern[6];
627
 
    }
628
 
    return pattern[0];
629
 
}
630
 
#endif
631
 
 
632
 
/* The macros below should be used to protect recursive SRE_MATCH()
633
 
 * calls that *failed* and do *not* return immediately (IOW, those
634
 
 * that will backtrack). Explaining:
635
 
 *
636
 
 * - Recursive SRE_MATCH() returned true: that's usually a success
637
 
 *   (besides atypical cases like ASSERT_NOT), therefore there's no
638
 
 *   reason to restore lastmark;
639
 
 *
640
 
 * - Recursive SRE_MATCH() returned false but the current SRE_MATCH()
641
 
 *   is returning to the caller: If the current SRE_MATCH() is the
642
 
 *   top function of the recursion, returning false will be a matching
643
 
 *   failure, and it doesn't matter where lastmark is pointing to.
644
 
 *   If it's *not* the top function, it will be a recursive SRE_MATCH()
645
 
 *   failure by itself, and the calling SRE_MATCH() will have to deal
646
 
 *   with the failure by the same rules explained here (it will restore
647
 
 *   lastmark by itself if necessary);
648
 
 *
649
 
 * - Recursive SRE_MATCH() returned false, and will continue the
650
 
 *   outside 'for' loop: must be protected when breaking, since the next
651
 
 *   OP could potentially depend on lastmark;
652
 
 *
653
 
 * - Recursive SRE_MATCH() returned false, and will be called again
654
 
 *   inside a local for/while loop: must be protected between each
655
 
 *   loop iteration, since the recursive SRE_MATCH() could do anything,
656
 
 *   and could potentially depend on lastmark.
657
 
 *
658
 
 * For more information, check the discussion at SF patch #712900.
659
 
 */
660
 
#define LASTMARK_SAVE()     \
661
 
    do { \
662
 
        ctx->lastmark = state->lastmark; \
663
 
        ctx->lastindex = state->lastindex; \
664
 
    } while (0)
665
 
#define LASTMARK_RESTORE()  \
666
 
    do { \
667
 
        state->lastmark = ctx->lastmark; \
668
 
        state->lastindex = ctx->lastindex; \
669
 
    } while (0)
670
 
 
671
 
#define RETURN_ERROR(i) do { return i; } while(0)
672
 
#define RETURN_FAILURE do { ret = 0; goto exit; } while(0)
673
 
#define RETURN_SUCCESS do { ret = 1; goto exit; } while(0)
674
 
 
675
 
#define RETURN_ON_ERROR(i) \
676
 
    do { if (i < 0) RETURN_ERROR(i); } while (0)
677
 
#define RETURN_ON_SUCCESS(i) \
678
 
    do { RETURN_ON_ERROR(i); if (i > 0) RETURN_SUCCESS; } while (0)
679
 
#define RETURN_ON_FAILURE(i) \
680
 
    do { RETURN_ON_ERROR(i); if (i == 0) RETURN_FAILURE; } while (0)
681
 
 
682
 
#define SFY(x) #x
683
 
 
684
 
#define DATA_STACK_ALLOC(state, type, ptr) \
685
 
do { \
686
 
    alloc_pos = state->data_stack_base; \
687
 
    TRACE(("allocating %s in %d (%d)\n", \
688
 
           SFY(type), alloc_pos, sizeof(type))); \
689
 
    if (state->data_stack_size < alloc_pos+sizeof(type)) { \
690
 
        int j = data_stack_grow(state, sizeof(type)); \
691
 
        if (j < 0) return j; \
692
 
        if (ctx_pos != -1) \
693
 
            DATA_STACK_LOOKUP_AT(state, SRE_MATCH_CONTEXT, ctx, ctx_pos); \
694
 
    } \
695
 
    ptr = (type*)(state->data_stack+alloc_pos); \
696
 
    state->data_stack_base += sizeof(type); \
697
 
} while (0)
698
 
 
699
 
#define DATA_STACK_LOOKUP_AT(state, type, ptr, pos) \
700
 
do { \
701
 
    TRACE(("looking up %s at %d\n", SFY(type), pos)); \
702
 
    ptr = (type*)(state->data_stack+pos); \
703
 
} while (0)
704
 
 
705
 
#define DATA_STACK_PUSH(state, data, size) \
706
 
do { \
707
 
    TRACE(("copy data in %p to %d (%d)\n", \
708
 
           data, state->data_stack_base, size)); \
709
 
    if (state->data_stack_size < state->data_stack_base+size) { \
710
 
        int j = data_stack_grow(state, size); \
711
 
        if (j < 0) return j; \
712
 
        if (ctx_pos != -1) \
713
 
            DATA_STACK_LOOKUP_AT(state, SRE_MATCH_CONTEXT, ctx, ctx_pos); \
714
 
    } \
715
 
    memcpy(state->data_stack+state->data_stack_base, data, size); \
716
 
    state->data_stack_base += size; \
717
 
} while (0)
718
 
 
719
 
#define DATA_STACK_POP(state, data, size, discard) \
720
 
do { \
721
 
    TRACE(("copy data to %p from %d (%d)\n", \
722
 
           data, state->data_stack_base-size, size)); \
723
 
    memcpy(data, state->data_stack+state->data_stack_base-size, size); \
724
 
    if (discard) \
725
 
        state->data_stack_base -= size; \
726
 
} while (0)
727
 
 
728
 
#define DATA_STACK_POP_DISCARD(state, size) \
729
 
do { \
730
 
    TRACE(("discard data from %d (%d)\n", \
731
 
           state->data_stack_base-size, size)); \
732
 
    state->data_stack_base -= size; \
733
 
} while(0)
734
 
 
735
 
#define DATA_PUSH(x) \
736
 
    DATA_STACK_PUSH(state, (x), sizeof(*(x)))
737
 
#define DATA_POP(x) \
738
 
    DATA_STACK_POP(state, (x), sizeof(*(x)), 1)
739
 
#define DATA_POP_DISCARD(x) \
740
 
    DATA_STACK_POP_DISCARD(state, sizeof(*(x)))
741
 
#define DATA_ALLOC(t,p) \
742
 
    DATA_STACK_ALLOC(state, t, p)
743
 
#define DATA_LOOKUP_AT(t,p,pos) \
744
 
    DATA_STACK_LOOKUP_AT(state,t,p,pos)
745
 
 
746
 
#define MARK_PUSH(lastmark) \
747
 
    do if (lastmark > 0) { \
748
 
        i = lastmark; /* ctx->lastmark may change if reallocated */ \
749
 
        DATA_STACK_PUSH(state, state->mark, (i+1)*sizeof(void*)); \
750
 
    } while (0)
751
 
#define MARK_POP(lastmark) \
752
 
    do if (lastmark > 0) { \
753
 
        DATA_STACK_POP(state, state->mark, (lastmark+1)*sizeof(void*), 1); \
754
 
    } while (0)
755
 
#define MARK_POP_KEEP(lastmark) \
756
 
    do if (lastmark > 0) { \
757
 
        DATA_STACK_POP(state, state->mark, (lastmark+1)*sizeof(void*), 0); \
758
 
    } while (0)
759
 
#define MARK_POP_DISCARD(lastmark) \
760
 
    do if (lastmark > 0) { \
761
 
        DATA_STACK_POP_DISCARD(state, (lastmark+1)*sizeof(void*)); \
762
 
    } while (0)
763
 
 
764
 
#define JUMP_NONE            0
765
 
#define JUMP_MAX_UNTIL_1     1
766
 
#define JUMP_MAX_UNTIL_2     2
767
 
#define JUMP_MAX_UNTIL_3     3
768
 
#define JUMP_MIN_UNTIL_1     4
769
 
#define JUMP_MIN_UNTIL_2     5
770
 
#define JUMP_MIN_UNTIL_3     6
771
 
#define JUMP_REPEAT          7
772
 
#define JUMP_REPEAT_ONE_1    8
773
 
#define JUMP_REPEAT_ONE_2    9
774
 
#define JUMP_MIN_REPEAT_ONE  10
775
 
#define JUMP_BRANCH          11
776
 
#define JUMP_ASSERT          12
777
 
#define JUMP_ASSERT_NOT      13
778
 
#define JUMP_POSS_REPEAT_1   14
779
 
#define JUMP_POSS_REPEAT_2   15
780
 
#define JUMP_ATOMIC_GROUP    16
781
 
#define JUMP__COUNT          17
782
 
 
783
 
#define DO_JUMP(jumpvalue, jumplabel, nextpattern) \
784
 
    DATA_ALLOC(SRE_MATCH_CONTEXT, nextctx); \
785
 
    nextctx->last_ctx_pos = ctx_pos; \
786
 
    nextctx->jump = jumpvalue; \
787
 
    nextctx->pattern = nextpattern; \
788
 
    ctx_pos = alloc_pos; \
789
 
    ctx = nextctx; \
790
 
    goto entrance; \
791
 
    jumplabel: \
792
 
    while (0) /* gcc doesn't like labels at end of scopes */ \
793
 
 
794
 
typedef struct {
795
 
    Py_ssize_t last_ctx_pos;
796
 
    Py_ssize_t jump;
797
 
    SRE_CHAR* ptr;
798
 
    SRE_CODE* pattern;
799
 
    Py_ssize_t count;
800
 
    Py_ssize_t lastmark;
801
 
    Py_ssize_t lastindex;
802
 
    union {
803
 
        SRE_CODE chr;
804
 
        SRE_REPEAT* rep;
805
 
    } u;
806
 
} SRE_MATCH_CONTEXT;
 
716
        SRE_DISCARD_BACKTRACK(context);
 
717
    }
 
718
}
 
719
 
 
720
LOCAL(int) SRE_AT_BOUNDARY(SRE_CONTEXT* context) {
 
721
    int before = context->text_ptr > context->text_start && SRE_IS_WORD(context->text_ptr[-1]);
 
722
    int after = context->text_ptr < context->text_end && SRE_IS_WORD(context->text_ptr[0]);
 
723
    return before != after;
 
724
}
 
725
 
 
726
LOCAL(int) SRE_LOC_AT_BOUNDARY(SRE_CONTEXT* context) {
 
727
    int before = context->text_ptr > context->text_start && SRE_LOC_IS_WORD(context->text_ptr[-1]);
 
728
    int after = context->text_ptr < context->text_end && SRE_LOC_IS_WORD(context->text_ptr[0]);
 
729
    return before != after;
 
730
}
 
731
 
 
732
LOCAL(int) SRE_UNI_AT_BOUNDARY(SRE_CONTEXT* context) {
 
733
    int before = context->text_ptr > context->text_start && SRE_UNI_IS_WORD(context->text_ptr[-1]);
 
734
    int after = context->text_ptr < context->text_end && SRE_UNI_IS_WORD(context->text_ptr[0]);
 
735
    return before != after;
 
736
}
 
737
 
 
738
LOCAL(int) SRE_LOOK_AHEAD_ONE(SRE_CONTEXT* context, SRE_STATE* state, SRE_CODE* look_literal) {
 
739
    switch (look_literal[0]) {
 
740
    case SRE_OP_LITERAL:
 
741
        return context->text_ptr[0] == (SRE_CHAR)look_literal[1];
 
742
    case SRE_OP_LITERAL_IGNORE:
 
743
        return state->lower(context->text_ptr[0]) == (SRE_CHAR)look_literal[1];
 
744
    case SRE_OP_LITERAL_STRING:
 
745
        return context->text_ptr[0] == (SRE_CHAR)look_literal[2];
 
746
    case SRE_OP_LITERAL_STRING_IGNORE:
 
747
        return state->lower(context->text_ptr[0]) == (SRE_CHAR)look_literal[2];
 
748
    case SRE_OP_BOUNDARY:
 
749
        return SRE_AT_BOUNDARY(context);
 
750
    case SRE_OP_LOC_BOUNDARY:
 
751
        return SRE_LOC_AT_BOUNDARY(context);
 
752
    case SRE_OP_UNI_BOUNDARY:
 
753
        return SRE_UNI_AT_BOUNDARY(context);
 
754
    default:
 
755
        return 1;
 
756
    }
 
757
}
 
758
 
 
759
LOCAL(int) SRE_LOOK_AHEAD_ONE_REV(SRE_CONTEXT* context, SRE_STATE* state, SRE_CODE* look_literal) {
 
760
    switch (look_literal[0]) {
 
761
    case SRE_OP_LITERAL:
 
762
        return context->text_ptr[-1] == (SRE_CHAR)look_literal[1];
 
763
    case SRE_OP_LITERAL_IGNORE:
 
764
        return state->lower(context->text_ptr[-1]) == (SRE_CHAR)look_literal[1];
 
765
    case SRE_OP_LITERAL_STRING:
 
766
        return context->text_ptr[-1] == (SRE_CHAR)look_literal[2];
 
767
    case SRE_OP_LITERAL_STRING_IGNORE:
 
768
        return state->lower(context->text_ptr[-1]) == (SRE_CHAR)look_literal[2];
 
769
    case SRE_OP_BOUNDARY:
 
770
        return SRE_AT_BOUNDARY(context);
 
771
    case SRE_OP_LOC_BOUNDARY:
 
772
        return SRE_LOC_AT_BOUNDARY(context);
 
773
    case SRE_OP_UNI_BOUNDARY:
 
774
        return SRE_UNI_AT_BOUNDARY(context);
 
775
    default:
 
776
        return 1;
 
777
    }
 
778
}
 
779
 
 
780
LOCAL(void) SRE_LOOK_AHEAD_MANY(SRE_CONTEXT* context, SRE_CHAR* limit_ptr, SRE_STATE* state, SRE_CODE* look_literal) {
 
781
    switch (look_literal[0]) {
 
782
    case SRE_OP_LITERAL:
 
783
        while (context->text_ptr >= limit_ptr && context->text_ptr[0] != (SRE_CHAR)look_literal[1])
 
784
            context->text_ptr--;
 
785
        break;
 
786
    case SRE_OP_LITERAL_IGNORE:
 
787
        while (context->text_ptr >= limit_ptr && state->lower(context->text_ptr[0]) != (SRE_CHAR)look_literal[1])
 
788
            context->text_ptr--;
 
789
        break;
 
790
    case SRE_OP_LITERAL_STRING:
 
791
        while (context->text_ptr >= limit_ptr && context->text_ptr[0] != (SRE_CHAR)look_literal[2])
 
792
            context->text_ptr--;
 
793
        break;
 
794
    case SRE_OP_LITERAL_STRING_IGNORE:
 
795
        while (context->text_ptr >= limit_ptr && state->lower(context->text_ptr[0]) != (SRE_CHAR)look_literal[2])
 
796
            context->text_ptr--;
 
797
        break;
 
798
    case SRE_OP_BOUNDARY:
 
799
        while (context->text_ptr >= limit_ptr && !SRE_AT_BOUNDARY(context))
 
800
            context->text_ptr--;
 
801
        break;
 
802
    case SRE_OP_LOC_BOUNDARY:
 
803
        while (context->text_ptr >= limit_ptr && !SRE_LOC_AT_BOUNDARY(context))
 
804
            context->text_ptr--;
 
805
        break;
 
806
    case SRE_OP_UNI_BOUNDARY:
 
807
        while (context->text_ptr >= limit_ptr && !SRE_UNI_AT_BOUNDARY(context))
 
808
            context->text_ptr--;
 
809
        break;
 
810
    }
 
811
}
 
812
 
 
813
LOCAL(void) SRE_LOOK_AHEAD_MANY_REV(SRE_CONTEXT* context, SRE_CHAR* limit_ptr, SRE_STATE* state, SRE_CODE* look_literal) {
 
814
    switch (look_literal[0]) {
 
815
    case SRE_OP_LITERAL:
 
816
        while (context->text_ptr <= limit_ptr && context->text_ptr[-1] != (SRE_CHAR)look_literal[1])
 
817
            context->text_ptr++;
 
818
        break;
 
819
    case SRE_OP_LITERAL_IGNORE:
 
820
        while (context->text_ptr <= limit_ptr && state->lower(context->text_ptr[-1]) != (SRE_CHAR)look_literal[1])
 
821
            context->text_ptr++;
 
822
        break;
 
823
    case SRE_OP_LITERAL_STRING:
 
824
        while (context->text_ptr <= limit_ptr && context->text_ptr[-1] != (SRE_CHAR)look_literal[2])
 
825
            context->text_ptr++;
 
826
        break;
 
827
    case SRE_OP_LITERAL_STRING_IGNORE:
 
828
        while (context->text_ptr <= limit_ptr && state->lower(context->text_ptr[-1]) != (SRE_CHAR)look_literal[2])
 
829
            context->text_ptr++;
 
830
        break;
 
831
    case SRE_OP_BOUNDARY:
 
832
        while (context->text_ptr <= limit_ptr && !SRE_AT_BOUNDARY(context))
 
833
            context->text_ptr++;
 
834
        break;
 
835
    case SRE_OP_LOC_BOUNDARY:
 
836
        while (context->text_ptr <= limit_ptr && !SRE_LOC_AT_BOUNDARY(context))
 
837
            context->text_ptr++;
 
838
        break;
 
839
    case SRE_OP_UNI_BOUNDARY:
 
840
        while (context->text_ptr <= limit_ptr && !SRE_UNI_AT_BOUNDARY(context))
 
841
            context->text_ptr++;
 
842
        break;
 
843
    }
 
844
}
807
845
 
808
846
/* check if string matches the given pattern.  returns <0 for
809
847
   error, 0 for failure, and 1 for success */
810
848
LOCAL(Py_ssize_t)
811
 
SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
812
 
{
813
 
    SRE_CHAR* end = (SRE_CHAR *)state->end;
814
 
    Py_ssize_t alloc_pos, ctx_pos = -1;
815
 
    Py_ssize_t i, ret = 0;
816
 
    Py_ssize_t jump;
817
 
    unsigned int sigcount=0;
818
 
 
819
 
    SRE_MATCH_CONTEXT* ctx;
820
 
    SRE_MATCH_CONTEXT* nextctx;
821
 
 
822
 
    TRACE(("|%p|%p|ENTER\n", pattern, state->ptr));
823
 
 
824
 
    DATA_ALLOC(SRE_MATCH_CONTEXT, ctx);
825
 
    ctx->last_ctx_pos = -1;
826
 
    ctx->jump = JUMP_NONE;
827
 
    ctx->pattern = pattern;
828
 
    ctx_pos = alloc_pos;
829
 
 
830
 
entrance:
831
 
 
832
 
    ctx->ptr = (SRE_CHAR *)state->ptr;
833
 
 
834
 
    if (ctx->pattern[0] == SRE_OP_INFO) {
835
 
        /* optimization info block */
836
 
        /* <INFO> <1=skip> <2=flags> <3=min> ... */
837
 
        if (ctx->pattern[3] && (end - ctx->ptr) < ctx->pattern[3]) {
838
 
            TRACE(("reject (got %d chars, need %d)\n",
839
 
                   (end - ctx->ptr), ctx->pattern[3]));
840
 
            RETURN_FAILURE;
841
 
        }
842
 
        ctx->pattern += ctx->pattern[1] + 1;
843
 
    }
844
 
 
 
849
SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern_ptr) {
 
850
    SRE_CONTEXT context;
 
851
    unsigned int sigcount = 0;
 
852
    int result;
 
853
 
 
854
    context.text_ptr = state->ptr;
 
855
    context.text_start = (SRE_CHAR *)state->beginning;
 
856
    context.text_end = (SRE_CHAR *)state->end;
 
857
    context.pattern_ptr = pattern_ptr;
 
858
    context.repeat_counter = state->repeat_counter;
 
859
    context.repeat_start = (SRE_CHAR**)state->repeat_start;
 
860
    context.backtrack_chunk = state->backtrack_chunk;
 
861
    context.saved_marks_chunk = state->saved_marks_chunk;
 
862
    context.mark = (SRE_CHAR**)state->mark;
 
863
    context.mark_count = state->mark_count;
 
864
 
 
865
    // Point to the final newline if it's the final character.
 
866
    context.final_linebreak = context.text_start < context.text_end && SRE_IS_LINEBREAK(context.text_end[-1]) ? context.text_end - 1 : NULL;
 
867
 
 
868
    TRACE(("|%p|%p|ENTER\n", context.pattern_ptr, context.text_ptr));
 
869
    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_FAILURE, NULL, -1);
 
870
    if (result != 0)
 
871
        return SRE_CLEANUP(&context, state, result);
 
872
    memset(context.mark, 0, context.mark_count * sizeof(SRE_CHAR*));
 
873
 
 
874
advance:
845
875
    for (;;) {
846
876
        ++sigcount;
847
877
        if ((0 == (sigcount & 0xfff)) && PyErr_CheckSignals())
848
 
            RETURN_ERROR(SRE_ERROR_INTERRUPTED);
849
 
 
850
 
        switch (*ctx->pattern++) {
851
 
 
852
 
        case SRE_OP_MARK:
853
 
            /* set mark */
854
 
            /* <MARK> <gid> */
855
 
            TRACE(("|%p|%p|MARK %d\n", ctx->pattern,
856
 
                   ctx->ptr, ctx->pattern[0]));
857
 
            i = ctx->pattern[0];
858
 
            if (i & 1)
859
 
                state->lastindex = i/2 + 1;
860
 
            if (i > state->lastmark) {
861
 
                /* state->lastmark is the highest valid index in the
862
 
                   state->mark array.  If it is increased by more than 1,
863
 
                   the intervening marks must be set to NULL to signal
864
 
                   that these marks have not been encountered. */
865
 
                Py_ssize_t j = state->lastmark + 1;
866
 
                while (j < i)
867
 
                    state->mark[j++] = NULL;
868
 
                state->lastmark = i;
869
 
            }
870
 
            state->mark[i] = ctx->ptr;
871
 
            ctx->pattern++;
872
 
            break;
873
 
 
874
 
        case SRE_OP_LITERAL:
875
 
            /* match literal string */
876
 
            /* <LITERAL> <code> */
877
 
            TRACE(("|%p|%p|LITERAL %d\n", ctx->pattern,
878
 
                   ctx->ptr, *ctx->pattern));
879
 
            if (ctx->ptr >= end || (SRE_CODE) ctx->ptr[0] != ctx->pattern[0])
880
 
                RETURN_FAILURE;
881
 
            ctx->pattern++;
882
 
            ctx->ptr++;
883
 
            break;
884
 
 
885
 
        case SRE_OP_NOT_LITERAL:
886
 
            /* match anything that is not literal character */
887
 
            /* <NOT_LITERAL> <code> */
888
 
            TRACE(("|%p|%p|NOT_LITERAL %d\n", ctx->pattern,
889
 
                   ctx->ptr, *ctx->pattern));
890
 
            if (ctx->ptr >= end || (SRE_CODE) ctx->ptr[0] == ctx->pattern[0])
891
 
                RETURN_FAILURE;
892
 
            ctx->pattern++;
893
 
            ctx->ptr++;
894
 
            break;
895
 
 
896
 
        case SRE_OP_SUCCESS:
897
 
            /* end of pattern */
898
 
            TRACE(("|%p|%p|SUCCESS\n", ctx->pattern, ctx->ptr));
899
 
            state->ptr = ctx->ptr;
900
 
            RETURN_SUCCESS;
901
 
 
902
 
        case SRE_OP_AT:
903
 
            /* match at given position */
904
 
            /* <AT> <code> */
905
 
            TRACE(("|%p|%p|AT %d\n", ctx->pattern, ctx->ptr, *ctx->pattern));
906
 
            if (!SRE_AT(state, ctx->ptr, *ctx->pattern))
907
 
                RETURN_FAILURE;
908
 
            ctx->pattern++;
909
 
            break;
910
 
 
911
 
        case SRE_OP_CATEGORY:
912
 
            /* match at given category */
913
 
            /* <CATEGORY> <code> */
914
 
            TRACE(("|%p|%p|CATEGORY %d\n", ctx->pattern,
915
 
                   ctx->ptr, *ctx->pattern));
916
 
            if (ctx->ptr >= end || !sre_category(ctx->pattern[0], ctx->ptr[0]))
917
 
                RETURN_FAILURE;
918
 
            ctx->pattern++;
919
 
            ctx->ptr++;
920
 
            break;
921
 
 
 
878
            return SRE_CLEANUP(&context, state, SRE_ERROR_INTERRUPTED);
 
879
 
 
880
        switch (*context.pattern_ptr++) {
922
881
        case SRE_OP_ANY:
923
 
            /* match anything (except a newline) */
924
 
            /* <ANY> */
925
 
            TRACE(("|%p|%p|ANY\n", ctx->pattern, ctx->ptr));
926
 
            if (ctx->ptr >= end || SRE_IS_LINEBREAK(ctx->ptr[0]))
927
 
                RETURN_FAILURE;
928
 
            ctx->ptr++;
 
882
            // Match anything (except a newline).
 
883
            // <ANY>
 
884
            TRACE(("|%p|%p|ANY\n", context.pattern_ptr, context.text_ptr));
 
885
            if (context.text_ptr >= context.text_end || SRE_IS_LINEBREAK(context.text_ptr[0]))
 
886
                goto backtrack;
 
887
            context.text_ptr++;
929
888
            break;
930
 
 
931
889
        case SRE_OP_ANY_ALL:
932
 
            /* match anything */
933
 
            /* <ANY_ALL> */
934
 
            TRACE(("|%p|%p|ANY_ALL\n", ctx->pattern, ctx->ptr));
935
 
            if (ctx->ptr >= end)
936
 
                RETURN_FAILURE;
937
 
            ctx->ptr++;
938
 
            break;
939
 
 
 
890
            // Match anything.
 
891
            // <ANY_ALL>
 
892
            TRACE(("|%p|%p|ANY_ALL\n", context.pattern_ptr, context.text_ptr));
 
893
            if (context.text_ptr >= context.text_end)
 
894
                goto backtrack;
 
895
            context.text_ptr++;
 
896
            break;
 
897
        case SRE_OP_ANY_ALL_REV:
 
898
            // Match anything.
 
899
            // <ANY_ALL_REV>
 
900
            TRACE(("|%p|%p|ANY_ALL_REV\n", context.pattern_ptr, context.text_ptr));
 
901
            if (context.text_ptr <= context.text_start)
 
902
                goto backtrack;
 
903
            context.text_ptr--;
 
904
            break;
 
905
        case SRE_OP_ANY_REV:
 
906
            // Match anything (except a newline).
 
907
            // <ANY_REV>
 
908
            TRACE(("|%p|%p|ANY_REV\n", context.pattern_ptr, context.text_ptr));
 
909
            if (context.text_ptr <= context.text_start || SRE_IS_LINEBREAK(context.text_ptr[-1]))
 
910
                goto backtrack;
 
911
            context.text_ptr--;
 
912
            break;
 
913
        case SRE_OP_ASSERT:
 
914
            // Assert subpattern.
 
915
            // <ASSERT> <skip to end> ... <END_ASSERT>
 
916
            TRACE(("|%p|%p|ASSERT\n", context.pattern_ptr, context.text_ptr));
 
917
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_ASSERT, context.pattern_ptr, -1);
 
918
            if (result != 0)
 
919
                return SRE_CLEANUP(&context, state, result);
 
920
            result = SRE_SAVE_MARKS(&context);
 
921
            if (result != 0)
 
922
                return SRE_CLEANUP(&context, state, result);
 
923
            context.pattern_ptr++;
 
924
            break;
 
925
        case SRE_OP_ASSERT_NOT:
 
926
            // Assert not subpattern.
 
927
            // <ASSERT_NOT> <skip to end> ... <END_ASSERT_NOT>
 
928
            TRACE(("|%p|%p|ASSERT_NOT\n", context.pattern_ptr, context.text_ptr));
 
929
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_ASSERT_NOT, context.pattern_ptr, -1);
 
930
            if (result != 0)
 
931
                return SRE_CLEANUP(&context, state, result);
 
932
            result = SRE_SAVE_MARKS(&context);
 
933
            if (result != 0)
 
934
                return SRE_CLEANUP(&context, state, result);
 
935
            context.pattern_ptr++;
 
936
            break;
 
937
        case SRE_OP_ATOMIC:
 
938
            // Atomic subpattern.
 
939
            // <ATOMIC> ... <END_ATOMIC>
 
940
            TRACE(("|%p|%p|ATOMIC\n", context.pattern_ptr, context.text_ptr));
 
941
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_ATOMIC, NULL, -1);
 
942
            if (result != 0)
 
943
                return SRE_CLEANUP(&context, state, result);
 
944
            result = SRE_SAVE_MARKS(&context);
 
945
            if (result != 0)
 
946
                return SRE_CLEANUP(&context, state, result);
 
947
            break;
 
948
        case SRE_OP_BIGCHARSET:
 
949
            // Match character in charset.
 
950
            // <BIGCHARSET> <charset>
 
951
            TRACE(("|%p|%p|BIGCHARSET\n", context.pattern_ptr, context.text_ptr));
 
952
            if (context.text_ptr >= context.text_end || !in_bigcharset(context.pattern_ptr, context.text_ptr[0]))
 
953
                goto backtrack;
 
954
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
955
            context.text_ptr++;
 
956
            break;
 
957
        case SRE_OP_BIGCHARSET_IGNORE:
 
958
            // Match character in charset, ignoring case.
 
959
            // <BIGCHARSET_IGNORE> <charset>
 
960
            TRACE(("|%p|%p|BIGCHARSET\n", context.pattern_ptr, context.text_ptr));
 
961
            if (context.text_ptr >= context.text_end || !in_bigcharset(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
962
                goto backtrack;
 
963
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
964
            context.text_ptr++;
 
965
            break;
 
966
        case SRE_OP_BIGCHARSET_IGNORE_REV:
 
967
            // Match character in charset, ignoring case.
 
968
            // <BIGCHARSET_IGNORE_REV> <charset>
 
969
            TRACE(("|%p|%p|BIGCHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
970
            if (context.text_ptr <= context.text_start || !in_bigcharset(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
971
                goto backtrack;
 
972
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
973
            context.text_ptr--;
 
974
            break;
 
975
        case SRE_OP_BIGCHARSET_REV:
 
976
            // Match character in charset.
 
977
            // <BIGCHARSET_REV> <charset>
 
978
            TRACE(("|%p|%p|BIGCHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
979
            if (context.text_ptr <= context.text_start || !in_bigcharset(context.pattern_ptr, context.text_ptr[-1]))
 
980
                goto backtrack;
 
981
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
982
            context.text_ptr--;
 
983
            break;
 
984
        case SRE_OP_BOUNDARY:
 
985
            // Boundary between word and non-word.
 
986
            // <BOUNDARY>
 
987
            TRACE(("|%p|%p|BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
988
            if (! SRE_AT_BOUNDARY(&context))
 
989
                goto backtrack;
 
990
            break;
 
991
        case SRE_OP_BRANCH:
 
992
            // Alternation.
 
993
            // <BRANCH> <skip to next> ... <JUMP> <skip to end> <skip to next> ... <JUMP> <skip to end> 0
 
994
            TRACE(("|%p|%p|BRANCH\n", context.pattern_ptr, context.text_ptr));
 
995
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_BRANCH, context.pattern_ptr, -1);
 
996
            if (result != 0)
 
997
                return SRE_CLEANUP(&context, state, result);
 
998
            result = SRE_SAVE_MARKS(&context);
 
999
            if (result != 0)
 
1000
                return SRE_CLEANUP(&context, state, result);
 
1001
            context.pattern_ptr++;
 
1002
            break;
 
1003
        case SRE_OP_CHARSET:
 
1004
            // Match character in charset.
 
1005
            // <CHARSET> <charset>
 
1006
            TRACE(("|%p|%p|CHARSET\n", context.pattern_ptr, context.text_ptr));
 
1007
            if (context.text_ptr >= context.text_end || !in_charset(context.pattern_ptr, context.text_ptr[0]))
 
1008
                goto backtrack;
 
1009
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1010
            context.text_ptr++;
 
1011
            break;
 
1012
        case SRE_OP_CHARSET_IGNORE:
 
1013
            // Match character in charset, ignoring case.
 
1014
            // <CHARSET_IGNORE> <charset>
 
1015
            TRACE(("|%p|%p|CHARSET\n", context.pattern_ptr, context.text_ptr));
 
1016
            if (context.text_ptr >= context.text_end || !in_charset(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
1017
                goto backtrack;
 
1018
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1019
            context.text_ptr++;
 
1020
            break;
 
1021
        case SRE_OP_CHARSET_IGNORE_REV:
 
1022
            // Match character in charset, ignoring case.
 
1023
            // <CHARSET_IGNORE_REV> <charset>
 
1024
            TRACE(("|%p|%p|CHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
1025
            if (context.text_ptr <= context.text_start || !in_charset(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
1026
                goto backtrack;
 
1027
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1028
            context.text_ptr--;
 
1029
            break;
 
1030
        case SRE_OP_CHARSET_REV:
 
1031
            // Match character in charset.
 
1032
            // <CHARSET_REV> <charset>
 
1033
            TRACE(("|%p|%p|CHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
1034
            if (context.text_ptr <= context.text_start || !in_charset(context.pattern_ptr, context.text_ptr[-1]))
 
1035
                goto backtrack;
 
1036
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1037
            context.text_ptr--;
 
1038
            break;
 
1039
        case SRE_OP_DIGIT:
 
1040
            // Digit.
 
1041
            // <DIGIT>
 
1042
            TRACE(("|%p|%p|DIGIT\n", context.pattern_ptr, context.text_ptr));
 
1043
            if (context.text_ptr >= context.text_end || !SRE_IS_DIGIT(context.text_ptr[0]))
 
1044
                goto backtrack;
 
1045
            context.text_ptr++;
 
1046
            break;
 
1047
        case SRE_OP_DIGIT_REV:
 
1048
            // Digit.
 
1049
            // <DIGIT_REV>
 
1050
            TRACE(("|%p|%p|DIGIT_REV\n", context.pattern_ptr, context.text_ptr));
 
1051
            if (context.text_ptr <= context.text_start || !SRE_IS_DIGIT(context.text_ptr[-1]))
 
1052
                goto backtrack;
 
1053
            context.text_ptr--;
 
1054
            break;
 
1055
        case SRE_OP_END_ASSERT:
 
1056
        {
 
1057
            // Assert subpattern.
 
1058
            // <ASSERT> <skip to end> ... <END_ASSERT>
 
1059
            SRE_BACKTRACK_ITEM* backtrack_item;
 
1060
            TRACE(("|%p|%p|END_ASSERT\n", context.pattern_ptr, context.text_ptr));
 
1061
            SRE_DISCARD_UNTIL_OP(&context, SRE_OP_ASSERT);
 
1062
            backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
1063
            context.text_ptr = backtrack_item->text_ptr;
 
1064
            SRE_DISCARD_BACKTRACK(&context);
 
1065
            SRE_RESTORE_MARKS(&context);
 
1066
            break;
 
1067
        }
 
1068
        case SRE_OP_END_ASSERT_NOT:
 
1069
        {
 
1070
            // Assert not subpattern.
 
1071
            // <ASSERT_NOT> <skip to end> ... <END_ASSERT_NOT>
 
1072
            TRACE(("|%p|%p|END_ASSERT_NOT\n", context.pattern_ptr, context.text_ptr));
 
1073
            SRE_DISCARD_UNTIL_OP(&context, SRE_OP_ASSERT_NOT);
 
1074
            SRE_DISCARD_BACKTRACK(&context);
 
1075
            SRE_RESTORE_MARKS(&context);
 
1076
            goto backtrack;
 
1077
        }
 
1078
        case SRE_OP_END_ATOMIC:
 
1079
        {
 
1080
            // Atomic subpattern.
 
1081
            // <ATOMIC> <skip to end> ... <END_ATOMIC>
 
1082
            SRE_DISCARD_UNTIL_OP(&context, SRE_OP_ATOMIC);
 
1083
            SRE_DISCARD_BACKTRACK(&context);
 
1084
            SRE_DISCARD_SAVED_MARKS(&context);
 
1085
            break;
 
1086
        }
 
1087
        case SRE_OP_END_OF_LINE:
 
1088
            // End of line.
 
1089
            // <END_OF_LINE>
 
1090
            TRACE(("|%p|%p|END_OF_LINE\n", context.pattern_ptr, context.text_ptr));
 
1091
            if (context.text_ptr < context.text_end && !SRE_IS_LINEBREAK(context.text_ptr[0]))
 
1092
                goto backtrack;
 
1093
            break;
 
1094
        case SRE_OP_END_OF_STRING:
 
1095
            // End of string.
 
1096
            // <END_OF_STRING>
 
1097
            TRACE(("|%p|%p|END_OF_STRING\n", context.pattern_ptr, context.text_ptr));
 
1098
            if (context.text_ptr < context.text_end)
 
1099
                goto backtrack;
 
1100
            break;
 
1101
        case SRE_OP_END_OF_STRING_2:
 
1102
            // End of string or final line.
 
1103
            // <END_OF_STRING_2>
 
1104
            TRACE(("|%p|%p|END_OF_STRING_2\n", context.pattern_ptr, context.text_ptr));
 
1105
            if (context.text_ptr < context.text_end && context.text_ptr != context.final_linebreak)
 
1106
                goto backtrack;
 
1107
            break;
 
1108
        case SRE_OP_END_REPEAT_MAX:
 
1109
        {
 
1110
            // End of greedy repeat.
 
1111
            // <REPEAT_MAX> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX> <skip to start>
 
1112
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1113
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1114
            int index = repeat_ptr[1];
 
1115
            int repeat_min = repeat_ptr[2];
 
1116
            int repeat_max = repeat_ptr[3];
 
1117
            SRE_CODE* body = repeat_ptr + 4;
 
1118
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1119
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
1120
            int curr_repeats = ++context.repeat_counter[index];
 
1121
            TRACE(("|%p|%p|END_REPEAT_MAX\n", context.pattern_ptr, context.text_ptr));
 
1122
            if (context.text_ptr == context.repeat_start[index])
 
1123
                context.pattern_ptr = tail;
 
1124
            else if (curr_repeats < repeat_min) {
 
1125
                if (repeat_min - curr_repeats > limit)
 
1126
                    goto backtrack;
 
1127
                context.pattern_ptr = body;
 
1128
                context.repeat_start[index] = context.text_ptr;
 
1129
            } else {
 
1130
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1131
                if (curr_repeats < repeat_max && limit > 0) {
 
1132
                    SRE_CODE* look_literal = tail;
 
1133
                    while (look_literal[0] == SRE_OP_MARK)
 
1134
                        look_literal += 2;
 
1135
                    // Look at what follows to avoid unnecessary backtracking.
 
1136
                    if (SRE_LOOK_AHEAD_ONE(&context, state, look_literal)) {
 
1137
                        result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MAX, end_repeat_ptr, -1);
 
1138
                        if (result != 0)
 
1139
                            return SRE_CLEANUP(&context, state, result);
 
1140
                        result = SRE_SAVE_MARKS(&context);
 
1141
                        if (result != 0)
 
1142
                            return SRE_CLEANUP(&context, state, result);
 
1143
                    }
 
1144
                    context.pattern_ptr = body;
 
1145
                    context.repeat_start[index] = context.text_ptr;
 
1146
                } else
 
1147
                    context.pattern_ptr = tail;
 
1148
            }
 
1149
            break;
 
1150
        }
 
1151
        case SRE_OP_END_REPEAT_MAX_REV:
 
1152
        {
 
1153
            // End of greedy repeat.
 
1154
            // <REPEAT_MAX_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX_REV> <skip to start>
 
1155
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1156
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1157
            int index = repeat_ptr[1];
 
1158
            int repeat_min = repeat_ptr[2];
 
1159
            int repeat_max = repeat_ptr[3];
 
1160
            SRE_CODE* body = repeat_ptr + 4;
 
1161
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1162
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
1163
            int curr_repeats = ++context.repeat_counter[index];
 
1164
            TRACE(("|%p|%p|END_REPEAT_MAX_REV\n", context.pattern_ptr, context.text_ptr));
 
1165
            if (context.text_ptr == context.repeat_start[index])
 
1166
                context.pattern_ptr = tail;
 
1167
            else if (curr_repeats < repeat_min) {
 
1168
                if (repeat_min - curr_repeats > limit)
 
1169
                    goto backtrack;
 
1170
                context.pattern_ptr = body;
 
1171
                context.repeat_start[index] = context.text_ptr;
 
1172
            } else {
 
1173
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1174
                if (curr_repeats < repeat_max && limit > 0) {
 
1175
                    SRE_CODE* look_literal = tail;
 
1176
                    while (look_literal[0] == SRE_OP_MARK)
 
1177
                        look_literal += 2;
 
1178
                    // Look at what follows to avoid unnecessary backtracking.
 
1179
                    if (SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal)) {
 
1180
                        result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MAX_REV, end_repeat_ptr, -1);
 
1181
                        if (result != 0)
 
1182
                            return SRE_CLEANUP(&context, state, result);
 
1183
                        result = SRE_SAVE_MARKS(&context);
 
1184
                        if (result != 0)
 
1185
                            return SRE_CLEANUP(&context, state, result);
 
1186
                    }
 
1187
                    context.pattern_ptr = body;
 
1188
                    context.repeat_start[index] = context.text_ptr;
 
1189
                } else
 
1190
                    context.pattern_ptr = tail;
 
1191
            }
 
1192
            break;
 
1193
        }
 
1194
        case SRE_OP_END_REPEAT_MIN:
 
1195
        {
 
1196
            // End of lazy repeat.
 
1197
            // <REPEAT_MIN> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN> <skip to start>
 
1198
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1199
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1200
            int index = repeat_ptr[1];
 
1201
            int repeat_min = repeat_ptr[2];
 
1202
            int repeat_max = repeat_ptr[3];
 
1203
            SRE_CODE* body = repeat_ptr + 4;
 
1204
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1205
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
1206
            int curr_repeats = ++context.repeat_counter[index];
 
1207
            TRACE(("|%p|%p|END_REPEAT_MIN\n", context.pattern_ptr, context.text_ptr));
 
1208
            if (context.text_ptr == context.repeat_start[index])
 
1209
                context.pattern_ptr = tail;
 
1210
            else if (curr_repeats < repeat_min) {
 
1211
                if (repeat_min - curr_repeats > limit)
 
1212
                    goto backtrack;
 
1213
                SRE_RESTORE_MARKS(&context);
 
1214
                result = SRE_SAVE_MARKS(&context);
 
1215
                if (result != 0)
 
1216
                    return SRE_CLEANUP(&context, state, result);
 
1217
                context.pattern_ptr = body;
 
1218
                context.repeat_start[index] = context.text_ptr;
 
1219
            } else {
 
1220
                int match;
 
1221
                if (limit > 0) {
 
1222
                    SRE_CODE* look_literal = tail;
 
1223
                    while (look_literal[0] == SRE_OP_MARK)
 
1224
                        look_literal += 2;
 
1225
                    // Look at what follows to avoid unnecessary backtracking.
 
1226
                    match = SRE_LOOK_AHEAD_ONE(&context, state, look_literal);
 
1227
                } else
 
1228
                    match = 1;
 
1229
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1230
                if (curr_repeats < repeat_max) {
 
1231
                    if (match) {
 
1232
                        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
1233
                        backtrack_item->text_ptr = context.text_ptr;
 
1234
                        result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MIN, end_repeat_ptr, -1);
 
1235
                        if (result != 0)
 
1236
                            return SRE_CLEANUP(&context, state, result);
 
1237
                        result = SRE_SAVE_MARKS(&context);
 
1238
                        if (result != 0)
 
1239
                            return SRE_CLEANUP(&context, state, result);
 
1240
                        context.pattern_ptr = tail;
 
1241
                    } else {
 
1242
                        context.pattern_ptr = body;
 
1243
                        context.repeat_start[index] = context.text_ptr;
 
1244
                    }
 
1245
                } else {
 
1246
                    if (match)
 
1247
                        context.pattern_ptr = tail;
 
1248
                    else
 
1249
                        goto backtrack;
 
1250
                }
 
1251
            }
 
1252
            break;
 
1253
        }
 
1254
        case SRE_OP_END_REPEAT_MIN_REV:
 
1255
        {
 
1256
            // End of lazy repeat.
 
1257
            // <REPEAT_MIN_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN_REV> <skip to start>
 
1258
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1259
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1260
            int index = repeat_ptr[1];
 
1261
            int repeat_min = repeat_ptr[2];
 
1262
            int repeat_max = repeat_ptr[3];
 
1263
            SRE_CODE* body = repeat_ptr + 4;
 
1264
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1265
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
1266
            int curr_repeats = ++context.repeat_counter[index];
 
1267
            TRACE(("|%p|%p|END_REPEAT_MIN_REV\n", context.pattern_ptr, context.text_ptr));
 
1268
            if (context.text_ptr == context.repeat_start[index])
 
1269
                context.pattern_ptr = tail;
 
1270
            else if (curr_repeats < repeat_min) {
 
1271
                if (repeat_min - curr_repeats > limit)
 
1272
                    goto backtrack;
 
1273
                SRE_RESTORE_MARKS(&context);
 
1274
                result = SRE_SAVE_MARKS(&context);
 
1275
                if (result != 0)
 
1276
                    return SRE_CLEANUP(&context, state, result);
 
1277
                context.pattern_ptr = body;
 
1278
                context.repeat_start[index] = context.text_ptr;
 
1279
            } else {
 
1280
                int match;
 
1281
                if (limit > 0) {
 
1282
                    SRE_CODE* look_literal = tail;
 
1283
                    while (look_literal[0] == SRE_OP_MARK)
 
1284
                        look_literal += 2;
 
1285
                    // Look at what follows to avoid unnecessary backtracking.
 
1286
                    match = SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal);
 
1287
                } else
 
1288
                    match = 1;
 
1289
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1290
                if (curr_repeats < repeat_max) {
 
1291
                    if (match) {
 
1292
                        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
1293
                        backtrack_item->text_ptr = context.text_ptr;
 
1294
                        result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MIN, end_repeat_ptr, -1);
 
1295
                        if (result != 0)
 
1296
                            return SRE_CLEANUP(&context, state, result);
 
1297
                        result = SRE_SAVE_MARKS(&context);
 
1298
                        if (result != 0)
 
1299
                            return SRE_CLEANUP(&context, state, result);
 
1300
                        context.pattern_ptr = tail;
 
1301
                    } else {
 
1302
                        context.pattern_ptr = body;
 
1303
                        context.repeat_start[index] = context.text_ptr;
 
1304
                    }
 
1305
                } else {
 
1306
                    if (match)
 
1307
                        context.pattern_ptr = tail;
 
1308
                    else
 
1309
                        goto backtrack;
 
1310
                }
 
1311
            }
 
1312
            break;
 
1313
        }
 
1314
        case SRE_OP_END_REPEAT_POSS:
 
1315
        {
 
1316
            // End of possessive repeat.
 
1317
            // <REPEAT_POSS> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS> <skip to start>
 
1318
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1319
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1320
            int index = repeat_ptr[1];
 
1321
            int repeat_min = repeat_ptr[2];
 
1322
            int repeat_max = repeat_ptr[3];
 
1323
            SRE_CODE* body = repeat_ptr + 4;
 
1324
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1325
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
1326
            int curr_repeats = ++context.repeat_counter[index];
 
1327
            TRACE(("|%p|%p|END_REPEAT_POSS\n", context.pattern_ptr, context.text_ptr));
 
1328
            SRE_DISCARD_UNTIL_OP(&context, SRE_OP_REPEAT_POSS);
 
1329
            if (context.repeat_start[index] == context.text_ptr)
 
1330
                context.pattern_ptr = tail;
 
1331
            else if (curr_repeats < repeat_min) {
 
1332
                if (repeat_min - curr_repeats > limit)
 
1333
                    goto backtrack;
 
1334
                context.pattern_ptr = body;
 
1335
                context.repeat_start[index] = context.text_ptr;
 
1336
            } else {
 
1337
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1338
                if (curr_repeats < repeat_max && limit > 0) {
 
1339
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_POSS, end_repeat_ptr, -1);
 
1340
                    if (result != 0)
 
1341
                        return SRE_CLEANUP(&context, state, result);
 
1342
                    result = SRE_SAVE_MARKS(&context);
 
1343
                    if (result != 0)
 
1344
                        return SRE_CLEANUP(&context, state, result);
 
1345
                    context.pattern_ptr = body;
 
1346
                    context.repeat_start[index] = context.text_ptr;
 
1347
                } else
 
1348
                    context.pattern_ptr = tail;
 
1349
            }
 
1350
            break;
 
1351
        }
 
1352
        case SRE_OP_END_REPEAT_POSS_REV:
 
1353
        {
 
1354
            // End of possessive repeat.
 
1355
            // <REPEAT_POSS_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS_REV> <skip to start>
 
1356
            SRE_CODE* repeat_ptr = context.pattern_ptr - context.pattern_ptr[0];
 
1357
            SRE_CODE* end_repeat_ptr = context.pattern_ptr;
 
1358
            int index = repeat_ptr[1];
 
1359
            int repeat_min = repeat_ptr[2];
 
1360
            int repeat_max = repeat_ptr[3];
 
1361
            SRE_CODE* body = repeat_ptr + 4;
 
1362
            SRE_CODE* tail = end_repeat_ptr + 1;
 
1363
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
1364
            int curr_repeats = ++context.repeat_counter[index];
 
1365
            TRACE(("|%p|%p|END_REPEAT_POSS_REV\n", context.pattern_ptr, context.text_ptr));
 
1366
            SRE_DISCARD_UNTIL_OP(&context, SRE_OP_REPEAT_POSS_REV);
 
1367
            if (context.repeat_start[index] == context.text_ptr)
 
1368
                context.pattern_ptr = tail;
 
1369
            else if (curr_repeats < repeat_min) {
 
1370
                if (repeat_min - curr_repeats > limit)
 
1371
                    goto backtrack;
 
1372
                context.pattern_ptr = body;
 
1373
                context.repeat_start[index] = context.text_ptr;
 
1374
            } else {
 
1375
                repeat_max = sre_repeat_limit(repeat_max, curr_repeats + limit);
 
1376
                if (curr_repeats < repeat_max && limit > 0) {
 
1377
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_POSS_REV, end_repeat_ptr, -1);
 
1378
                    if (result != 0)
 
1379
                        return SRE_CLEANUP(&context, state, result);
 
1380
                    result = SRE_SAVE_MARKS(&context);
 
1381
                    if (result != 0)
 
1382
                        return SRE_CLEANUP(&context, state, result);
 
1383
                    context.pattern_ptr = body;
 
1384
                    context.repeat_start[index] = context.text_ptr;
 
1385
                } else
 
1386
                    context.pattern_ptr = tail;
 
1387
            }
 
1388
            break;
 
1389
        }
 
1390
        case SRE_OP_GROUPREF:
 
1391
        {
 
1392
            // Match backreference.
 
1393
            // <GROUPREF> <group>
 
1394
            Py_ssize_t group;
 
1395
            SRE_CHAR* group_start;
 
1396
            SRE_CHAR* group_end;
 
1397
            Py_ssize_t length;
 
1398
            Py_ssize_t i;
 
1399
            TRACE(("|%p|%p|GROUPREF %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1400
            group = context.pattern_ptr[0]; // Zero-based index. Note that externally group 0 is the entire matched string.
 
1401
            group_start = context.mark[group * 2];
 
1402
            group_end = context.mark[group * 2 + 1];
 
1403
            if (group_start == NULL || group_end == NULL)
 
1404
                goto backtrack;
 
1405
            length = group_end - group_start;
 
1406
            if (length > context.text_end - context.text_ptr)
 
1407
                goto backtrack;
 
1408
            i = 0;
 
1409
            while (i < length) {
 
1410
                if (context.text_ptr[i] != group_start[i])
 
1411
                    goto backtrack;
 
1412
                i++;
 
1413
            }
 
1414
            context.pattern_ptr++;
 
1415
            context.text_ptr += length;
 
1416
            break;
 
1417
        }
 
1418
        case SRE_OP_GROUPREF_EXISTS:
 
1419
        {
 
1420
            // Whether backreference exists.
 
1421
            // <GROUPREF_EXISTS> <group> <skip> code_yes <JUMP> <skip> code_no
 
1422
            Py_ssize_t group;
 
1423
            SRE_CHAR* group_start;
 
1424
            SRE_CHAR* group_end;
 
1425
            TRACE(("|%p|%p|GROUPREF_EXISTS %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1426
            group = context.pattern_ptr[0]; // Zero-based index. Note that externally group 0 is the entire matched string.
 
1427
            group_start = context.mark[group * 2];
 
1428
            group_end = context.mark[group * 2 + 1];
 
1429
            if (group_start == NULL || group_end == NULL)
 
1430
                context.pattern_ptr += context.pattern_ptr[1];
 
1431
            else
 
1432
                context.pattern_ptr += 2;
 
1433
            break;
 
1434
        }
 
1435
        case SRE_OP_GROUPREF_IGNORE:
 
1436
        {
 
1437
            // Match backreference, ignoring case.
 
1438
            // <GROUPREF_IGNORE> <group>
 
1439
            Py_ssize_t group;
 
1440
            SRE_CHAR* group_start;
 
1441
            SRE_CHAR* group_end;
 
1442
            Py_ssize_t length;
 
1443
            Py_ssize_t i;
 
1444
            TRACE(("|%p|%p|GROUPREF_IGNORE %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1445
            group = context.pattern_ptr[0]; // Zero-based index. Note that externally group 0 is the entire matched string.
 
1446
            group_start = context.mark[group * 2];
 
1447
            group_end = context.mark[group * 2 + 1];
 
1448
            if (group_start == NULL || group_end == NULL)
 
1449
                goto backtrack;
 
1450
            length = group_end - group_start;
 
1451
            if (length > context.text_end - context.text_ptr)
 
1452
                goto backtrack;
 
1453
            i = 0;
 
1454
            while (i < length) {
 
1455
                if (state->lower(context.text_ptr[i]) != state->lower(group_start[i]))
 
1456
                    goto backtrack;
 
1457
                i++;
 
1458
            }
 
1459
            context.pattern_ptr++;
 
1460
            context.text_ptr += length;
 
1461
            break;
 
1462
        }
 
1463
        case SRE_OP_GROUPREF_IGNORE_REV:
 
1464
        {
 
1465
            // Match backreference, ignoring case.
 
1466
            // <GROUPREF_IGNORE_REV> <group>
 
1467
            Py_ssize_t group;
 
1468
            SRE_CHAR* group_start;
 
1469
            SRE_CHAR* group_end;
 
1470
            Py_ssize_t length;
 
1471
            Py_ssize_t i;
 
1472
            TRACE(("|%p|%p|GROUPREF_IGNORE_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1473
            group = context.pattern_ptr[0]; // Zero-based index. Note that externally group 0 is the entire matched string.
 
1474
            group_start = context.mark[group * 2];
 
1475
            group_end = context.mark[group * 2 + 1];
 
1476
            if (group_start == NULL || group_end == NULL)
 
1477
                goto backtrack;
 
1478
            length = group_end - group_start;
 
1479
            if (length > context.text_ptr - context.text_start)
 
1480
                goto backtrack;
 
1481
            context.text_ptr -= length;
 
1482
            i = 0;
 
1483
            while (i < length) {
 
1484
                if (state->lower(context.text_ptr[i]) != state->lower(group_start[i]))
 
1485
                    goto backtrack;
 
1486
                i++;
 
1487
            }
 
1488
            context.pattern_ptr++;
 
1489
            break;
 
1490
        }
 
1491
        case SRE_OP_GROUPREF_REV:
 
1492
        {
 
1493
            // Match backreference.
 
1494
            // <GROUPREF_REV> <group>
 
1495
            Py_ssize_t group;
 
1496
            SRE_CHAR* group_start;
 
1497
            SRE_CHAR* group_end;
 
1498
            Py_ssize_t length;
 
1499
            Py_ssize_t i;
 
1500
            TRACE(("|%p|%p|GROUPREF_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1501
            group = context.pattern_ptr[0]; // Zero-based index. Note that externally group 0 is the entire matched string.
 
1502
            group_start = context.mark[group * 2];
 
1503
            group_end = context.mark[group * 2 + 1];
 
1504
            if (group_start == NULL || group_end == NULL)
 
1505
                goto backtrack;
 
1506
            length = group_end - group_start;
 
1507
            if (length > context.text_ptr - context.text_start)
 
1508
                goto backtrack;
 
1509
            context.text_ptr -= length;
 
1510
            i = 0;
 
1511
            while (i < length) {
 
1512
                if (context.text_ptr[i] != group_start[i])
 
1513
                    goto backtrack;
 
1514
                i++;
 
1515
            }
 
1516
            context.pattern_ptr++;
 
1517
            break;
 
1518
        }
940
1519
        case SRE_OP_IN:
941
 
            /* match set member (or non_member) */
942
 
            /* <IN> <skip> <set> */
943
 
            TRACE(("|%p|%p|IN\n", ctx->pattern, ctx->ptr));
944
 
            if (ctx->ptr >= end || !SRE_CHARSET(ctx->pattern + 1, *ctx->ptr))
945
 
                RETURN_FAILURE;
946
 
            ctx->pattern += ctx->pattern[0];
947
 
            ctx->ptr++;
948
 
            break;
949
 
 
950
 
        case SRE_OP_LITERAL_IGNORE:
951
 
            TRACE(("|%p|%p|LITERAL_IGNORE %d\n",
952
 
                   ctx->pattern, ctx->ptr, ctx->pattern[0]));
953
 
            if (ctx->ptr >= end ||
954
 
                state->lower(*ctx->ptr) != state->lower(*ctx->pattern))
955
 
                RETURN_FAILURE;
956
 
            ctx->pattern++;
957
 
            ctx->ptr++;
958
 
            break;
959
 
 
960
 
        case SRE_OP_NOT_LITERAL_IGNORE:
961
 
            TRACE(("|%p|%p|NOT_LITERAL_IGNORE %d\n",
962
 
                   ctx->pattern, ctx->ptr, *ctx->pattern));
963
 
            if (ctx->ptr >= end ||
964
 
                state->lower(*ctx->ptr) == state->lower(*ctx->pattern))
965
 
                RETURN_FAILURE;
966
 
            ctx->pattern++;
967
 
            ctx->ptr++;
968
 
            break;
969
 
 
 
1520
            // Match set member.
 
1521
            // <IN> <set>
 
1522
            TRACE(("|%p|%p|IN\n", context.pattern_ptr, context.text_ptr));
 
1523
            if (context.text_ptr >= context.text_end || !SRE_IN(context.pattern_ptr, context.text_ptr[0]))
 
1524
                goto backtrack;
 
1525
            context.pattern_ptr += context.pattern_ptr[0];
 
1526
            context.text_ptr++;
 
1527
            break;
970
1528
        case SRE_OP_IN_IGNORE:
971
 
            TRACE(("|%p|%p|IN_IGNORE\n", ctx->pattern, ctx->ptr));
972
 
            if (ctx->ptr >= end
973
 
                || !SRE_CHARSET(ctx->pattern+1,
974
 
                                (SRE_CODE)state->lower(*ctx->ptr)))
975
 
                RETURN_FAILURE;
976
 
            ctx->pattern += ctx->pattern[0];
977
 
            ctx->ptr++;
978
 
            break;
979
 
 
 
1529
            // Match set member, ignoring case.
 
1530
            // <IN_IGNORE> <set>
 
1531
            TRACE(("|%p|%p|IN_IGNORE\n", context.pattern_ptr, context.text_ptr));
 
1532
            if (context.text_ptr >= context.text_end || !SRE_IN(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
1533
                goto backtrack;
 
1534
            context.pattern_ptr += context.pattern_ptr[0];
 
1535
            context.text_ptr++;
 
1536
            break;
 
1537
        case SRE_OP_IN_IGNORE_REV:
 
1538
            // Match set member, ignoring case.
 
1539
            // <IN_IGNORE_REV> <set>
 
1540
            TRACE(("|%p|%p|IN_IGNORE_REV\n", context.pattern_ptr, context.text_ptr));
 
1541
            if (context.text_ptr <= context.text_start || !SRE_IN(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
1542
                goto backtrack;
 
1543
            context.pattern_ptr += context.pattern_ptr[0];
 
1544
            context.text_ptr--;
 
1545
            break;
 
1546
        case SRE_OP_IN_REV:
 
1547
            // Match set member.
 
1548
            // <IN_REV> <set>
 
1549
            TRACE(("|%p|%p|IN_REV\n", context.pattern_ptr, context.text_ptr));
 
1550
            if (context.text_ptr <= context.text_start || !SRE_IN(context.pattern_ptr, context.text_ptr[-1]))
 
1551
                goto backtrack;
 
1552
            context.pattern_ptr += context.pattern_ptr[0];
 
1553
            context.text_ptr--;
 
1554
            break;
980
1555
        case SRE_OP_JUMP:
981
 
        case SRE_OP_INFO:
982
 
            /* jump forward */
983
 
            /* <JUMP> <offset> */
984
 
            TRACE(("|%p|%p|JUMP %d\n", ctx->pattern,
985
 
                   ctx->ptr, ctx->pattern[0]));
986
 
            ctx->pattern += ctx->pattern[0];
987
 
            break;
988
 
 
989
 
        case SRE_OP_BRANCH:
990
 
            /* alternation */
991
 
            /* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
992
 
            TRACE(("|%p|%p|BRANCH\n", ctx->pattern, ctx->ptr));
993
 
            LASTMARK_SAVE();
994
 
            ctx->u.rep = state->repeat;
995
 
            if (ctx->u.rep)
996
 
                MARK_PUSH(ctx->lastmark);
997
 
            for (; ctx->pattern[0]; ctx->pattern += ctx->pattern[0]) {
998
 
                if (ctx->pattern[1] == SRE_OP_LITERAL &&
999
 
                    (ctx->ptr >= end ||
1000
 
                     (SRE_CODE) *ctx->ptr != ctx->pattern[2]))
1001
 
                    continue;
1002
 
                if (ctx->pattern[1] == SRE_OP_IN &&
1003
 
                    (ctx->ptr >= end ||
1004
 
                     !SRE_CHARSET(ctx->pattern + 3, (SRE_CODE) *ctx->ptr)))
1005
 
                    continue;
1006
 
                state->ptr = ctx->ptr;
1007
 
                DO_JUMP(JUMP_BRANCH, jump_branch, ctx->pattern+1);
1008
 
                if (ret) {
1009
 
                    if (ctx->u.rep)
1010
 
                        MARK_POP_DISCARD(ctx->lastmark);
1011
 
                    RETURN_ON_ERROR(ret);
1012
 
                    RETURN_SUCCESS;
1013
 
                }
1014
 
                if (ctx->u.rep)
1015
 
                    MARK_POP_KEEP(ctx->lastmark);
1016
 
                LASTMARK_RESTORE();
1017
 
            }
1018
 
            if (ctx->u.rep)
1019
 
                MARK_POP_DISCARD(ctx->lastmark);
1020
 
            RETURN_FAILURE;
1021
 
 
1022
 
        case SRE_OP_REPEAT_ONE:
1023
 
            /* match repeated sequence (maximizing regexp) */
1024
 
 
1025
 
            /* this operator only works if the repeated item is
1026
 
               exactly one character wide, and we're not already
1027
 
               collecting backtracking points.  for other cases,
1028
 
               use the MAX_REPEAT operator */
1029
 
 
1030
 
            /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
1031
 
 
1032
 
            TRACE(("|%p|%p|REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
1033
 
                   ctx->pattern[1], ctx->pattern[2]));
1034
 
 
1035
 
            if (ctx->ptr + ctx->pattern[1] > end)
1036
 
                RETURN_FAILURE; /* cannot match */
1037
 
 
1038
 
            state->ptr = ctx->ptr;
1039
 
 
1040
 
            ret = SRE_COUNT(state, ctx->pattern+3, ctx->pattern[2]);
1041
 
            RETURN_ON_ERROR(ret);
1042
 
            DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1043
 
            ctx->count = ret;
1044
 
            ctx->ptr += ctx->count;
1045
 
 
1046
 
            /* when we arrive here, count contains the number of
1047
 
               matches, and ctx->ptr points to the tail of the target
1048
 
               string.  check if the rest of the pattern matches,
1049
 
               and backtrack if not. */
1050
 
 
1051
 
            if (ctx->count < (Py_ssize_t) ctx->pattern[1])
1052
 
                RETURN_FAILURE;
1053
 
 
1054
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS) {
1055
 
                /* tail is empty.  we're finished */
1056
 
                state->ptr = ctx->ptr;
1057
 
                RETURN_SUCCESS;
1058
 
            }
1059
 
 
1060
 
            LASTMARK_SAVE();
1061
 
 
1062
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_LITERAL) {
1063
 
                /* tail starts with a literal. skip positions where
1064
 
                   the rest of the pattern cannot possibly match */
1065
 
                ctx->u.chr = ctx->pattern[ctx->pattern[0]+1];
1066
 
                for (;;) {
1067
 
                    while (ctx->count >= (Py_ssize_t) ctx->pattern[1] &&
1068
 
                           (ctx->ptr >= end || *ctx->ptr != ctx->u.chr)) {
1069
 
                        ctx->ptr--;
1070
 
                        ctx->count--;
1071
 
                    }
1072
 
                    if (ctx->count < (Py_ssize_t) ctx->pattern[1])
1073
 
                        break;
1074
 
                    state->ptr = ctx->ptr;
1075
 
                    DO_JUMP(JUMP_REPEAT_ONE_1, jump_repeat_one_1,
1076
 
                            ctx->pattern+ctx->pattern[0]);
1077
 
                    if (ret) {
1078
 
                        RETURN_ON_ERROR(ret);
1079
 
                        RETURN_SUCCESS;
1080
 
                    }
1081
 
 
1082
 
                    LASTMARK_RESTORE();
1083
 
 
1084
 
                    ctx->ptr--;
1085
 
                    ctx->count--;
1086
 
                }
1087
 
 
1088
 
            } else {
1089
 
                /* general case */
1090
 
                while (ctx->count >= (Py_ssize_t) ctx->pattern[1]) {
1091
 
                    state->ptr = ctx->ptr;
1092
 
                    DO_JUMP(JUMP_REPEAT_ONE_2, jump_repeat_one_2,
1093
 
                            ctx->pattern+ctx->pattern[0]);
1094
 
                    if (ret) {
1095
 
                        RETURN_ON_ERROR(ret);
1096
 
                        RETURN_SUCCESS;
1097
 
                    }
1098
 
                    ctx->ptr--;
1099
 
                    ctx->count--;
1100
 
                    LASTMARK_RESTORE();
1101
 
                }
1102
 
            }
1103
 
            RETURN_FAILURE;
1104
 
 
1105
 
        case SRE_OP_MIN_REPEAT_ONE:
1106
 
            /* match repeated sequence (minimizing regexp) */
1107
 
 
1108
 
            /* this operator only works if the repeated item is
1109
 
               exactly one character wide, and we're not already
1110
 
               collecting backtracking points.  for other cases,
1111
 
               use the MIN_REPEAT operator */
1112
 
 
1113
 
            /* <MIN_REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
1114
 
 
1115
 
            TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
1116
 
                   ctx->pattern[1], ctx->pattern[2]));
1117
 
 
1118
 
            if (ctx->ptr + ctx->pattern[1] > end)
1119
 
                RETURN_FAILURE; /* cannot match */
1120
 
 
1121
 
            state->ptr = ctx->ptr;
1122
 
 
1123
 
            if (ctx->pattern[1] == 0)
1124
 
                ctx->count = 0;
1125
 
            else {
1126
 
                /* count using pattern min as the maximum */
1127
 
                ret = SRE_COUNT(state, ctx->pattern+3, ctx->pattern[1]);
1128
 
                RETURN_ON_ERROR(ret);
1129
 
                DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1130
 
                if (ret < (Py_ssize_t) ctx->pattern[1])
1131
 
                    /* didn't match minimum number of times */
1132
 
                    RETURN_FAILURE;
1133
 
                /* advance past minimum matches of repeat */
1134
 
                ctx->count = ret;
1135
 
                ctx->ptr += ctx->count;
1136
 
            }
1137
 
 
1138
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS) {
1139
 
                /* tail is empty.  we're finished */
1140
 
                state->ptr = ctx->ptr;
1141
 
                RETURN_SUCCESS;
1142
 
 
1143
 
            } else {
1144
 
                /* general case */
1145
 
                LASTMARK_SAVE();
1146
 
                while ((Py_ssize_t)ctx->pattern[2] == 65535
1147
 
                       || ctx->count <= (Py_ssize_t)ctx->pattern[2]) {
1148
 
                    state->ptr = ctx->ptr;
1149
 
                    DO_JUMP(JUMP_MIN_REPEAT_ONE,jump_min_repeat_one,
1150
 
                            ctx->pattern+ctx->pattern[0]);
1151
 
                    if (ret) {
1152
 
                        RETURN_ON_ERROR(ret);
1153
 
                        RETURN_SUCCESS;
1154
 
                    }
1155
 
                    state->ptr = ctx->ptr;
1156
 
                    ret = SRE_COUNT(state, ctx->pattern+3, 1);
1157
 
                    RETURN_ON_ERROR(ret);
1158
 
                    DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1159
 
                    if (ret == 0)
1160
 
                        break;
1161
 
                    assert(ret == 1);
1162
 
                    ctx->ptr++;
1163
 
                    ctx->count++;
1164
 
                    LASTMARK_RESTORE();
1165
 
                }
1166
 
            }
1167
 
            RETURN_FAILURE;
1168
 
 
1169
 
        case SRE_OP_POSSESSIVE_ONE:
1170
 
            /* match repeated sequence (maximizing regexp) without
1171
 
               backtracking */
1172
 
 
1173
 
            /* this operator only works if the repeated item is
1174
 
               exactly one character wide, and we're not already
1175
 
               collecting backtracking points.  for other cases,
1176
 
               use the MAX_REPEAT operator */
1177
 
 
1178
 
            /* <POSSESSIVE_ONE> <skip> <1=min> <2=max> item <SUCCESS>
1179
 
               tail */
1180
 
 
1181
 
            TRACE(("|%p|%p|POSSESSIVE_ONE %d %d\n", ctx->pattern,
1182
 
                   ctx->ptr, ctx->pattern[1], ctx->pattern[2]));
1183
 
 
1184
 
            if (ctx->ptr + ctx->pattern[1] > end) {
1185
 
                RETURN_FAILURE; /* cannot match */
1186
 
            }
1187
 
 
1188
 
            state->ptr = ctx->ptr;
1189
 
 
1190
 
            ret = SRE_COUNT(state, ctx->pattern + 3, ctx->pattern[2]);
1191
 
            RETURN_ON_ERROR(ret);
1192
 
            DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1193
 
            ctx->count = ret;
1194
 
            ctx->ptr += ctx->count;
1195
 
 
1196
 
            /* when we arrive here, count contains the number of
1197
 
               matches, and ctx->ptr points to the tail of the target
1198
 
               string.  check if the rest of the pattern matches,
1199
 
               and fail if not. */
1200
 
 
1201
 
            /* Test for not enough repetitions in match */
1202
 
            if (ctx->count < (Py_ssize_t) ctx->pattern[1]) {
1203
 
                RETURN_FAILURE;
1204
 
            }
1205
 
 
1206
 
            /* Update the pattern to point to the next op code */
1207
 
            ctx->pattern += ctx->pattern[0];
1208
 
 
1209
 
            /* Let the tail be evaluated separately and consider this
1210
 
               match successful. */
1211
 
            if (*ctx->pattern == SRE_OP_SUCCESS) {
1212
 
                /* tail is empty.  we're finished */
1213
 
                state->ptr = ctx->ptr;
1214
 
                RETURN_SUCCESS;
1215
 
            }
1216
 
 
1217
 
            /* Attempt to match the rest of the string */
1218
 
            break;
1219
 
 
1220
 
        case SRE_OP_REPEAT:
1221
 
            /* create repeat context.  all the hard work is done
1222
 
               by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */
1223
 
            /* <REPEAT> <skip> <1=min> <2=max> item <UNTIL> tail */
1224
 
            TRACE(("|%p|%p|REPEAT %d %d\n", ctx->pattern, ctx->ptr,
1225
 
                   ctx->pattern[1], ctx->pattern[2]));
1226
 
 
1227
 
            /* install new repeat context */
1228
 
            ctx->u.rep = (SRE_REPEAT*) PyObject_MALLOC(sizeof(*ctx->u.rep));
1229
 
            if (!ctx->u.rep) {
1230
 
                PyErr_NoMemory();
1231
 
                RETURN_FAILURE;
1232
 
            }
1233
 
            ctx->u.rep->count = -1;
1234
 
            ctx->u.rep->pattern = ctx->pattern;
1235
 
            ctx->u.rep->prev = state->repeat;
1236
 
            ctx->u.rep->last_ptr = NULL;
1237
 
            state->repeat = ctx->u.rep;
1238
 
 
1239
 
            state->ptr = ctx->ptr;
1240
 
            DO_JUMP(JUMP_REPEAT, jump_repeat, ctx->pattern+ctx->pattern[0]);
1241
 
            state->repeat = ctx->u.rep->prev;
1242
 
            PyObject_FREE(ctx->u.rep);
1243
 
 
1244
 
            if (ret) {
1245
 
                RETURN_ON_ERROR(ret);
1246
 
                RETURN_SUCCESS;
1247
 
            }
1248
 
            RETURN_FAILURE;
1249
 
 
1250
 
        case SRE_OP_MAX_UNTIL:
1251
 
            /* maximizing repeat */
1252
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
1253
 
 
1254
 
            /* FIXME: we probably need to deal with zero-width
1255
 
               matches in here... */
1256
 
 
1257
 
            ctx->u.rep = state->repeat;
1258
 
            if (!ctx->u.rep)
1259
 
                RETURN_ERROR(SRE_ERROR_STATE);
1260
 
 
1261
 
            state->ptr = ctx->ptr;
1262
 
 
1263
 
            ctx->count = ctx->u.rep->count+1;
1264
 
 
1265
 
            TRACE(("|%p|%p|MAX_UNTIL %d\n", ctx->pattern,
1266
 
                   ctx->ptr, ctx->count));
1267
 
 
1268
 
            if (ctx->count < ctx->u.rep->pattern[1]) {
1269
 
                /* not enough matches */
1270
 
                ctx->u.rep->count = ctx->count;
1271
 
                DO_JUMP(JUMP_MAX_UNTIL_1, jump_max_until_1,
1272
 
                        ctx->u.rep->pattern+3);
1273
 
                if (ret) {
1274
 
                    RETURN_ON_ERROR(ret);
1275
 
                    RETURN_SUCCESS;
1276
 
                }
1277
 
                ctx->u.rep->count = ctx->count-1;
1278
 
                state->ptr = ctx->ptr;
1279
 
                RETURN_FAILURE;
1280
 
            }
1281
 
 
1282
 
            if ((ctx->count < ctx->u.rep->pattern[2] ||
1283
 
                ctx->u.rep->pattern[2] == 65535) &&
1284
 
                state->ptr != ctx->u.rep->last_ptr) {
1285
 
                /* we may have enough matches, but if we can
1286
 
                   match another item, do so */
1287
 
                ctx->u.rep->count = ctx->count;
1288
 
                LASTMARK_SAVE();
1289
 
                MARK_PUSH(ctx->lastmark);
1290
 
                /* zero-width match protection */
1291
 
                DATA_PUSH(&ctx->u.rep->last_ptr);
1292
 
                ctx->u.rep->last_ptr = state->ptr;
1293
 
                DO_JUMP(JUMP_MAX_UNTIL_2, jump_max_until_2,
1294
 
                        ctx->u.rep->pattern+3);
1295
 
                DATA_POP(&ctx->u.rep->last_ptr);
1296
 
                if (ret) {
1297
 
                    MARK_POP_DISCARD(ctx->lastmark);
1298
 
                    RETURN_ON_ERROR(ret);
1299
 
                    RETURN_SUCCESS;
1300
 
                }
1301
 
                MARK_POP(ctx->lastmark);
1302
 
                LASTMARK_RESTORE();
1303
 
                ctx->u.rep->count = ctx->count-1;
1304
 
                state->ptr = ctx->ptr;
1305
 
            }
1306
 
 
1307
 
            /* cannot match more repeated items here.  make sure the
1308
 
               tail matches */
1309
 
            state->repeat = ctx->u.rep->prev;
1310
 
            DO_JUMP(JUMP_MAX_UNTIL_3, jump_max_until_3, ctx->pattern);
1311
 
            RETURN_ON_SUCCESS(ret);
1312
 
            state->repeat = ctx->u.rep;
1313
 
            state->ptr = ctx->ptr;
1314
 
            RETURN_FAILURE;
1315
 
 
1316
 
        case SRE_OP_MIN_UNTIL:
1317
 
            /* minimizing repeat */
1318
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
1319
 
 
1320
 
            ctx->u.rep = state->repeat;
1321
 
            if (!ctx->u.rep)
1322
 
                RETURN_ERROR(SRE_ERROR_STATE);
1323
 
 
1324
 
            state->ptr = ctx->ptr;
1325
 
 
1326
 
            ctx->count = ctx->u.rep->count+1;
1327
 
 
1328
 
            TRACE(("|%p|%p|MIN_UNTIL %d %p\n", ctx->pattern,
1329
 
                   ctx->ptr, ctx->count, ctx->u.rep->pattern));
1330
 
 
1331
 
            if (ctx->count < ctx->u.rep->pattern[1]) {
1332
 
                /* not enough matches */
1333
 
                ctx->u.rep->count = ctx->count;
1334
 
                DO_JUMP(JUMP_MIN_UNTIL_1, jump_min_until_1,
1335
 
                        ctx->u.rep->pattern+3);
1336
 
                if (ret) {
1337
 
                    RETURN_ON_ERROR(ret);
1338
 
                    RETURN_SUCCESS;
1339
 
                }
1340
 
                ctx->u.rep->count = ctx->count-1;
1341
 
                state->ptr = ctx->ptr;
1342
 
                RETURN_FAILURE;
1343
 
            }
1344
 
 
1345
 
            LASTMARK_SAVE();
1346
 
 
1347
 
            /* see if the tail matches */
1348
 
            state->repeat = ctx->u.rep->prev;
1349
 
            DO_JUMP(JUMP_MIN_UNTIL_2, jump_min_until_2, ctx->pattern);
1350
 
            if (ret) {
1351
 
                RETURN_ON_ERROR(ret);
1352
 
                RETURN_SUCCESS;
1353
 
            }
1354
 
 
1355
 
            state->repeat = ctx->u.rep;
1356
 
            state->ptr = ctx->ptr;
1357
 
 
1358
 
            LASTMARK_RESTORE();
1359
 
 
1360
 
            if (ctx->count >= ctx->u.rep->pattern[2]
1361
 
                && ctx->u.rep->pattern[2] != 65535)
1362
 
                RETURN_FAILURE;
1363
 
 
1364
 
            ctx->u.rep->count = ctx->count;
1365
 
            DO_JUMP(JUMP_MIN_UNTIL_3,jump_min_until_3,
1366
 
                    ctx->u.rep->pattern+3);
1367
 
            if (ret) {
1368
 
                RETURN_ON_ERROR(ret);
1369
 
                RETURN_SUCCESS;
1370
 
            }
1371
 
            ctx->u.rep->count = ctx->count-1;
1372
 
            state->ptr = ctx->ptr;
1373
 
            RETURN_FAILURE;
1374
 
 
1375
 
        case SRE_OP_POSSESSIVE_REPEAT:
1376
 
            /* create possessive repeat contexts. */
1377
 
            /* <POSSESSIVE_REPEAT> <skip> <1=min> <2=max> pattern
1378
 
               <SUCCESS> tail */
1379
 
            TRACE(("|%p|%p|POSSESSIVE_REPEAT %d %d\n", ctx->pattern,
1380
 
                   ctx->ptr, ctx->pattern[1], ctx->pattern[2]));
1381
 
 
1382
 
            /* Set the global Input pointer to this context's Input
1383
 
               pointer */
1384
 
            state->ptr = ctx->ptr;
1385
 
 
1386
 
            /* Initialize Count to 0 */
1387
 
            ctx->count = 0;
1388
 
 
1389
 
            /* Check for minimum required matches. */
1390
 
            while (ctx->count < (int)ctx->pattern[1]) {
1391
 
                /* not enough matches */
1392
 
                DO_JUMP(JUMP_POSS_REPEAT_1, jump_poss_repeat_1,
1393
 
                        &ctx->pattern[3]);
1394
 
                if (ret) {
1395
 
                    RETURN_ON_ERROR(ret);
1396
 
                    ctx->count++;
1397
 
                }
1398
 
                else {
1399
 
                    state->ptr = ctx->ptr;
1400
 
                    RETURN_FAILURE;
1401
 
                }
1402
 
            }
1403
 
                
1404
 
            /* Clear the context's Input stream pointer so that it
1405
 
               doesn't match the global state so that the while loop can
1406
 
               be entered. */
1407
 
            ctx->ptr = NULL;
1408
 
 
1409
 
            /* Keep trying to parse the <pattern> sub-pattern until the
1410
 
               end is reached, creating a new context each time. */
1411
 
            while ((ctx->count < (int)ctx->pattern[2] ||
1412
 
                    (int)ctx->pattern[2] == 65535) &&
1413
 
                   state->ptr != ctx->ptr) {
1414
 
                /* Save the Capture Group Marker state into the current
1415
 
                   Context and back up the current highest number
1416
 
                   Capture Group marker. */
1417
 
                LASTMARK_SAVE();
1418
 
                MARK_PUSH(ctx->lastmark);
1419
 
 
1420
 
                /* zero-width match protection */
1421
 
                /* Set the context's Input Stream pointer to be the
1422
 
                   current Input Stream pointer from the global
1423
 
                   state.  When the loop reaches the next iteration,
1424
 
                   the context will then store the last known good
1425
 
                   position with the global state holding the Input
1426
 
                   Input Stream position that has been updated with
1427
 
                   the most recent match.  Thus, if state's Input
1428
 
                   stream remains the same as the one stored in the
1429
 
                   current Context, we know we have successfully
1430
 
                   matched an empty string and that all subsequent
1431
 
                   matches will also be the empty string until the
1432
 
                   maximum number of matches are counted, and because
1433
 
                   of this, we could immediately stop at that point and
1434
 
                   consider this match successful. */
1435
 
                ctx->ptr = state->ptr;
1436
 
 
1437
 
                /* We have not reached the maximin matches, so try to
1438
 
                   match once more. */
1439
 
                DO_JUMP(JUMP_POSS_REPEAT_2, jump_poss_repeat_2,
1440
 
                        &ctx->pattern[3]);
1441
 
 
1442
 
                /* Check to see if the last attempted match
1443
 
                   succeeded. */
1444
 
                if (ret) {
1445
 
                    /* Drop the saved highest number Capture Group
1446
 
                       marker saved above and use the newly updated
1447
 
                       value. */
1448
 
                    MARK_POP_DISCARD(ctx->lastmark);
1449
 
                    RETURN_ON_ERROR(ret);
1450
 
 
1451
 
                    /* Success, increment the count. */
1452
 
                    ctx->count++;
1453
 
                }
1454
 
                /* Last attempted match failed. */
1455
 
                else {
1456
 
                    /* Restore the previously saved highest number
1457
 
                       Capture Group marker since the last iteration
1458
 
                       did not match, then restore that to the global
1459
 
                       state. */
1460
 
                    MARK_POP(ctx->lastmark);
1461
 
                    LASTMARK_RESTORE();
1462
 
 
1463
 
                    /* We have sufficient matches, so exit loop. */
1464
 
                    break;
1465
 
                }
1466
 
            }
1467
 
 
1468
 
            /* Evaluate Tail */
1469
 
            /* Jump to end of pattern indicated by skip. */
1470
 
            ctx->pattern += ctx->pattern[0];
1471
 
            ctx->ptr = state->ptr;
1472
 
            break;
1473
 
 
1474
 
        case SRE_OP_ATOMIC_GROUP:
1475
 
            /* Atomic Group Sub Pattern */
1476
 
            /* <ATOMIC_GROUP> <skip> pattern <SUCCESS> tail */
1477
 
            TRACE(("|%p|%p|ATOMIC_GROUP\n", ctx->pattern, ctx->ptr));
1478
 
 
1479
 
            /* Set the global Input pointer to this context's Input
1480
 
            pointer */
1481
 
            state->ptr = ctx->ptr;
1482
 
 
1483
 
            /* Evaluate the Atomic Group in a new context, terminating
1484
 
               when the end of the group, represented by a SUCCESS op
1485
 
               code, is reached. */
1486
 
            /* Group Pattern begins at an offset of 1 code. */
1487
 
            DO_JUMP(JUMP_ATOMIC_GROUP, jump_atomic_group,
1488
 
                    &ctx->pattern[1]);
1489
 
 
1490
 
            /* Test Exit Condition */
1491
 
            RETURN_ON_ERROR(ret);
1492
 
 
1493
 
            if (ret == 0) {
1494
 
                /* Atomic Group failed to Match. */
1495
 
                state->ptr = ctx->ptr;
1496
 
                RETURN_FAILURE;
1497
 
            }
1498
 
                
1499
 
            /* Evaluate Tail */
1500
 
            /* Jump to end of pattern indicated by skip. */
1501
 
            ctx->pattern += ctx->pattern[0];
1502
 
            ctx->ptr = state->ptr;
1503
 
            break;
1504
 
            
1505
 
        case SRE_OP_GROUPREF:
1506
 
            /* match backreference */
1507
 
            TRACE(("|%p|%p|GROUPREF %d\n", , ctx->pattern[0]));
1508
 
            i = ctx->pattern[0];
1509
 
            {
1510
 
                Py_ssize_t groupref = i+i;
1511
 
                if (groupref >= state->lastmark) {
1512
 
                    RETURN_FAILURE;
1513
 
                } else {
1514
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1515
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1516
 
                    if (!p || !e || e < p)
1517
 
                        RETURN_FAILURE;
1518
 
                    while (p < e) {
1519
 
                        if (ctx->ptr >= end || *ctx->ptr != *p)
1520
 
                            RETURN_FAILURE;
1521
 
                        p++; ctx->ptr++;
1522
 
                    }
1523
 
                }
1524
 
            }
1525
 
            ctx->pattern++;
1526
 
            break;
1527
 
 
1528
 
        case SRE_OP_GROUPREF_IGNORE:
1529
 
            /* match backreference */
1530
 
            TRACE(("|%p|%p|GROUPREF_IGNORE %d\n", ctx->pattern,
1531
 
                   ctx->ptr, ctx->pattern[0]));
1532
 
            i = ctx->pattern[0];
1533
 
            {
1534
 
                Py_ssize_t groupref = i+i;
1535
 
                if (groupref >= state->lastmark) {
1536
 
                    RETURN_FAILURE;
1537
 
                } else {
1538
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1539
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1540
 
                    if (!p || !e || e < p)
1541
 
                        RETURN_FAILURE;
1542
 
                    while (p < e) {
1543
 
                        if (ctx->ptr >= end ||
1544
 
                            state->lower(*ctx->ptr) != state->lower(*p))
1545
 
                            RETURN_FAILURE;
1546
 
                        p++; ctx->ptr++;
1547
 
                    }
1548
 
                }
1549
 
            }
1550
 
            ctx->pattern++;
1551
 
            break;
1552
 
 
1553
 
        case SRE_OP_GROUPREF_EXISTS:
1554
 
            TRACE(("|%p|%p|GROUPREF_EXISTS %d\n", ctx->pattern,
1555
 
                   ctx->ptr, ctx->pattern[0]));
1556
 
            /* <GROUPREF_EXISTS> <group> <skip> codeyes <JUMP> codeno ... */
1557
 
            i = ctx->pattern[0];
1558
 
            {
1559
 
                Py_ssize_t groupref = i+i;
1560
 
                if (groupref >= state->lastmark) {
1561
 
                    ctx->pattern += ctx->pattern[1];
1562
 
                    break;
1563
 
                } else {
1564
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1565
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1566
 
                    if (!p || !e || e < p) {
1567
 
                        ctx->pattern += ctx->pattern[1];
1568
 
                        break;
1569
 
                    }
1570
 
                }
1571
 
            }
1572
 
            ctx->pattern += 2;
1573
 
            break;
1574
 
 
1575
 
        case SRE_OP_ASSERT:
1576
 
            /* assert subpattern */
1577
 
            /* <ASSERT> <skip> <back> <pattern> */
1578
 
            TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern,
1579
 
                   ctx->ptr, ctx->pattern[1]));
1580
 
            state->ptr = ctx->ptr - ctx->pattern[1];
1581
 
            if (state->ptr < state->beginning)
1582
 
                RETURN_FAILURE;
1583
 
            DO_JUMP(JUMP_ASSERT, jump_assert, ctx->pattern+2);
1584
 
            RETURN_ON_FAILURE(ret);
1585
 
            ctx->pattern += ctx->pattern[0];
1586
 
            break;
1587
 
 
1588
 
        case SRE_OP_ASSERT_NOT:
1589
 
            /* assert not subpattern */
1590
 
            /* <ASSERT_NOT> <skip> <back> <pattern> */
1591
 
            TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern,
1592
 
                   ctx->ptr, ctx->pattern[1]));
1593
 
            state->ptr = ctx->ptr - ctx->pattern[1];
1594
 
            if (state->ptr >= state->beginning) {
1595
 
                DO_JUMP(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2);
1596
 
                if (ret) {
1597
 
                    RETURN_ON_ERROR(ret);
1598
 
                    RETURN_FAILURE;
1599
 
                }
1600
 
            }
1601
 
            ctx->pattern += ctx->pattern[0];
1602
 
            break;
1603
 
 
1604
 
        case SRE_OP_FAILURE:
1605
 
            /* immediate failure */
1606
 
            TRACE(("|%p|%p|FAILURE\n", ctx->pattern, ctx->ptr));
1607
 
            RETURN_FAILURE;
1608
 
 
1609
 
        default:
1610
 
            TRACE(("|%p|%p|UNKNOWN %d\n", ctx->pattern, ctx->ptr,
1611
 
                   ctx->pattern[-1]));
1612
 
            RETURN_ERROR(SRE_ERROR_ILLEGAL);
1613
 
        }
1614
 
    }
1615
 
 
1616
 
exit:
1617
 
    ctx_pos = ctx->last_ctx_pos;
1618
 
    jump = ctx->jump;
1619
 
    DATA_POP_DISCARD(ctx);
1620
 
    if (ctx_pos == -1)
1621
 
        return ret;
1622
 
    DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1623
 
 
1624
 
    switch (jump) {
1625
 
        case JUMP_MAX_UNTIL_2:
1626
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_2\n", ctx->pattern, ctx->ptr));
1627
 
            goto jump_max_until_2;
1628
 
        case JUMP_MAX_UNTIL_3:
1629
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_3\n", ctx->pattern, ctx->ptr));
1630
 
            goto jump_max_until_3;
1631
 
        case JUMP_MIN_UNTIL_2:
1632
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_2\n", ctx->pattern, ctx->ptr));
1633
 
            goto jump_min_until_2;
1634
 
        case JUMP_MIN_UNTIL_3:
1635
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_3\n", ctx->pattern, ctx->ptr));
1636
 
            goto jump_min_until_3;
1637
 
        case JUMP_BRANCH:
1638
 
            TRACE(("|%p|%p|JUMP_BRANCH\n", ctx->pattern, ctx->ptr));
1639
 
            goto jump_branch;
1640
 
        case JUMP_MAX_UNTIL_1:
1641
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_1\n", ctx->pattern, ctx->ptr));
1642
 
            goto jump_max_until_1;
1643
 
        case JUMP_MIN_UNTIL_1:
1644
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_1\n", ctx->pattern, ctx->ptr));
1645
 
            goto jump_min_until_1;
1646
 
        case JUMP_POSS_REPEAT_1:
1647
 
            TRACE(("|%p|%p|JUMP_POSS_REPEAT_1\n", ctx->pattern, ctx->ptr));
1648
 
            goto jump_poss_repeat_1;
1649
 
        case JUMP_POSS_REPEAT_2:
1650
 
            TRACE(("|%p|%p|JUMP_POSS_REPEAT_2\n", ctx->pattern, ctx->ptr));
1651
 
            goto jump_poss_repeat_2;
1652
 
        case JUMP_REPEAT:
1653
 
            TRACE(("|%p|%p|JUMP_REPEAT\n", ctx->pattern, ctx->ptr));
1654
 
            goto jump_repeat;
1655
 
        case JUMP_REPEAT_ONE_1:
1656
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_1\n", ctx->pattern, ctx->ptr));
1657
 
            goto jump_repeat_one_1;
1658
 
        case JUMP_REPEAT_ONE_2:
1659
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_2\n", ctx->pattern, ctx->ptr));
1660
 
            goto jump_repeat_one_2;
1661
 
        case JUMP_MIN_REPEAT_ONE:
1662
 
            TRACE(("|%p|%p|JUMP_MIN_REPEAT_ONE\n", ctx->pattern, ctx->ptr));
1663
 
            goto jump_min_repeat_one;
1664
 
        case JUMP_ATOMIC_GROUP:
1665
 
            TRACE(("|%p|%p|JUMP_ATOMIC_GROUP\n", ctx->pattern, ctx->ptr));
1666
 
            goto jump_atomic_group;
1667
 
        case JUMP_ASSERT:
1668
 
            TRACE(("|%p|%p|JUMP_ASSERT\n", ctx->pattern, ctx->ptr));
1669
 
            goto jump_assert;
1670
 
        case JUMP_ASSERT_NOT:
1671
 
            TRACE(("|%p|%p|JUMP_ASSERT_NOT\n", ctx->pattern, ctx->ptr));
1672
 
            goto jump_assert_not;
1673
 
        case JUMP_NONE:
1674
 
            TRACE(("|%p|%p|RETURN %d\n", ctx->pattern, ctx->ptr, ret));
1675
 
            break;
1676
 
    }
1677
 
 
1678
 
    return ret; /* should never get here */
 
1556
            // Jump forward.
 
1557
            // <JUMP> <offset>
 
1558
            TRACE(("|%p|%p|JUMP %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1559
            context.pattern_ptr += context.pattern_ptr[0];
 
1560
            break;
 
1561
        case SRE_OP_LITERAL:
 
1562
            // Match literal character.
 
1563
            // <LITERAL> <code>
 
1564
            TRACE(("|%p|%p|LITERAL %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1565
            if (context.text_ptr >= context.text_end || (SRE_CODE) context.text_ptr[0] != context.pattern_ptr[0])
 
1566
                goto backtrack;
 
1567
            context.pattern_ptr++;
 
1568
            context.text_ptr++;
 
1569
            break;
 
1570
        case SRE_OP_LITERAL_IGNORE:
 
1571
            // Match literal character, ignoring case.
 
1572
            // <LITERAL_IGNORE> <code>
 
1573
            TRACE(("|%p|%p|LITERAL_IGNORE %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1574
            if (context.text_ptr >= context.text_end || state->lower(context.text_ptr[0]) != context.pattern_ptr[0])
 
1575
                goto backtrack;
 
1576
            context.pattern_ptr++;
 
1577
            context.text_ptr++;
 
1578
            break;
 
1579
        case SRE_OP_LITERAL_IGNORE_REV:
 
1580
            // Match literal character, ignoring case.
 
1581
            // <LITERAL_IGNORE_REV> <code>
 
1582
            TRACE(("|%p|%p|LITERAL_IGNORE_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1583
            if (context.text_ptr <= context.text_start || state->lower(context.text_ptr[-1]) != context.pattern_ptr[0])
 
1584
                goto backtrack;
 
1585
            context.pattern_ptr++;
 
1586
            context.text_ptr--;
 
1587
            break;
 
1588
        case SRE_OP_LITERAL_REV:
 
1589
            // Match literal character.
 
1590
            // <LITERAL_REV> <code>
 
1591
            TRACE(("|%p|%p|LITERAL_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1592
            if (context.text_ptr <= context.text_start || (SRE_CODE) context.text_ptr[-1] != context.pattern_ptr[0])
 
1593
                goto backtrack;
 
1594
            context.pattern_ptr++;
 
1595
            context.text_ptr--;
 
1596
            break;
 
1597
        case SRE_OP_LITERAL_STRING:
 
1598
        {
 
1599
            // Match literal string.
 
1600
            // <LITERAL_STRING> <length> ...
 
1601
            Py_ssize_t length;
 
1602
            Py_ssize_t i;
 
1603
            TRACE(("|%p|%p|LITERAL_STRING %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1604
            length = *context.pattern_ptr++;
 
1605
            if (context.text_ptr + length > context.text_end)
 
1606
                goto backtrack;
 
1607
            i = 0;
 
1608
            do {
 
1609
                if ((SRE_CODE) context.text_ptr[i] != context.pattern_ptr[i])
 
1610
                    goto backtrack;
 
1611
                i++;
 
1612
            }
 
1613
            while (i < length);
 
1614
            context.pattern_ptr += length;
 
1615
            context.text_ptr += length;
 
1616
            break;
 
1617
        }
 
1618
        case SRE_OP_LITERAL_STRING_IGNORE:
 
1619
        {
 
1620
            // Match literal string, ignoring case.
 
1621
            // <LITERAL_STRING_IGNORE> <length> ...
 
1622
            Py_ssize_t length;
 
1623
            Py_ssize_t i;
 
1624
            TRACE(("|%p|%p|LITERAL_STRING_IGNORE %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1625
            length = *context.pattern_ptr++;
 
1626
            if (length > context.text_end - context.text_ptr)
 
1627
                goto backtrack;
 
1628
            i = 0;
 
1629
            do {
 
1630
                if (state->lower(context.text_ptr[i]) != context.pattern_ptr[i])
 
1631
                    goto backtrack;
 
1632
                i++;
 
1633
            }
 
1634
            while (i < length);
 
1635
            context.pattern_ptr += length;
 
1636
            context.text_ptr += length;
 
1637
            break;
 
1638
        }
 
1639
        case SRE_OP_LITERAL_STRING_IGNORE_REV:
 
1640
        {
 
1641
            // Match literal string, ignoring case.
 
1642
            // <LITERAL_STRING_IGNORE_REV> <length> ...
 
1643
            Py_ssize_t length;
 
1644
            Py_ssize_t i;
 
1645
            TRACE(("|%p|%p|LITERAL_STRING_IGNORE_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1646
            length = *context.pattern_ptr++;
 
1647
            if (length > context.text_ptr - context.text_start)
 
1648
                goto backtrack;
 
1649
            context.text_ptr -= length;
 
1650
            i = 0;
 
1651
            do {
 
1652
                if (state->lower(context.text_ptr[i]) != context.pattern_ptr[i])
 
1653
                    goto backtrack;
 
1654
                i++;
 
1655
            }
 
1656
            while (i < length);
 
1657
            context.pattern_ptr += length;
 
1658
            break;
 
1659
        }
 
1660
        case SRE_OP_LITERAL_STRING_REV:
 
1661
        {
 
1662
            // Match literal string.
 
1663
            // <LITERAL_STRING_REV> <length> ...
 
1664
            Py_ssize_t length;
 
1665
            Py_ssize_t i;
 
1666
            TRACE(("|%p|%p|LITERAL_STRING_REV %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1667
            length = *context.pattern_ptr++;
 
1668
            if (context.text_ptr - length < context.text_start)
 
1669
                goto backtrack;
 
1670
            context.text_ptr -= length;
 
1671
            i = 0;
 
1672
            do {
 
1673
                if ((SRE_CODE) context.text_ptr[i] != context.pattern_ptr[i])
 
1674
                    goto backtrack;
 
1675
                i++;
 
1676
            }
 
1677
            while (i < length);
 
1678
            context.pattern_ptr += length;
 
1679
            break;
 
1680
        }
 
1681
        case SRE_OP_LOC_BOUNDARY:
 
1682
        {
 
1683
            // Boundary between word and non-word.
 
1684
            // <LOC_BOUNDARY>
 
1685
            int before = context.text_ptr > context.text_start && SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
1686
            int after = context.text_ptr < context.text_end && SRE_LOC_IS_WORD(context.text_ptr[0]);
 
1687
            TRACE(("|%p|%p|LOC_BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
1688
            if (before == after)
 
1689
                goto backtrack;
 
1690
            break;
 
1691
        }
 
1692
        case SRE_OP_LOC_NOT_BOUNDARY:
 
1693
        {
 
1694
            // Not boundary between word and non-word.
 
1695
            // <LOC_NOT_BOUNDARY>
 
1696
            int before = context.text_ptr > context.text_start && SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
1697
            int after = context.text_ptr < context.text_end && SRE_LOC_IS_WORD(context.text_ptr[0]);
 
1698
            TRACE(("|%p|%p|LOC_NOT_BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
1699
            if (before != after)
 
1700
                goto backtrack;
 
1701
            break;
 
1702
        }
 
1703
        case SRE_OP_LOC_NOT_WORD:
 
1704
            // Not word.
 
1705
            // <LOC_NOT_WORD>
 
1706
            TRACE(("|%p|%p|LOC_NOT_WORD\n", context.pattern_ptr, context.text_ptr));
 
1707
            if (context.text_ptr >= context.text_end || SRE_LOC_IS_WORD(context.text_ptr[0]))
 
1708
                goto backtrack;
 
1709
            context.text_ptr++;
 
1710
            break;
 
1711
        case SRE_OP_LOC_NOT_WORD_REV:
 
1712
            // Not word.
 
1713
            // <LOC_NOT_WORD_REV>
 
1714
            TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
1715
            if (context.text_ptr <= context.text_start || SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
1716
                goto backtrack;
 
1717
            context.text_ptr--;
 
1718
            break;
 
1719
        case SRE_OP_LOC_WORD:
 
1720
            // Word.
 
1721
            // <LOC_WORD>
 
1722
            TRACE(("|%p|%p|LOC_WORD\n", context.pattern_ptr, context.text_ptr));
 
1723
            if (context.text_ptr >= context.text_end || !SRE_LOC_IS_WORD(context.text_ptr[0]))
 
1724
                goto backtrack;
 
1725
            context.text_ptr++;
 
1726
            break;
 
1727
        case SRE_OP_LOC_WORD_REV:
 
1728
            // Word.
 
1729
            // <LOC_WORD_REV>
 
1730
            TRACE(("|%p|%p|LOC_WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
1731
            if (context.text_ptr <= context.text_start || !SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
1732
                goto backtrack;
 
1733
            context.text_ptr--;
 
1734
            break;
 
1735
        case SRE_OP_MARK:
 
1736
        {
 
1737
            // Set mark.
 
1738
            // <MARK> <index>
 
1739
            TRACE(("|%p|%p|MARK %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1740
            context.mark[context.pattern_ptr[0]] = context.text_ptr;
 
1741
            context.pattern_ptr++;
 
1742
            break;
 
1743
        }
 
1744
        case SRE_OP_NOT_BIGCHARSET:
 
1745
            // Match character not in charset.
 
1746
            // <NOT_BIGCHARSET> <charset>
 
1747
            TRACE(("|%p|%p|NOT_BIGCHARSET\n", context.pattern_ptr, context.text_ptr));
 
1748
            if (context.text_ptr >= context.text_end || in_bigcharset(context.pattern_ptr, context.text_ptr[0]))
 
1749
                goto backtrack;
 
1750
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
1751
            context.text_ptr++;
 
1752
            break;
 
1753
        case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
1754
            // Match character not in charset, ignoring case.
 
1755
            // <NOT_BIGCHARSET_IGNORE> <charset>
 
1756
            TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", context.pattern_ptr, context.text_ptr));
 
1757
            if (context.text_ptr >= context.text_end || in_bigcharset(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
1758
                goto backtrack;
 
1759
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
1760
            context.text_ptr++;
 
1761
            break;
 
1762
        case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
1763
            // Match character not in charset, ignoring case.
 
1764
            // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
1765
            TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", context.pattern_ptr, context.text_ptr));
 
1766
            if (context.text_ptr <= context.text_start || in_bigcharset(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
1767
                goto backtrack;
 
1768
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
1769
            context.text_ptr--;
 
1770
            break;
 
1771
        case SRE_OP_NOT_BIGCHARSET_REV:
 
1772
            // Match character not in charset.
 
1773
            // <NOT_BIGCHARSET_REV> <charset>
 
1774
            TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
1775
            if (context.text_ptr <= context.text_start || in_bigcharset(context.pattern_ptr, context.text_ptr[-1]))
 
1776
                goto backtrack;
 
1777
            context.pattern_ptr = skip_bigcharset(context.pattern_ptr);
 
1778
            context.text_ptr--;
 
1779
            break;
 
1780
        case SRE_OP_NOT_BOUNDARY:
 
1781
        {
 
1782
            // Not boundary between word and non-word.
 
1783
            // <NOT_BOUNDARY>
 
1784
            int before = context.text_ptr > context.text_start && SRE_IS_WORD(context.text_ptr[-1]);
 
1785
            int after = context.text_ptr < context.text_end && SRE_IS_WORD(context.text_ptr[0]);
 
1786
            TRACE(("|%p|%p|NOT_BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
1787
            if (before != after)
 
1788
                goto backtrack;
 
1789
            break;
 
1790
        }
 
1791
        case SRE_OP_NOT_CHARSET:
 
1792
        {
 
1793
            // Match character not in charset.
 
1794
            // <NOT_CHARSET> <charset>
 
1795
            TRACE(("|%p|%p|NOT_CHARSET\n", context.pattern_ptr, context.text_ptr));
 
1796
            if (context.text_ptr >= context.text_end || in_charset(context.pattern_ptr, context.text_ptr[0]))
 
1797
                goto backtrack;
 
1798
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1799
            context.text_ptr++;
 
1800
            break;
 
1801
        }
 
1802
        case SRE_OP_NOT_CHARSET_IGNORE:
 
1803
        {
 
1804
            // Match character not in charset, ignoring case.
 
1805
            // <NOT_CHARSET_IGNORE> <charset>
 
1806
            TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", context.pattern_ptr, context.text_ptr));
 
1807
            if (context.text_ptr >= context.text_end || in_charset(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
1808
                goto backtrack;
 
1809
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1810
            context.text_ptr++;
 
1811
            break;
 
1812
        }
 
1813
        case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
1814
        {
 
1815
            // Match character not in charset, ignoring case.
 
1816
            // <NOT_CHARSET_IGNORE_REV> <charset>
 
1817
            TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", context.pattern_ptr, context.text_ptr));
 
1818
            if (context.text_ptr <= context.text_start || in_charset(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
1819
                goto backtrack;
 
1820
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1821
            context.text_ptr--;
 
1822
            break;
 
1823
        }
 
1824
        case SRE_OP_NOT_CHARSET_REV:
 
1825
        {
 
1826
            // Match character not in charset.
 
1827
            // <NOT_CHARSET_REV> <charset>
 
1828
            TRACE(("|%p|%p|NOT_CHARSET_REV\n", context.pattern_ptr, context.text_ptr));
 
1829
            if (context.text_ptr <= context.text_start || in_charset(context.pattern_ptr, context.text_ptr[-1]))
 
1830
                goto backtrack;
 
1831
            context.pattern_ptr = skip_charset(context.pattern_ptr);
 
1832
            context.text_ptr--;
 
1833
            break;
 
1834
        }
 
1835
        case SRE_OP_NOT_DIGIT:
 
1836
            // Not digit.
 
1837
            // <NOT_DIGIT>
 
1838
            TRACE(("|%p|%p|NOT_DIGIT\n", context.pattern_ptr, context.text_ptr));
 
1839
            if (context.text_ptr >= context.text_end || SRE_IS_DIGIT(context.text_ptr[0]))
 
1840
                goto backtrack;
 
1841
            context.text_ptr++;
 
1842
            break;
 
1843
        case SRE_OP_NOT_DIGIT_REV:
 
1844
            // Not digit.
 
1845
            // <NOT_DIGIT_REV>
 
1846
            TRACE(("|%p|%p|NOT_DIGIT_REV\n", context.pattern_ptr, context.text_ptr));
 
1847
            if (context.text_ptr <= context.text_start || SRE_IS_DIGIT(context.text_ptr[-1]))
 
1848
                goto backtrack;
 
1849
            context.text_ptr--;
 
1850
            break;
 
1851
        case SRE_OP_NOT_IN:
 
1852
            // Match not set member.
 
1853
            // <NOT_IN> <set>
 
1854
            TRACE(("|%p|%p|NOT_IN\n", context.pattern_ptr, context.text_ptr));
 
1855
            if (context.text_ptr >= context.text_end || SRE_IN(context.pattern_ptr, context.text_ptr[0]))
 
1856
                goto backtrack;
 
1857
            context.pattern_ptr += context.pattern_ptr[0];
 
1858
            context.text_ptr++;
 
1859
            break;
 
1860
        case SRE_OP_NOT_IN_IGNORE:
 
1861
            // Match not set member, ignoring case.
 
1862
            // <NOT_IN_IGNORE> <set>
 
1863
            TRACE(("|%p|%p|NOT_IN_IGNORE\n", context.pattern_ptr, context.text_ptr));
 
1864
            if (context.text_ptr >= context.text_end || SRE_IN(context.pattern_ptr, state->lower(context.text_ptr[0])))
 
1865
                goto backtrack;
 
1866
            context.pattern_ptr += context.pattern_ptr[0];
 
1867
            context.text_ptr++;
 
1868
            break;
 
1869
        case SRE_OP_NOT_IN_IGNORE_REV:
 
1870
            // Match not set member, ignoring case.
 
1871
            // <NOT_IN_IGNORE_REV> <set>
 
1872
            TRACE(("|%p|%p|NOT_IN_IGNORE_REV\n", context.pattern_ptr, context.text_ptr));
 
1873
            if (context.text_ptr <= context.text_start || SRE_IN(context.pattern_ptr, state->lower(context.text_ptr[-1])))
 
1874
                goto backtrack;
 
1875
            context.pattern_ptr += context.pattern_ptr[0];
 
1876
            context.text_ptr--;
 
1877
            break;
 
1878
        case SRE_OP_NOT_IN_REV:
 
1879
            // Match not set member.
 
1880
            // <NOT_IN_REV> <set>
 
1881
            TRACE(("|%p|%p|NOT_IN_REV\n", context.pattern_ptr, context.text_ptr));
 
1882
            if (context.text_ptr <= context.text_start || SRE_IN(context.pattern_ptr, context.text_ptr[-1]))
 
1883
                goto backtrack;
 
1884
            context.pattern_ptr += context.pattern_ptr[0];
 
1885
            context.text_ptr--;
 
1886
            break;
 
1887
        case SRE_OP_NOT_LITERAL:
 
1888
            // Match a character that is not this character.
 
1889
            // <NOT_LITERAL> <code>
 
1890
            TRACE(("|%p|%p|NOT_LITERAL %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1891
            if (context.text_ptr >= context.text_end || (SRE_CODE) context.text_ptr[0] == context.pattern_ptr[0])
 
1892
                goto backtrack;
 
1893
            context.pattern_ptr++;
 
1894
            context.text_ptr++;
 
1895
            break;
 
1896
        case SRE_OP_NOT_LITERAL_IGNORE:
 
1897
            // Match a character that is not this character, ignoring case.
 
1898
            // <NOT_LITERAL_IGNORE> <code>
 
1899
            TRACE(("|%p|%p|NOT_LITERAL_IGNORE %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1900
            if (context.text_ptr >= context.text_end || state->lower(context.text_ptr[0]) == context.pattern_ptr[0])
 
1901
                goto backtrack;
 
1902
            context.pattern_ptr++;
 
1903
            context.text_ptr++;
 
1904
            break;
 
1905
        case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
1906
            // Match a character that is not this character, ignoring case.
 
1907
            // <NOT_LITERAL_IGNORE_REV> <code>
 
1908
            TRACE(("|%p|%p|NOT_LITERAL_IGNORE %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1909
            if (context.text_ptr <= context.text_start || state->lower(context.text_ptr[-1]) == context.pattern_ptr[0])
 
1910
                goto backtrack;
 
1911
            context.pattern_ptr++;
 
1912
            context.text_ptr--;
 
1913
            break;
 
1914
        case SRE_OP_NOT_LITERAL_REV:
 
1915
            // Match a character that is not this character.
 
1916
            // <NOT_LITERAL_REV> <code>
 
1917
            TRACE(("|%p|%p|NOT_LITERAL %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1918
            if (context.text_ptr <= context.text_start || (SRE_CODE) context.text_ptr[-1] == context.pattern_ptr[0])
 
1919
                goto backtrack;
 
1920
            context.pattern_ptr++;
 
1921
            context.text_ptr--;
 
1922
            break;
 
1923
        case SRE_OP_NOT_RANGE:
 
1924
            // Match not range character.
 
1925
            // <NOT_RANGE> <lower> <upper>
 
1926
            TRACE(("|%p|%p|NOT_RANGE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1927
            if (context.text_ptr >= context.text_end || SRE_IN_RANGE(context.text_ptr[0], context.pattern_ptr[0], context.pattern_ptr[1]))
 
1928
                goto backtrack;
 
1929
            context.pattern_ptr += 2;
 
1930
            context.text_ptr++;
 
1931
            break;
 
1932
        case SRE_OP_NOT_RANGE_IGNORE:
 
1933
            // Match not range character, ignoring case.
 
1934
            // <NOT_RANGE_IGNORE> <lower> <upper>
 
1935
            TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1936
            if (context.text_ptr >= context.text_end || SRE_IN_RANGE(state->lower(context.text_ptr[0]), context.pattern_ptr[0], context.pattern_ptr[1]))
 
1937
                goto backtrack;
 
1938
            context.pattern_ptr += 2;
 
1939
            context.text_ptr++;
 
1940
            break;
 
1941
        case SRE_OP_NOT_RANGE_IGNORE_REV:
 
1942
            // Match not range character, ignoring case.
 
1943
            // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
1944
            TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1945
            if (context.text_ptr <= context.text_start || SRE_IN_RANGE(state->lower(context.text_ptr[-1]), context.pattern_ptr[0], context.pattern_ptr[1]))
 
1946
                goto backtrack;
 
1947
            context.pattern_ptr += 2;
 
1948
            context.text_ptr--;
 
1949
            break;
 
1950
        case SRE_OP_NOT_RANGE_REV:
 
1951
            // Match not range character.
 
1952
            // <NOT_RANGE_REV> <lower> <upper>
 
1953
            TRACE(("|%p|%p|NOT_RANGE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1954
            if (context.text_ptr <= context.text_start || SRE_IN_RANGE(context.text_ptr[-1], context.pattern_ptr[0], context.pattern_ptr[1]))
 
1955
                goto backtrack;
 
1956
            context.pattern_ptr += 2;
 
1957
            context.text_ptr--;
 
1958
            break;
 
1959
        case SRE_OP_NOT_WHITESPACE:
 
1960
            // Not whitespace.
 
1961
            // <NOT_WHITESPACE>
 
1962
            TRACE(("|%p|%p|NOT_WHITESPACE\n", context.pattern_ptr, context.text_ptr));
 
1963
            if (context.text_ptr >= context.text_end || SRE_IS_WHITESPACE(context.text_ptr[0]))
 
1964
                goto backtrack;
 
1965
            context.text_ptr++;
 
1966
            break;
 
1967
        case SRE_OP_NOT_WHITESPACE_REV:
 
1968
            // Not whitespace.
 
1969
            // <NOT_WHITESPACE_REV>
 
1970
            TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", context.pattern_ptr, context.text_ptr));
 
1971
            if (context.text_ptr <= context.text_start || SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
1972
                goto backtrack;
 
1973
            context.text_ptr--;
 
1974
            break;
 
1975
        case SRE_OP_NOT_WORD:
 
1976
            // Not word.
 
1977
            // <NOT_WORD>
 
1978
            TRACE(("|%p|%p|NOT_WORD\n", context.pattern_ptr, context.text_ptr));
 
1979
            if (context.text_ptr >= context.text_end || SRE_IS_WORD(context.text_ptr[0]))
 
1980
                goto backtrack;
 
1981
            context.text_ptr++;
 
1982
            break;
 
1983
        case SRE_OP_NOT_WORD_REV:
 
1984
            // Not word.
 
1985
            // <NOT_WORD_REV>
 
1986
            TRACE(("|%p|%p|NOT_WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
1987
            if (context.text_ptr <= context.text_start || SRE_IS_WORD(context.text_ptr[-1]))
 
1988
                goto backtrack;
 
1989
            context.text_ptr--;
 
1990
            break;
 
1991
        case SRE_OP_RANGE:
 
1992
            // Match range character.
 
1993
            // <RANGE> <lower> <upper>
 
1994
            TRACE(("|%p|%p|RANGE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
1995
            if (context.text_ptr >= context.text_end || !SRE_IN_RANGE(context.text_ptr[0], context.pattern_ptr[0], context.pattern_ptr[1]))
 
1996
                goto backtrack;
 
1997
            context.pattern_ptr += 2;
 
1998
            context.text_ptr++;
 
1999
            break;
 
2000
        case SRE_OP_RANGE_IGNORE:
 
2001
            // Match range character, ignoring case.
 
2002
            // <RANGE_IGNORE> <lower> <upper>
 
2003
            TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
2004
            if (context.text_ptr >= context.text_end || !SRE_IN_RANGE(state->lower(context.text_ptr[0]), context.pattern_ptr[0], context.pattern_ptr[1]))
 
2005
                goto backtrack;
 
2006
            context.pattern_ptr += 2;
 
2007
            context.text_ptr++;
 
2008
            break;
 
2009
        case SRE_OP_RANGE_IGNORE_REV:
 
2010
            // Match range character, ignoring case.
 
2011
            // <RANGE_IGNORE_REV> <lower> <upper>
 
2012
            TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
2013
            if (context.text_ptr <= context.text_start || !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), context.pattern_ptr[0], context.pattern_ptr[1]))
 
2014
                goto backtrack;
 
2015
            context.pattern_ptr += 2;
 
2016
            context.text_ptr--;
 
2017
            break;
 
2018
        case SRE_OP_RANGE_REV:
 
2019
            // Match range character.
 
2020
            // <RANGE_REV> <lower> <upper>
 
2021
            TRACE(("|%p|%p|RANGE %d %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[0]));
 
2022
            if (context.text_ptr <= context.text_start || !SRE_IN_RANGE(context.text_ptr[-1], context.pattern_ptr[0], context.pattern_ptr[1]))
 
2023
                goto backtrack;
 
2024
            context.pattern_ptr += 2;
 
2025
            context.text_ptr--;
 
2026
            break;
 
2027
        case SRE_OP_REPEAT_MAX:
 
2028
        {
 
2029
            // Greedy repeat.
 
2030
            // <REPEAT_MAX> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX> <skip to start>
 
2031
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2032
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
2033
            SRE_CODE* tail = end_repeat_ptr + 1;
 
2034
            int index = repeat_ptr[1];
 
2035
            int repeat_min = repeat_ptr[2];
 
2036
            int repeat_max = repeat_ptr[3];
 
2037
            SRE_CODE* body = repeat_ptr + 4;
 
2038
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
2039
            TRACE(("|%p|%p|REPEAT_MAX %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2040
            if (repeat_min > limit)
 
2041
                goto backtrack;
 
2042
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_MAX, repeat_ptr, index);
 
2043
            if (result != 0)
 
2044
                return SRE_CLEANUP(&context, state, result);
 
2045
            result = SRE_SAVE_MARKS(&context);
 
2046
            if (result != 0)
 
2047
                return SRE_CLEANUP(&context, state, result);
 
2048
            context.repeat_counter[index] = 0;
 
2049
            if (repeat_min == 0) {
 
2050
                int match;
 
2051
                // Look at what follows to avoid unnecessary backtracking.
 
2052
                if (limit > 0) {
 
2053
                    SRE_CODE* look_literal = tail;
 
2054
                    while (look_literal[0] == SRE_OP_MARK)
 
2055
                        look_literal += 2;
 
2056
                    match = SRE_LOOK_AHEAD_ONE(&context, state, look_literal);
 
2057
                } else
 
2058
                    match = 1;
 
2059
                if (match) {
 
2060
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MAX, end_repeat_ptr, -1);
 
2061
                    if (result != 0)
 
2062
                        return SRE_CLEANUP(&context, state, result);
 
2063
                    result = SRE_SAVE_MARKS(&context);
 
2064
                    if (result != 0)
 
2065
                        return SRE_CLEANUP(&context, state, result);
 
2066
                }
 
2067
            }
 
2068
            context.pattern_ptr = body;
 
2069
            context.repeat_start[index] = context.text_ptr;
 
2070
            break;
 
2071
        }
 
2072
        case SRE_OP_REPEAT_MAX_REV:
 
2073
        {
 
2074
            // Greedy repeat.
 
2075
            // <REPEAT_MAX_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX_REV> <skip to start>
 
2076
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2077
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
2078
            SRE_CODE* tail = end_repeat_ptr + 1;
 
2079
            int index = repeat_ptr[1];
 
2080
            int repeat_min = repeat_ptr[2];
 
2081
            int repeat_max = repeat_ptr[3];
 
2082
            SRE_CODE* body = repeat_ptr + 4;
 
2083
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
2084
            TRACE(("|%p|%p|REPEAT_MAX_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2085
            if (repeat_min > limit)
 
2086
                goto backtrack;
 
2087
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_MAX_REV, repeat_ptr, index);
 
2088
            if (result != 0)
 
2089
                return SRE_CLEANUP(&context, state, result);
 
2090
            result = SRE_SAVE_MARKS(&context);
 
2091
            if (result != 0)
 
2092
                return SRE_CLEANUP(&context, state, result);
 
2093
            context.repeat_counter[index] = 0;
 
2094
            if (repeat_min == 0) {
 
2095
                int match;
 
2096
                // Look at what follows to avoid unnecessary backtracking.
 
2097
                if (limit > 0) {
 
2098
                    SRE_CODE* look_literal = tail;
 
2099
                    while (look_literal[0] == SRE_OP_MARK)
 
2100
                        look_literal += 2;
 
2101
                    match = SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal);
 
2102
                } else
 
2103
                    match = 1;
 
2104
                if (match) {
 
2105
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MAX_REV, end_repeat_ptr, -1);
 
2106
                    if (result != 0)
 
2107
                        return SRE_CLEANUP(&context, state, result);
 
2108
                    result = SRE_SAVE_MARKS(&context);
 
2109
                    if (result != 0)
 
2110
                        return SRE_CLEANUP(&context, state, result);
 
2111
                }
 
2112
            }
 
2113
            context.pattern_ptr = body;
 
2114
            context.repeat_start[index] = context.text_ptr;
 
2115
            break;
 
2116
        }
 
2117
        case SRE_OP_REPEAT_MIN:
 
2118
        {
 
2119
            // Lazy repeat.
 
2120
            // <REPEAT_MIN> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN> <skip to start>
 
2121
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2122
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
2123
            SRE_CODE* tail = end_repeat_ptr + 1;
 
2124
            int index = repeat_ptr[1];
 
2125
            int repeat_min = repeat_ptr[2];
 
2126
            int repeat_max = repeat_ptr[3];
 
2127
            SRE_CODE* body = repeat_ptr + 4;
 
2128
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
2129
            TRACE(("|%p|%p|REPEAT_MIN %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2130
            if (repeat_min > limit)
 
2131
                goto backtrack;
 
2132
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_MIN, repeat_ptr, index);
 
2133
            if (result != 0)
 
2134
                return SRE_CLEANUP(&context, state, result);
 
2135
            result = SRE_SAVE_MARKS(&context);
 
2136
            if (result != 0)
 
2137
                return SRE_CLEANUP(&context, state, result);
 
2138
            context.repeat_counter[index] = 0;
 
2139
            if (repeat_min == 0) {
 
2140
                int match;
 
2141
                if (limit > 0) {
 
2142
                    SRE_CODE* look_literal = tail;
 
2143
                    while (look_literal[0] == SRE_OP_MARK)
 
2144
                        look_literal += 2;
 
2145
                    // Look at what follows to avoid unnecessary backtracking.
 
2146
                    match = SRE_LOOK_AHEAD_ONE(&context, state, look_literal);
 
2147
                } else
 
2148
                    match = 1;
 
2149
                if (match) {
 
2150
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MIN, end_repeat_ptr, -1);
 
2151
                    if (result != 0)
 
2152
                        return SRE_CLEANUP(&context, state, result);
 
2153
                    result = SRE_SAVE_MARKS(&context);
 
2154
                    if (result != 0)
 
2155
                        return SRE_CLEANUP(&context, state, result);
 
2156
                    context.pattern_ptr = tail;
 
2157
                } else {
 
2158
                    context.pattern_ptr = body;
 
2159
                    context.repeat_start[index] = context.text_ptr;
 
2160
                }
 
2161
            } else {
 
2162
                context.pattern_ptr = body;
 
2163
                context.repeat_start[index] = context.text_ptr;
 
2164
            }
 
2165
            break;
 
2166
        }
 
2167
        case SRE_OP_REPEAT_MIN_REV:
 
2168
        {
 
2169
            // Lazy repeat.
 
2170
            // <REPEAT_MIN_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN_REV> <skip to start>
 
2171
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2172
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
2173
            SRE_CODE* tail = end_repeat_ptr + 1;
 
2174
            int index = repeat_ptr[1];
 
2175
            int repeat_min = repeat_ptr[2];
 
2176
            int repeat_max = repeat_ptr[3];
 
2177
            SRE_CODE* body = repeat_ptr + 4;
 
2178
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
2179
            TRACE(("|%p|%p|REPEAT_MIN_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2180
            if (repeat_min > limit)
 
2181
                goto backtrack;
 
2182
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_MIN_REV, repeat_ptr, index);
 
2183
            if (result != 0)
 
2184
                return SRE_CLEANUP(&context, state, result);
 
2185
            result = SRE_SAVE_MARKS(&context);
 
2186
            if (result != 0)
 
2187
                return SRE_CLEANUP(&context, state, result);
 
2188
            context.repeat_counter[index] = 0;
 
2189
            if (repeat_min == 0) {
 
2190
                int match;
 
2191
                if (limit > 0) {
 
2192
                    SRE_CODE* look_literal = tail;
 
2193
                    while (look_literal[0] == SRE_OP_MARK)
 
2194
                        look_literal += 2;
 
2195
                    // Look at what follows to avoid unnecessary backtracking.
 
2196
                    match = SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal);
 
2197
                } else
 
2198
                    match = 1;
 
2199
                if (match) {
 
2200
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_MIN_REV, end_repeat_ptr, -1);
 
2201
                    if (result != 0)
 
2202
                        return SRE_CLEANUP(&context, state, result);
 
2203
                    result = SRE_SAVE_MARKS(&context);
 
2204
                    if (result != 0)
 
2205
                        return SRE_CLEANUP(&context, state, result);
 
2206
                    context.pattern_ptr = tail;
 
2207
                } else {
 
2208
                    context.pattern_ptr = body;
 
2209
                    context.repeat_start[index] = context.text_ptr;
 
2210
                }
 
2211
            } else {
 
2212
                context.pattern_ptr = body;
 
2213
                context.repeat_start[index] = context.text_ptr;
 
2214
            }
 
2215
            break;
 
2216
        }
 
2217
        case SRE_OP_REPEAT_ONE_MAX:
 
2218
        {
 
2219
            // Greedy repeat.
 
2220
            // <REPEAT_ONE_MAX> <skip to end> <index> <min> <max> ...
 
2221
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2222
            int index = context.pattern_ptr[1];
 
2223
            int repeat_min = context.pattern_ptr[2];
 
2224
            int repeat_max = context.pattern_ptr[3];
 
2225
            SRE_CODE* body = context.pattern_ptr + 4;
 
2226
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
2227
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
2228
            SRE_CODE* look_literal = tail;
 
2229
            SRE_CHAR* start_ptr = context.text_ptr;
 
2230
            SRE_CHAR* end_ptr;
 
2231
            TRACE(("|%p|%p|REPEAT_ONE_MAX %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2232
            if (repeat_min > limit)
 
2233
                goto backtrack;
 
2234
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
2235
            end_ptr = start_ptr + repeat_max;
 
2236
            // Match up to the maximum.
 
2237
            switch (body[0]) {
 
2238
            case SRE_OP_ANY:
 
2239
                // <ANY>
 
2240
                TRACE(("|%p|%p|ANY\n", body, context.text_ptr));
 
2241
                while (context.text_ptr < end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[0]))
 
2242
                    context.text_ptr++;
 
2243
                break;
 
2244
            case SRE_OP_ANY_ALL:
 
2245
                // <ANY_ALL>
 
2246
                TRACE(("|%p|%p|ANY_ALL\n", body, context.text_ptr));
 
2247
                context.text_ptr = end_ptr;
 
2248
                break;
 
2249
            case SRE_OP_BIGCHARSET:
 
2250
                // <BIGCHARSET> <charset>
 
2251
                TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
2252
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, context.text_ptr[0]))
 
2253
                    context.text_ptr++;
 
2254
                break;
 
2255
            case SRE_OP_BIGCHARSET_IGNORE:
 
2256
                // <BIGCHARSET_IGNORE> <charset>
 
2257
                TRACE(("|%p|%p|BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
2258
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
2259
                    context.text_ptr++;
 
2260
            case SRE_OP_CHARSET:
 
2261
                // <CHARSET> <charset>
 
2262
                TRACE(("|%p|%p|CHARSET\n", body, context.text_ptr));
 
2263
                while (context.text_ptr < end_ptr && in_charset(body + 1, context.text_ptr[0]))
 
2264
                    context.text_ptr++;
 
2265
                break;
 
2266
            case SRE_OP_CHARSET_IGNORE:
 
2267
                // <CHARSET_IGNORE> <charset>
 
2268
                TRACE(("|%p|%p|CHARSET_IGNORE\n", body, context.text_ptr));
 
2269
                while (context.text_ptr < end_ptr && in_charset(body + 1, state->lower(context.text_ptr[0])))
 
2270
                    context.text_ptr++;
 
2271
                break;
 
2272
            case SRE_OP_DIGIT:
 
2273
                // <DIGIT>
 
2274
                TRACE(("|%p|%p|DIGIT\n", body, context.text_ptr));
 
2275
                while (context.text_ptr < end_ptr && SRE_IS_DIGIT(context.text_ptr[0]))
 
2276
                    context.text_ptr++;
 
2277
                break;
 
2278
            case SRE_OP_IN:
 
2279
                // <IN> <set>
 
2280
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
2281
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, context.text_ptr[0]))
 
2282
                    context.text_ptr++;
 
2283
                break;
 
2284
            case SRE_OP_IN_IGNORE:
 
2285
                // <IN_IGNORE> <set>
 
2286
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
2287
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
2288
                    context.text_ptr++;
 
2289
                break;
 
2290
            case SRE_OP_LITERAL:
 
2291
                // <LITERAL> <code>
 
2292
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
2293
                while (context.text_ptr < end_ptr && context.text_ptr[0] == (SRE_CHAR)body[1])
 
2294
                    context.text_ptr++;
 
2295
                break;
 
2296
            case SRE_OP_LITERAL_IGNORE:
 
2297
                // <LITERAL_IGNORE> <code>
 
2298
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
2299
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) == (SRE_CHAR)body[1])
 
2300
                    context.text_ptr++;
 
2301
                break;
 
2302
            case SRE_OP_LOC_NOT_WORD:
 
2303
                // <LOC_NOT_WORD>
 
2304
                TRACE(("|%p|%p|LOC_NOT_WORD\n", body, context.text_ptr));
 
2305
                while (context.text_ptr < end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[0]))
 
2306
                    context.text_ptr++;
 
2307
                break;
 
2308
            case SRE_OP_LOC_WORD:
 
2309
                // <LOC_WORD>
 
2310
                TRACE(("|%p|%p|LOC_WORD\n", body, context.text_ptr));
 
2311
                while (context.text_ptr < end_ptr && SRE_LOC_IS_WORD(context.text_ptr[0]))
 
2312
                    context.text_ptr++;
 
2313
                break;
 
2314
            case SRE_OP_NOT_BIGCHARSET:
 
2315
                // <NOT_BIGCHARSET> <charset>
 
2316
                TRACE(("|%p|%p|NOT_BIGCHARSET\n", body, context.text_ptr));
 
2317
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, context.text_ptr[0]))
 
2318
                    context.text_ptr++;
 
2319
                break;
 
2320
            case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
2321
                // <NOT_BIGCHARSET_IGNORE> <charset>
 
2322
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
2323
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
2324
                    context.text_ptr++;
 
2325
                break;
 
2326
            case SRE_OP_NOT_CHARSET:
 
2327
                // <NOT_CHARSET> <charset>
 
2328
                TRACE(("|%p|%p|NOT_CHARSET\n", body, context.text_ptr));
 
2329
                while (context.text_ptr < end_ptr && !in_charset(body + 1, context.text_ptr[0]))
 
2330
                    context.text_ptr++;
 
2331
                break;
 
2332
            case SRE_OP_NOT_CHARSET_IGNORE:
 
2333
                // <NOT_CHARSET_IGNORE> <charset>
 
2334
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", body, context.text_ptr));
 
2335
                while (context.text_ptr < end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[0])))
 
2336
                    context.text_ptr++;
 
2337
                break;
 
2338
            case SRE_OP_NOT_DIGIT:
 
2339
                // <NOT_DIGIT>
 
2340
                TRACE(("|%p|%p|NOT_DIGIT\n", body, context.text_ptr));
 
2341
                while (context.text_ptr < end_ptr && !SRE_IS_DIGIT(context.text_ptr[0]))
 
2342
                    context.text_ptr++;
 
2343
                break;
 
2344
            case SRE_OP_NOT_IN:
 
2345
                // <NOT_IN> <set>
 
2346
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
2347
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, context.text_ptr[0]))
 
2348
                    context.text_ptr++;
 
2349
                break;
 
2350
            case SRE_OP_NOT_IN_IGNORE:
 
2351
                // <NOT_IN_IGNORE> <set>
 
2352
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
2353
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
2354
                    context.text_ptr++;
 
2355
                break;
 
2356
            case SRE_OP_NOT_LITERAL:
 
2357
                // <NOT_LITERAL> <code>
 
2358
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
2359
                while (context.text_ptr < end_ptr && context.text_ptr[0] != (SRE_CHAR)body[1])
 
2360
                    context.text_ptr++;
 
2361
                break;
 
2362
            case SRE_OP_NOT_LITERAL_IGNORE:
 
2363
                // <NOT_LITERAL_IGNORE> <code>
 
2364
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
2365
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) != (SRE_CHAR)body[1])
 
2366
                    context.text_ptr++;
 
2367
                break;
 
2368
            case SRE_OP_NOT_RANGE:
 
2369
                // <NOT_RANGE> <lower> <upper>
 
2370
                TRACE(("|%p|%p|NOT_RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2371
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
2372
                    context.text_ptr++;
 
2373
                break;
 
2374
            case SRE_OP_NOT_RANGE_IGNORE:
 
2375
                // <NOT_RANGE_IGNORE> <lower> <upper>
 
2376
                TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2377
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
2378
                    context.text_ptr++;
 
2379
                break;
 
2380
            case SRE_OP_NOT_WHITESPACE:
 
2381
                // <NOT_WHITESPACE>
 
2382
                TRACE(("|%p|%p|NOT_WHITESPACE\n", body, context.text_ptr));
 
2383
                while (context.text_ptr < end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[0]))
 
2384
                    context.text_ptr++;
 
2385
                break;
 
2386
            case SRE_OP_NOT_WORD:
 
2387
                // <NOT_WORD>
 
2388
                TRACE(("|%p|%p|NOT_WORD\n", body, context.text_ptr));
 
2389
                while (context.text_ptr < end_ptr && !SRE_IS_WORD(context.text_ptr[0]))
 
2390
                    context.text_ptr++;
 
2391
                break;
 
2392
            case SRE_OP_RANGE:
 
2393
                // <RANGE> <lower> <upper>
 
2394
                TRACE(("|%p|%p|RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2395
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
2396
                    context.text_ptr++;
 
2397
                break;
 
2398
            case SRE_OP_RANGE_IGNORE:
 
2399
                // <RANGE_IGNORE> <lower> <upper>
 
2400
                TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2401
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
2402
                    context.text_ptr++;
 
2403
                break;
 
2404
            case SRE_OP_UNI_DIGIT:
 
2405
                // <UNI_DIGIT>
 
2406
                TRACE(("|%p|%p|UNI_DIGIT\n", body, context.text_ptr));
 
2407
                while (context.text_ptr < end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
2408
                    context.text_ptr++;
 
2409
                break;
 
2410
            case SRE_OP_UNI_NOT_DIGIT:
 
2411
                // <UNI_NOT_DIGIT>
 
2412
                TRACE(("|%p|%p|UNI_NOT_DIGIT\n", body, context.text_ptr));
 
2413
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
2414
                    context.text_ptr++;
 
2415
                break;
 
2416
            case SRE_OP_UNI_NOT_WHITESPACE:
 
2417
                // <UNI_NOT_WHITESPACE>
 
2418
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", body, context.text_ptr));
 
2419
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
2420
                    context.text_ptr++;
 
2421
                break;
 
2422
            case SRE_OP_UNI_NOT_WORD:
 
2423
                // <UNI_NOT_WORD>
 
2424
                TRACE(("|%p|%p|UNI_NOT_WORD\n", body, context.text_ptr));
 
2425
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[0]))
 
2426
                    context.text_ptr++;
 
2427
                break;
 
2428
            case SRE_OP_UNI_WHITESPACE:
 
2429
                // <UNI_WHITESPACE>
 
2430
                TRACE(("|%p|%p|UNI_WHITESPACE\n", body, context.text_ptr));
 
2431
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
2432
                    context.text_ptr++;
 
2433
                break;
 
2434
            case SRE_OP_UNI_WORD:
 
2435
                // <UNI_WORD>
 
2436
                TRACE(("|%p|%p|UNI_WORD\n", body, context.text_ptr));
 
2437
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WORD(context.text_ptr[0]))
 
2438
                    context.text_ptr++;
 
2439
                break;
 
2440
            case SRE_OP_WHITESPACE:
 
2441
                // <WHITESPACE>
 
2442
                TRACE(("|%p|%p|WHITESPACE\n", body, context.text_ptr));
 
2443
                while (context.text_ptr < end_ptr && SRE_IS_WHITESPACE(context.text_ptr[0]))
 
2444
                    context.text_ptr++;
 
2445
                break;
 
2446
            case SRE_OP_WORD:
 
2447
                // <WORD>
 
2448
                TRACE(("|%p|%p|WORD\n", body, context.text_ptr));
 
2449
                while (context.text_ptr < end_ptr && SRE_IS_WORD(context.text_ptr[0]))
 
2450
                    context.text_ptr++;
 
2451
                break;
 
2452
            }
 
2453
            start_ptr += repeat_min;
 
2454
            // Look at what follows to avoid unnecessary backtracking.
 
2455
            while (look_literal[0] == SRE_OP_MARK)
 
2456
                look_literal += 2;
 
2457
            SRE_LOOK_AHEAD_MANY(&context, start_ptr, state, look_literal);
 
2458
            // Matched at least the minimum?
 
2459
            if (context.text_ptr < start_ptr)
 
2460
                goto backtrack;
 
2461
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_ONE_MAX, repeat_ptr, index);
 
2462
            if (result != 0)
 
2463
                return SRE_CLEANUP(&context, state, result);
 
2464
            context.repeat_counter[index] = repeat_min + (context.text_ptr - start_ptr);
 
2465
            context.pattern_ptr = tail;
 
2466
            break;
 
2467
        }
 
2468
        case SRE_OP_REPEAT_ONE_MAX_REV:
 
2469
        {
 
2470
            // Greedy repeat.
 
2471
            // <REPEAT_ONE_MAX_REV> <skip to end> <index> <min> <max> ...
 
2472
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2473
            int index = context.pattern_ptr[1];
 
2474
            int repeat_min = context.pattern_ptr[2];
 
2475
            int repeat_max = context.pattern_ptr[3];
 
2476
            SRE_CODE* body = context.pattern_ptr + 4;
 
2477
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
2478
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
2479
            SRE_CODE* look_literal = tail;
 
2480
            SRE_CHAR* start_ptr = context.text_ptr;
 
2481
            SRE_CHAR* end_ptr;
 
2482
            TRACE(("|%p|%p|REPEAT_ONE_MAX_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2483
            if (repeat_min > limit)
 
2484
                goto backtrack;
 
2485
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
2486
            end_ptr = start_ptr - repeat_max;
 
2487
            // Match up to the maximum.
 
2488
            switch (body[0]) {
 
2489
            case SRE_OP_ANY_REV:
 
2490
                // <ANY_REV>
 
2491
                TRACE(("|%p|%p|ANY_REV\n", body, context.text_ptr));
 
2492
                while (context.text_ptr > end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[-1]))
 
2493
                    context.text_ptr--;
 
2494
                break;
 
2495
            case SRE_OP_ANY_ALL_REV:
 
2496
                // <ANY_ALL_REV>
 
2497
                TRACE(("|%p|%p|ANY_ALL_REV\n", body, context.text_ptr));
 
2498
                context.text_ptr = end_ptr;
 
2499
                break;
 
2500
            case SRE_OP_BIGCHARSET_REV:
 
2501
                // <BIGCHARSET_REV> <charset>
 
2502
                TRACE(("|%p|%p|BIGCHARSET_REV\n", body, context.text_ptr));
 
2503
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, context.text_ptr[-1]))
 
2504
                    context.text_ptr--;
 
2505
                break;
 
2506
            case SRE_OP_BIGCHARSET_IGNORE_REV:
 
2507
                // <BIGCHARSET_IGNORE_REV> <charset>
 
2508
                TRACE(("|%p|%p|BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
2509
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
2510
                    context.text_ptr--;
 
2511
                break;
 
2512
            case SRE_OP_CHARSET_REV:
 
2513
                // <CHARSET_REV> <charset>
 
2514
                TRACE(("|%p|%p|CHARSET_REV\n", body, context.text_ptr));
 
2515
                while (context.text_ptr > end_ptr && in_charset(body + 1, context.text_ptr[-1]))
 
2516
                    context.text_ptr--;
 
2517
                break;
 
2518
            case SRE_OP_CHARSET_IGNORE_REV:
 
2519
                // <CHARSET_IGNORE_REV> <charset>
 
2520
                TRACE(("|%p|%p|CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
2521
                while (context.text_ptr > end_ptr && in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
2522
                    context.text_ptr--;
 
2523
                break;
 
2524
            case SRE_OP_DIGIT_REV:
 
2525
                // <DIGIT_REV>
 
2526
                TRACE(("|%p|%p|DIGIT_REV\n", body, context.text_ptr));
 
2527
                while (context.text_ptr > end_ptr && SRE_IS_DIGIT(context.text_ptr[-1]))
 
2528
                    context.text_ptr--;
 
2529
                break;
 
2530
            case SRE_OP_IN_REV:
 
2531
                // <IN_REV> <set>
 
2532
                TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
2533
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, context.text_ptr[-1]))
 
2534
                    context.text_ptr--;
 
2535
                break;
 
2536
            case SRE_OP_IN_IGNORE_REV:
 
2537
                // <IN_IGNORE_REV> <set>
 
2538
                TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
2539
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
2540
                    context.text_ptr--;
 
2541
                break;
 
2542
            case SRE_OP_LITERAL_REV:
 
2543
                // <LITERAL_REV> <code>
 
2544
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
2545
                while (context.text_ptr > end_ptr && context.text_ptr[-1] == (SRE_CHAR)body[1])
 
2546
                    context.text_ptr--;
 
2547
                break;
 
2548
            case SRE_OP_LITERAL_IGNORE_REV:
 
2549
                // <LITERAL_IGNORE_REV> <code>
 
2550
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
2551
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) == (SRE_CHAR)body[1])
 
2552
                    context.text_ptr--;
 
2553
                break;
 
2554
            case SRE_OP_LOC_NOT_WORD_REV:
 
2555
                // <LOC_NOT_WORD_REV>
 
2556
                TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", body, context.text_ptr));
 
2557
                while (context.text_ptr > end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
2558
                    context.text_ptr--;
 
2559
                break;
 
2560
            case SRE_OP_LOC_WORD_REV:
 
2561
                // <LOC_WORD_REV>
 
2562
                TRACE(("|%p|%p|LOC_WORD_REV\n", body, context.text_ptr));
 
2563
                while (context.text_ptr > end_ptr && SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
2564
                    context.text_ptr--;
 
2565
                break;
 
2566
            case SRE_OP_NOT_BIGCHARSET_REV:
 
2567
                // <NOT_BIGCHARSET_REV> <charset>
 
2568
                TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", body, context.text_ptr));
 
2569
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, context.text_ptr[-1]))
 
2570
                    context.text_ptr--;
 
2571
                break;
 
2572
            case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
2573
                // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
2574
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
2575
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
2576
                    context.text_ptr--;
 
2577
                break;
 
2578
            case SRE_OP_NOT_CHARSET_REV:
 
2579
                // <NOT_CHARSET_REV> <charset>
 
2580
                TRACE(("|%p|%p|NOT_CHARSET_REV\n", body, context.text_ptr));
 
2581
                while (context.text_ptr > end_ptr && !in_charset(body + 1, context.text_ptr[-1]))
 
2582
                    context.text_ptr--;
 
2583
                break;
 
2584
            case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
2585
                // <NOT_CHARSET_IGNORE_REV> <charset>
 
2586
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
2587
                while (context.text_ptr > end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
2588
                    context.text_ptr--;
 
2589
                break;
 
2590
            case SRE_OP_NOT_DIGIT_REV:
 
2591
                // <NOT_DIGIT_REV>
 
2592
                TRACE(("|%p|%p|NOT_DIGIT_REV\n", body, context.text_ptr));
 
2593
                while (context.text_ptr > end_ptr && !SRE_IS_DIGIT(context.text_ptr[-1]))
 
2594
                    context.text_ptr--;
 
2595
                break;
 
2596
            case SRE_OP_NOT_IN_REV:
 
2597
                // <NOT_IN_REV> <set>
 
2598
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
2599
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, context.text_ptr[-1]))
 
2600
                    context.text_ptr--;
 
2601
                break;
 
2602
            case SRE_OP_NOT_IN_IGNORE_REV:
 
2603
                // <NOT_IN_IGNORE_REV> <set>
 
2604
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
2605
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
2606
                    context.text_ptr--;
 
2607
                break;
 
2608
            case SRE_OP_NOT_LITERAL_REV:
 
2609
                // <NOT_LITERAL_REV> <code>
 
2610
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
2611
                while (context.text_ptr > end_ptr && context.text_ptr[-1] != (SRE_CHAR)body[1])
 
2612
                    context.text_ptr--;
 
2613
                break;
 
2614
            case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
2615
                // <NOT_LITERAL_IGNORE_REV> <code>
 
2616
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
2617
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) != (SRE_CHAR)body[1])
 
2618
                    context.text_ptr--;
 
2619
                break;
 
2620
            case SRE_OP_NOT_RANGE_REV:
 
2621
                // <NOT_RANGE_REV> <lower> <upper>
 
2622
                TRACE(("|%p|%p|NOT_RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2623
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
2624
                    context.text_ptr--;
 
2625
                break;
 
2626
            case SRE_OP_NOT_RANGE_IGNORE_REV:
 
2627
                // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
2628
                TRACE(("|%p|%p|NOT_RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2629
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
2630
                    context.text_ptr--;
 
2631
                break;
 
2632
            case SRE_OP_NOT_WHITESPACE_REV:
 
2633
                // <NOT_WHITESPACE_REV>
 
2634
                TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
2635
                while (context.text_ptr > end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
2636
                    context.text_ptr--;
 
2637
                break;
 
2638
            case SRE_OP_NOT_WORD_REV:
 
2639
                // <NOT_WORD_REV>
 
2640
                TRACE(("|%p|%p|NOT_WORD_REV\n", body, context.text_ptr));
 
2641
                while (context.text_ptr > end_ptr && !SRE_IS_WORD(context.text_ptr[-1]))
 
2642
                    context.text_ptr--;
 
2643
                break;
 
2644
            case SRE_OP_RANGE_REV:
 
2645
                // <RANGE_REV> <lower> <upper>
 
2646
                TRACE(("|%p|%p|RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2647
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
2648
                    context.text_ptr--;
 
2649
                break;
 
2650
            case SRE_OP_RANGE_IGNORE_REV:
 
2651
                // <RANGE_IGNORE_REV> <lower> <upper>
 
2652
                TRACE(("|%p|%p|RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2653
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
2654
                    context.text_ptr--;
 
2655
                break;
 
2656
            case SRE_OP_UNI_DIGIT_REV:
 
2657
                // <UNI_DIGIT_REV>
 
2658
                TRACE(("|%p|%p|UNI_DIGIT_REV\n", body, context.text_ptr));
 
2659
                while (context.text_ptr > end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
2660
                    context.text_ptr--;
 
2661
                break;
 
2662
            case SRE_OP_UNI_NOT_DIGIT_REV:
 
2663
                // <UNI_NOT_DIGIT_REV>
 
2664
                TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", body, context.text_ptr));
 
2665
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
2666
                    context.text_ptr--;
 
2667
                break;
 
2668
            case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
2669
                // <UNI_NOT_WHITESPACE_REV>
 
2670
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
2671
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
2672
                    context.text_ptr--;
 
2673
                break;
 
2674
            case SRE_OP_UNI_NOT_WORD_REV:
 
2675
                // <UNI_NOT_WORD_REV>
 
2676
                TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", body, context.text_ptr));
 
2677
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
2678
                    context.text_ptr--;
 
2679
                break;
 
2680
            case SRE_OP_UNI_WHITESPACE_REV:
 
2681
                // <UNI_WHITESPACE_REV>
 
2682
                TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", body, context.text_ptr));
 
2683
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
2684
                    context.text_ptr--;
 
2685
                break;
 
2686
            case SRE_OP_UNI_WORD_REV:
 
2687
                // <UNI_WORD_REV>
 
2688
                TRACE(("|%p|%p|UNI_WORD_REV\n", body, context.text_ptr));
 
2689
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
2690
                    context.text_ptr--;
 
2691
                break;
 
2692
            case SRE_OP_WHITESPACE_REV:
 
2693
                // <WHITESPACE_REV>
 
2694
                TRACE(("|%p|%p|WHITESPACE_REV\n", body, context.text_ptr));
 
2695
                while (context.text_ptr > end_ptr && SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
2696
                    context.text_ptr--;
 
2697
                break;
 
2698
            case SRE_OP_WORD_REV:
 
2699
                // <WORD_REV>
 
2700
                TRACE(("|%p|%p|WORD_REV\n", body, context.text_ptr));
 
2701
                while (context.text_ptr > end_ptr && SRE_IS_WORD(context.text_ptr[-1]))
 
2702
                    context.text_ptr--;
 
2703
                break;
 
2704
            }
 
2705
            start_ptr -= repeat_min;
 
2706
            // Look at what follows to avoid unnecessary backtracking.
 
2707
            while (look_literal[0] == SRE_OP_MARK)
 
2708
                look_literal += 2;
 
2709
            SRE_LOOK_AHEAD_MANY_REV(&context, start_ptr, state, look_literal);
 
2710
            // Matched at least the minimum?
 
2711
            if (context.text_ptr > start_ptr)
 
2712
                goto backtrack;
 
2713
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_ONE_MAX_REV, repeat_ptr, index);
 
2714
            if (result != 0)
 
2715
                return SRE_CLEANUP(&context, state, result);
 
2716
            context.repeat_counter[index] = repeat_min + (start_ptr - context.text_ptr);
 
2717
            context.pattern_ptr = tail;
 
2718
            break;
 
2719
        }
 
2720
        case SRE_OP_REPEAT_ONE_MIN:
 
2721
        {
 
2722
            // Lazy repeat.
 
2723
            // <REPEAT_ONE_MIN> <skip to end> <index> <min> <max> ...
 
2724
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
2725
            int index = context.pattern_ptr[1];
 
2726
            int repeat_min = context.pattern_ptr[2];
 
2727
            int repeat_max = context.pattern_ptr[3];
 
2728
            SRE_CODE* body = context.pattern_ptr + 4;
 
2729
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
2730
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
2731
            SRE_CODE* look_literal = tail;
 
2732
            SRE_CHAR* start_ptr = context.text_ptr;
 
2733
            SRE_CHAR* end_ptr;
 
2734
            int match;
 
2735
            TRACE(("|%p|%p|REPEAT_ONE_MIN %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
2736
            if (repeat_min > limit)
 
2737
                goto backtrack;
 
2738
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
2739
            end_ptr = start_ptr + repeat_min;
 
2740
            // First match the minimum.
 
2741
            switch (body[0]) {
 
2742
            case SRE_OP_ANY:
 
2743
                // <ANY>
 
2744
                TRACE(("|%p|%p|ANY\n", body, context.text_ptr));
 
2745
                while (context.text_ptr < end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[0]))
 
2746
                    context.text_ptr++;
 
2747
                break;
 
2748
            case SRE_OP_ANY_ALL:
 
2749
                // <ANY_ALL>
 
2750
                TRACE(("|%p|%p|ANY_ALL\n", body, context.text_ptr));
 
2751
                context.text_ptr = end_ptr;
 
2752
                break;
 
2753
            case SRE_OP_BIGCHARSET:
 
2754
                // <BIGCHARSET> <charset>
 
2755
                TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
2756
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, context.text_ptr[0]))
 
2757
                    context.text_ptr++;
 
2758
                break;
 
2759
            case SRE_OP_BIGCHARSET_IGNORE:
 
2760
                // <BIGCHARSET_IGNORE> <charset>
 
2761
                TRACE(("|%p|%p|BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
2762
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
2763
                    context.text_ptr++;
 
2764
                break;
 
2765
            case SRE_OP_CHARSET:
 
2766
                // <CHARSET> <charset>
 
2767
                TRACE(("|%p|%p|CHARSET\n", body, context.text_ptr));
 
2768
                while (context.text_ptr < end_ptr && in_charset(body + 1, context.text_ptr[0]))
 
2769
                    context.text_ptr++;
 
2770
                break;
 
2771
            case SRE_OP_CHARSET_IGNORE:
 
2772
                // <CHARSET_IGNORE> <charset>
 
2773
                TRACE(("|%p|%p|CHARSET_IGNORE\n", body, context.text_ptr));
 
2774
                while (context.text_ptr < end_ptr && in_charset(body + 1, state->lower(context.text_ptr[0])))
 
2775
                    context.text_ptr++;
 
2776
                break;
 
2777
            case SRE_OP_DIGIT:
 
2778
                // <DIGIT>
 
2779
                TRACE(("|%p|%p|DIGIT\n", body, context.text_ptr));
 
2780
                while (context.text_ptr < end_ptr && SRE_IS_DIGIT(context.text_ptr[0]))
 
2781
                    context.text_ptr++;
 
2782
                break;
 
2783
            case SRE_OP_IN:
 
2784
                // <IN> <set>
 
2785
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
2786
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, context.text_ptr[0]))
 
2787
                    context.text_ptr++;
 
2788
                break;
 
2789
            case SRE_OP_IN_IGNORE:
 
2790
                // <IN_IGNORE> <set>
 
2791
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
2792
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
2793
                    context.text_ptr++;
 
2794
                break;
 
2795
            case SRE_OP_LITERAL:
 
2796
                // <LITERAL> <code>
 
2797
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
2798
                while (context.text_ptr < end_ptr && context.text_ptr[0] == (SRE_CHAR)body[1])
 
2799
                    context.text_ptr++;
 
2800
                break;
 
2801
            case SRE_OP_LITERAL_IGNORE:
 
2802
                // <LITERAL_IGNORE> <code>
 
2803
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
2804
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) == (SRE_CHAR)body[1])
 
2805
                    context.text_ptr++;
 
2806
                break;
 
2807
            case SRE_OP_LOC_NOT_WORD:
 
2808
                // <LOC_NOT_WORD>
 
2809
                TRACE(("|%p|%p|LOC_NOT_WORD\n", body, context.text_ptr));
 
2810
                while (context.text_ptr < end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[0]))
 
2811
                    context.text_ptr++;
 
2812
                break;
 
2813
            case SRE_OP_LOC_WORD:
 
2814
                // <LOC_WORD>
 
2815
                TRACE(("|%p|%p|LOC_WORD\n", body, context.text_ptr));
 
2816
                while (context.text_ptr < end_ptr && SRE_LOC_IS_WORD(context.text_ptr[0]))
 
2817
                    context.text_ptr++;
 
2818
                break;
 
2819
            case SRE_OP_NOT_BIGCHARSET:
 
2820
                // <NOT_BIGCHARSET> <charset>
 
2821
                TRACE(("|%p|%p|NOT_BIGCHARSET\n", body, context.text_ptr));
 
2822
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, context.text_ptr[0]))
 
2823
                    context.text_ptr++;
 
2824
                break;
 
2825
            case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
2826
                // <NOT_BIGCHARSET_IGNORE> <charset>
 
2827
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
2828
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
2829
                    context.text_ptr++;
 
2830
                break;
 
2831
            case SRE_OP_NOT_CHARSET:
 
2832
                // <NOT_CHARSET> <charset>
 
2833
                TRACE(("|%p|%p|NOT_CHARSET\n", body, context.text_ptr));
 
2834
                while (context.text_ptr < end_ptr && !in_charset(body + 1, context.text_ptr[0]))
 
2835
                    context.text_ptr++;
 
2836
                break;
 
2837
            case SRE_OP_NOT_CHARSET_IGNORE:
 
2838
                // <NOT_CHARSET_IGNORE> <charset>
 
2839
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", body, context.text_ptr));
 
2840
                while (context.text_ptr < end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[0])))
 
2841
                    context.text_ptr++;
 
2842
                break;
 
2843
            case SRE_OP_NOT_DIGIT:
 
2844
                // <NOT_DIGIT>
 
2845
                TRACE(("|%p|%p|NOT_DIGIT\n", body, context.text_ptr));
 
2846
                while (context.text_ptr < end_ptr && !SRE_IS_DIGIT(context.text_ptr[0]))
 
2847
                    context.text_ptr++;
 
2848
                break;
 
2849
            case SRE_OP_NOT_IN:
 
2850
                // <NOT_IN> <set>
 
2851
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
2852
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, context.text_ptr[0]))
 
2853
                    context.text_ptr++;
 
2854
                break;
 
2855
            case SRE_OP_NOT_IN_IGNORE:
 
2856
                // <NOT_IN_IGNORE> <set>
 
2857
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
2858
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
2859
                    context.text_ptr++;
 
2860
                break;
 
2861
            case SRE_OP_NOT_LITERAL:
 
2862
                // <NOT_LITERAL> <code>
 
2863
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
2864
                while (context.text_ptr < end_ptr && context.text_ptr[0] != (SRE_CHAR)body[1])
 
2865
                    context.text_ptr++;
 
2866
                break;
 
2867
            case SRE_OP_NOT_LITERAL_IGNORE:
 
2868
                // <NOT_LITERAL_IGNORE> <code>
 
2869
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
2870
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) != (SRE_CHAR)body[1])
 
2871
                    context.text_ptr++;
 
2872
                break;
 
2873
            case SRE_OP_NOT_RANGE:
 
2874
                // <NOT_RANGE> <lower> <upper>
 
2875
                TRACE(("|%p|%p|NOT_RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2876
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
2877
                    context.text_ptr++;
 
2878
                break;
 
2879
            case SRE_OP_NOT_RANGE_IGNORE:
 
2880
                // <NOT_RANGE_IGNORE> <lower> <upper>
 
2881
                TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2882
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
2883
                    context.text_ptr++;
 
2884
                break;
 
2885
            case SRE_OP_NOT_WHITESPACE:
 
2886
                // <NOT_WHITESPACE>
 
2887
                TRACE(("|%p|%p|NOT_WHITESPACE\n", body, context.text_ptr));
 
2888
                while (context.text_ptr < end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[0]))
 
2889
                    context.text_ptr++;
 
2890
                break;
 
2891
            case SRE_OP_NOT_WORD:
 
2892
                // <NOT_WORD>
 
2893
                TRACE(("|%p|%p|NOT_WORD\n", body, context.text_ptr));
 
2894
                while (context.text_ptr < end_ptr && !SRE_IS_WORD(context.text_ptr[0]))
 
2895
                    context.text_ptr++;
 
2896
                break;
 
2897
            case SRE_OP_RANGE:
 
2898
                // <RANGE> <lower> <upper>
 
2899
                TRACE(("|%p|%p|RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2900
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
2901
                    context.text_ptr++;
 
2902
                break;
 
2903
            case SRE_OP_RANGE_IGNORE:
 
2904
                // <RANGE_IGNORE> <lower> <upper>
 
2905
                TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
2906
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
2907
                    context.text_ptr++;
 
2908
                break;
 
2909
            case SRE_OP_UNI_DIGIT:
 
2910
                // <UNI_DIGIT>
 
2911
                TRACE(("|%p|%p|UNI_DIGIT\n", body, context.text_ptr));
 
2912
                while (context.text_ptr < end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
2913
                    context.text_ptr++;
 
2914
                break;
 
2915
            case SRE_OP_UNI_NOT_DIGIT:
 
2916
                // <UNI_NOT_DIGIT>
 
2917
                TRACE(("|%p|%p|UNI_NOT_DIGIT\n", body, context.text_ptr));
 
2918
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
2919
                    context.text_ptr++;
 
2920
                break;
 
2921
            case SRE_OP_UNI_NOT_WHITESPACE:
 
2922
                // <UNI_NOT_WHITESPACE>
 
2923
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", body, context.text_ptr));
 
2924
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
2925
                    context.text_ptr++;
 
2926
                break;
 
2927
            case SRE_OP_UNI_NOT_WORD:
 
2928
                // <UNI_NOT_WORD>
 
2929
                TRACE(("|%p|%p|UNI_NOT_WORD\n", body, context.text_ptr));
 
2930
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[0]))
 
2931
                    context.text_ptr++;
 
2932
                break;
 
2933
            case SRE_OP_UNI_WHITESPACE:
 
2934
                // <UNI_WHITESPACE>
 
2935
                TRACE(("|%p|%p|UNI_WHITESPACE\n", body, context.text_ptr));
 
2936
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
2937
                    context.text_ptr++;
 
2938
                break;
 
2939
            case SRE_OP_UNI_WORD:
 
2940
                // <UNI_WORD>
 
2941
                TRACE(("|%p|%p|UNI_WORD\n", body, context.text_ptr));
 
2942
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WORD(context.text_ptr[0]))
 
2943
                    context.text_ptr++;
 
2944
                break;
 
2945
            case SRE_OP_WHITESPACE:
 
2946
                // <WHITESPACE>
 
2947
                TRACE(("|%p|%p|WHITESPACE\n", body, context.text_ptr));
 
2948
                while (context.text_ptr < end_ptr && SRE_IS_WHITESPACE(context.text_ptr[0]))
 
2949
                    context.text_ptr++;
 
2950
                break;
 
2951
            case SRE_OP_WORD:
 
2952
                // <WORD>
 
2953
                TRACE(("|%p|%p|WORD\n", body, context.text_ptr));
 
2954
                while (context.text_ptr < end_ptr && SRE_IS_WORD(context.text_ptr[0]))
 
2955
                    context.text_ptr++;
 
2956
                break;
 
2957
            }
 
2958
            // Matched at least the minimum?
 
2959
            if (context.text_ptr < end_ptr)
 
2960
                goto backtrack;
 
2961
            // Now try up to the maximum.
 
2962
            end_ptr = start_ptr + repeat_max;
 
2963
            while (look_literal[0] == SRE_OP_MARK)
 
2964
                look_literal += 2;
 
2965
next_min:
 
2966
            // Look at what follows to avoid unnecessary backtracking.
 
2967
            if (SRE_LOOK_AHEAD_ONE(&context, state, look_literal)) {
 
2968
                if (context.text_ptr < end_ptr) {
 
2969
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_ONE_MIN, repeat_ptr, index);
 
2970
                    if (result != 0)
 
2971
                        return SRE_CLEANUP(&context, state, result);
 
2972
                }
 
2973
                context.repeat_counter[index] = context.text_ptr - start_ptr;
 
2974
                context.pattern_ptr = tail;
 
2975
                goto advance;
 
2976
            }
 
2977
            // Try another.
 
2978
            if (context.text_ptr >= end_ptr)
 
2979
                goto backtrack;
 
2980
            switch (body[0]) {
 
2981
            case SRE_OP_ANY:
 
2982
                // <ANY>
 
2983
                TRACE(("|%p|%p|ANY\n", body, context.text_ptr));
 
2984
                match = !SRE_IS_LINEBREAK(context.text_ptr[0]);
 
2985
                break;
 
2986
            case SRE_OP_ANY_ALL:
 
2987
                // <ANY_ALL>
 
2988
                TRACE(("|%p|%p|ANY_ALL\n", body, context.text_ptr));
 
2989
                match = 1;
 
2990
                break;
 
2991
            case SRE_OP_BIGCHARSET:
 
2992
                // <BIGCHARSET> <charset>
 
2993
                TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
2994
                match = in_bigcharset(body + 1, context.text_ptr[0]);
 
2995
                break;
 
2996
            case SRE_OP_BIGCHARSET_IGNORE:
 
2997
                // <BIGCHARSET_IGNORE> <charset>
 
2998
                TRACE(("|%p|%p|BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
2999
                match = in_bigcharset(body + 1, state->lower(context.text_ptr[0]));
 
3000
                break;
 
3001
            case SRE_OP_CHARSET:
 
3002
                // <CHARSET> <charset>
 
3003
                TRACE(("|%p|%p|CHARSET\n", body, context.text_ptr));
 
3004
                match = in_charset(body + 1, context.text_ptr[0]);
 
3005
                break;
 
3006
            case SRE_OP_CHARSET_IGNORE:
 
3007
                // <CHARSET_IGNORE> <charset>
 
3008
                TRACE(("|%p|%p|CHARSET_IGNORE\n", body, context.text_ptr));
 
3009
                match = in_charset(body + 1, state->lower(context.text_ptr[0]));
 
3010
                break;
 
3011
            case SRE_OP_DIGIT:
 
3012
                // <DIGIT>
 
3013
                TRACE(("|%p|%p|DIGIT\n", body, context.text_ptr));
 
3014
                match = SRE_IS_DIGIT(context.text_ptr[0]);
 
3015
                break;
 
3016
            case SRE_OP_IN:
 
3017
                // <IN> <set>
 
3018
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3019
                match = SRE_IN(body + 1, context.text_ptr[0]);
 
3020
                break;
 
3021
            case SRE_OP_IN_IGNORE:
 
3022
                // <IN_IGNORE> <set>
 
3023
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3024
                match = SRE_IN(body + 1, state->lower(context.text_ptr[0]));
 
3025
                break;
 
3026
            case SRE_OP_LITERAL:
 
3027
                // <LITERAL> <code>
 
3028
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
3029
                match = context.text_ptr[0] == (SRE_CHAR)body[1];
 
3030
                break;
 
3031
            case SRE_OP_LITERAL_IGNORE:
 
3032
                // <LITERAL_IGNORE> <code>
 
3033
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
3034
                match = state->lower(context.text_ptr[0]) == (SRE_CHAR)body[1];
 
3035
                break;
 
3036
            case SRE_OP_LOC_NOT_WORD:
 
3037
                // <LOC_NOT_WORD>
 
3038
                TRACE(("|%p|%p|LOC_NOT_WORD\n", body, context.text_ptr));
 
3039
                match = !SRE_LOC_IS_WORD(context.text_ptr[0]);
 
3040
                break;
 
3041
            case SRE_OP_LOC_WORD:
 
3042
                // <LOC_WORD>
 
3043
                TRACE(("|%p|%p|LOC_WORD\n", body, context.text_ptr));
 
3044
                match = SRE_LOC_IS_WORD(context.text_ptr[0]);
 
3045
                break;
 
3046
            case SRE_OP_NOT_BIGCHARSET:
 
3047
                // <NOT_BIGCHARSET> <charset>
 
3048
                TRACE(("|%p|%p|NOT_BIGCHARSET\n", body, context.text_ptr));
 
3049
                match = !in_bigcharset(body + 1, context.text_ptr[0]);
 
3050
                break;
 
3051
            case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
3052
                // <NOT_BIGCHARSET_IGNORE> <charset>
 
3053
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
3054
                match = !in_bigcharset(body + 1, state->lower(context.text_ptr[0]));
 
3055
                break;
 
3056
            case SRE_OP_NOT_CHARSET:
 
3057
                // <NOT_CHARSET> <charset>
 
3058
                TRACE(("|%p|%p|NOT_CHARSET\n", body, context.text_ptr));
 
3059
                match = !in_charset(body + 1, context.text_ptr[0]);
 
3060
                break;
 
3061
            case SRE_OP_NOT_CHARSET_IGNORE:
 
3062
                // <NOT_CHARSET_IGNORE> <charset>
 
3063
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", body, context.text_ptr));
 
3064
                match = !in_charset(body + 1, state->lower(context.text_ptr[0]));
 
3065
                break;
 
3066
            case SRE_OP_NOT_DIGIT:
 
3067
                // <NOT_DIGIT>
 
3068
                TRACE(("|%p|%p|NOT_DIGIT\n", body, context.text_ptr));
 
3069
                match = !SRE_IS_DIGIT(context.text_ptr[0]);
 
3070
                break;
 
3071
            case SRE_OP_NOT_IN:
 
3072
                // <NOT_IN> <set>
 
3073
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
3074
                match = !SRE_IN(body + 1, context.text_ptr[0]);
 
3075
                break;
 
3076
            case SRE_OP_NOT_IN_IGNORE:
 
3077
                // <NOT_IN_IGNORE> <set>
 
3078
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
3079
                match = !SRE_IN(body + 1, state->lower(context.text_ptr[0]));
 
3080
                break;
 
3081
            case SRE_OP_NOT_LITERAL:
 
3082
                // <NOT_LITERAL> <code>
 
3083
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
3084
                match = context.text_ptr[0] != (SRE_CHAR)body[1];
 
3085
                break;
 
3086
            case SRE_OP_NOT_LITERAL_IGNORE:
 
3087
                // <NOT_LITERAL_IGNORE> <code>
 
3088
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
3089
                match = state->lower(context.text_ptr[0]) != (SRE_CHAR)body[1];
 
3090
                break;
 
3091
            case SRE_OP_NOT_RANGE:
 
3092
                // <NOT_RANGE> <lower> <upper>
 
3093
                TRACE(("|%p|%p|NOT_RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3094
                match = !SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]);
 
3095
                break;
 
3096
            case SRE_OP_NOT_RANGE_IGNORE:
 
3097
                // <NOT_RANGE_IGNORE> <lower> <upper>
 
3098
                TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3099
                match = !SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]);
 
3100
                break;
 
3101
            case SRE_OP_NOT_WHITESPACE:
 
3102
                // <NOT_WHITESPACE>
 
3103
                TRACE(("|%p|%p|NOT_WHITESPACE\n", body, context.text_ptr));
 
3104
                match = !SRE_IS_WHITESPACE(context.text_ptr[0]);
 
3105
                break;
 
3106
            case SRE_OP_NOT_WORD:
 
3107
                // <NOT_WORD>
 
3108
                TRACE(("|%p|%p|NOT_WORD\n", body, context.text_ptr));
 
3109
                match = !SRE_IS_WORD(context.text_ptr[0]);
 
3110
                break;
 
3111
            case SRE_OP_RANGE:
 
3112
                // <RANGE> <lower> <upper>
 
3113
                TRACE(("|%p|%p|RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3114
                match = SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]);
 
3115
                break;
 
3116
            case SRE_OP_RANGE_IGNORE:
 
3117
                // <RANGE_IGNORE> <lower> <upper>
 
3118
                TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3119
                match = SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]);
 
3120
                break;
 
3121
            case SRE_OP_UNI_DIGIT:
 
3122
                // <UNI_DIGIT>
 
3123
                TRACE(("|%p|%p|UNI_DIGIT\n", body, context.text_ptr));
 
3124
                match = SRE_UNI_IS_DIGIT(context.text_ptr[0]);
 
3125
                break;
 
3126
            case SRE_OP_UNI_NOT_DIGIT:
 
3127
                // <UNI_NOT_DIGIT>
 
3128
                TRACE(("|%p|%p|UNI_NOT_DIGIT\n", body, context.text_ptr));
 
3129
                match = !SRE_UNI_IS_DIGIT(context.text_ptr[0]);
 
3130
                break;
 
3131
            case SRE_OP_UNI_NOT_WHITESPACE:
 
3132
                // <UNI_NOT_WHITESPACE>
 
3133
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", body, context.text_ptr));
 
3134
                match = !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]);
 
3135
                break;
 
3136
            case SRE_OP_UNI_NOT_WORD:
 
3137
                // <UNI_NOT_WORD>
 
3138
                TRACE(("|%p|%p|UNI_NOT_WORD\n", body, context.text_ptr));
 
3139
                match = !SRE_UNI_IS_WORD(context.text_ptr[0]);
 
3140
                break;
 
3141
            case SRE_OP_UNI_WHITESPACE:
 
3142
                // <UNI_WHITESPACE>
 
3143
                TRACE(("|%p|%p|UNI_WHITESPACE\n", body, context.text_ptr));
 
3144
                match = SRE_UNI_IS_WHITESPACE(context.text_ptr[0]);
 
3145
                break;
 
3146
            case SRE_OP_UNI_WORD:
 
3147
                // <UNI_WORD>
 
3148
                TRACE(("|%p|%p|UNI_WORD\n", body, context.text_ptr));
 
3149
                match = SRE_UNI_IS_WORD(context.text_ptr[0]);
 
3150
                break;
 
3151
            case SRE_OP_WHITESPACE:
 
3152
                // <WHITESPACE>
 
3153
                TRACE(("|%p|%p|WHITESPACE\n", body, context.text_ptr));
 
3154
                match = SRE_IS_WHITESPACE(context.text_ptr[0]);
 
3155
                break;
 
3156
            case SRE_OP_WORD:
 
3157
                // <WORD>
 
3158
                TRACE(("|%p|%p|WORD\n", body, context.text_ptr));
 
3159
                match = SRE_IS_WORD(context.text_ptr[0]);
 
3160
                break;
 
3161
            }
 
3162
            if (! match)
 
3163
                goto backtrack;
 
3164
            context.text_ptr++;
 
3165
            goto next_min;
 
3166
        }
 
3167
        case SRE_OP_REPEAT_ONE_MIN_REV:
 
3168
        {
 
3169
            // Lazy repeat.
 
3170
            // <REPEAT_ONE_MIN_REV> <skip to end> <index> <min> <max> ...
 
3171
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
3172
            int index = context.pattern_ptr[1];
 
3173
            int repeat_min = context.pattern_ptr[2];
 
3174
            int repeat_max = context.pattern_ptr[3];
 
3175
            SRE_CODE* body = context.pattern_ptr + 4;
 
3176
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
3177
            Py_ssize_t limit = context.text_start - context.text_ptr;
 
3178
            SRE_CODE* look_literal = tail;
 
3179
            SRE_CHAR* start_ptr = context.text_ptr;
 
3180
            SRE_CHAR* end_ptr;
 
3181
            int match;
 
3182
            TRACE(("|%p|%p|REPEAT_ONE_MIN_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
3183
            if (repeat_min > limit)
 
3184
                goto backtrack;
 
3185
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
3186
            end_ptr = start_ptr - repeat_min;
 
3187
            // First match the minimum.
 
3188
            switch (body[0]) {
 
3189
            case SRE_OP_ANY_REV:
 
3190
                // <ANY_REV>
 
3191
                TRACE(("|%p|%p|ANY_REV\n", body, context.text_ptr));
 
3192
                while (context.text_ptr > end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[-1]))
 
3193
                    context.text_ptr--;
 
3194
                break;
 
3195
            case SRE_OP_ANY_ALL_REV:
 
3196
                // <ANY_ALL_REV>
 
3197
                TRACE(("|%p|%p|ANY_ALL_REV\n", body, context.text_ptr));
 
3198
                context.text_ptr = end_ptr;
 
3199
                break;
 
3200
            case SRE_OP_BIGCHARSET_REV:
 
3201
                // <BIGCHARSET_REV> <charset>
 
3202
                TRACE(("|%p|%p|BIGCHARSET_REV\n", body, context.text_ptr));
 
3203
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, context.text_ptr[-1]))
 
3204
                    context.text_ptr--;
 
3205
                break;
 
3206
            case SRE_OP_BIGCHARSET_IGNORE_REV:
 
3207
                // <BIGCHARSET_IGNORE_REV> <charset>
 
3208
                TRACE(("|%p|%p|BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3209
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
3210
                    context.text_ptr--;
 
3211
                break;
 
3212
            case SRE_OP_CHARSET_REV:
 
3213
                // <CHARSET_REV> <charset>
 
3214
                TRACE(("|%p|%p|CHARSET_REV\n", body, context.text_ptr));
 
3215
                while (context.text_ptr > end_ptr && in_charset(body + 1, context.text_ptr[-1]))
 
3216
                    context.text_ptr--;
 
3217
                break;
 
3218
            case SRE_OP_CHARSET_IGNORE_REV:
 
3219
                // <CHARSET_IGNORE_REV> <charset>
 
3220
                TRACE(("|%p|%p|CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3221
                while (context.text_ptr > end_ptr && in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
3222
                    context.text_ptr--;
 
3223
                break;
 
3224
            case SRE_OP_DIGIT_REV:
 
3225
                // <DIGIT_REV>
 
3226
                TRACE(("|%p|%p|DIGIT_REV\n", body, context.text_ptr));
 
3227
                while (context.text_ptr > end_ptr && SRE_IS_DIGIT(context.text_ptr[-1]))
 
3228
                    context.text_ptr--;
 
3229
                break;
 
3230
            case SRE_OP_IN_REV:
 
3231
                // <IN_REV> <set>
 
3232
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3233
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, context.text_ptr[-1]))
 
3234
                    context.text_ptr--;
 
3235
                break;
 
3236
            case SRE_OP_IN_IGNORE_REV:
 
3237
                // <IN_IGNORE_REV> <set>
 
3238
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3239
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
3240
                    context.text_ptr--;
 
3241
                break;
 
3242
            case SRE_OP_LITERAL_REV:
 
3243
                // <LITERAL_REV> <code>
 
3244
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3245
                while (context.text_ptr > end_ptr && context.text_ptr[-1] == (SRE_CHAR)body[1])
 
3246
                    context.text_ptr--;
 
3247
                break;
 
3248
            case SRE_OP_LITERAL_IGNORE_REV:
 
3249
                // <LITERAL_IGNORE_REV> <code>
 
3250
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3251
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) == (SRE_CHAR)body[1])
 
3252
                    context.text_ptr--;
 
3253
                break;
 
3254
            case SRE_OP_LOC_NOT_WORD_REV:
 
3255
                // <LOC_NOT_WORD_REV>
 
3256
                TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", body, context.text_ptr));
 
3257
                while (context.text_ptr > end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
3258
                    context.text_ptr--;
 
3259
                break;
 
3260
            case SRE_OP_LOC_WORD_REV:
 
3261
                // <LOC_WORD_REV>
 
3262
                TRACE(("|%p|%p|LOC_WORD_REV\n", body, context.text_ptr));
 
3263
                while (context.text_ptr > end_ptr && SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
3264
                    context.text_ptr--;
 
3265
                break;
 
3266
            case SRE_OP_NOT_BIGCHARSET_REV:
 
3267
                // <NOT_BIGCHARSET_REV> <charset>
 
3268
                TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", body, context.text_ptr));
 
3269
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, context.text_ptr[-1]))
 
3270
                    context.text_ptr--;
 
3271
                break;
 
3272
            case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
3273
                // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
3274
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3275
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
3276
                    context.text_ptr--;
 
3277
                break;
 
3278
            case SRE_OP_NOT_CHARSET_REV:
 
3279
                // <NOT_CHARSET_REV> <charset>
 
3280
                TRACE(("|%p|%p|NOT_CHARSET_REV\n", body, context.text_ptr));
 
3281
                while (context.text_ptr > end_ptr && !in_charset(body + 1, context.text_ptr[-1]))
 
3282
                    context.text_ptr--;
 
3283
                break;
 
3284
            case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
3285
                // <NOT_CHARSET_IGNORE_REV> <charset>
 
3286
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3287
                while (context.text_ptr > end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
3288
                    context.text_ptr--;
 
3289
                break;
 
3290
            case SRE_OP_NOT_DIGIT_REV:
 
3291
                // <NOT_DIGIT_REV>
 
3292
                TRACE(("|%p|%p|NOT_DIGIT_REV\n", body, context.text_ptr));
 
3293
                while (context.text_ptr > end_ptr && !SRE_IS_DIGIT(context.text_ptr[-1]))
 
3294
                    context.text_ptr--;
 
3295
                break;
 
3296
            case SRE_OP_NOT_IN_REV:
 
3297
                // <NOT_IN_REV> <set>
 
3298
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3299
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, context.text_ptr[-1]))
 
3300
                    context.text_ptr--;
 
3301
                break;
 
3302
            case SRE_OP_NOT_IN_IGNORE_REV:
 
3303
                // <NOT_IN_IGNORE_REV> <set>
 
3304
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3305
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
3306
                    context.text_ptr--;
 
3307
                break;
 
3308
            case SRE_OP_NOT_LITERAL_REV:
 
3309
                // <NOT_LITERAL_REV> <code>
 
3310
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3311
                while (context.text_ptr > end_ptr && context.text_ptr[-1] != (SRE_CHAR)body[1])
 
3312
                    context.text_ptr--;
 
3313
                break;
 
3314
            case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
3315
                // <NOT_LITERAL_IGNORE_REV> <code>
 
3316
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3317
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) != (SRE_CHAR)body[1])
 
3318
                    context.text_ptr--;
 
3319
                break;
 
3320
            case SRE_OP_NOT_RANGE_REV:
 
3321
                // <NOT_RANGE_REV> <lower> <upper>
 
3322
                TRACE(("|%p|%p|NOT_RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3323
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
3324
                    context.text_ptr--;
 
3325
                break;
 
3326
            case SRE_OP_NOT_RANGE_IGNORE_REV:
 
3327
                // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
3328
                TRACE(("|%p|%p|NOT_RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3329
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
3330
                    context.text_ptr--;
 
3331
                break;
 
3332
            case SRE_OP_NOT_WHITESPACE_REV:
 
3333
                // <NOT_WHITESPACE_REV>
 
3334
                TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
3335
                while (context.text_ptr > end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
3336
                    context.text_ptr--;
 
3337
                break;
 
3338
            case SRE_OP_NOT_WORD_REV:
 
3339
                // <NOT_WORD_REV>
 
3340
                TRACE(("|%p|%p|NOT_WORD_REV\n", body, context.text_ptr));
 
3341
                while (context.text_ptr > end_ptr && !SRE_IS_WORD(context.text_ptr[-1]))
 
3342
                    context.text_ptr--;
 
3343
                break;
 
3344
            case SRE_OP_RANGE_REV:
 
3345
                // <RANGE_REV> <lower> <upper>
 
3346
                TRACE(("|%p|%p|RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3347
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
3348
                    context.text_ptr--;
 
3349
                break;
 
3350
            case SRE_OP_RANGE_IGNORE_REV:
 
3351
                // <RANGE_IGNORE_REV> <lower> <upper>
 
3352
                TRACE(("|%p|%p|RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3353
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
3354
                    context.text_ptr--;
 
3355
                break;
 
3356
            case SRE_OP_UNI_DIGIT_REV:
 
3357
                // <UNI_DIGIT_REV>
 
3358
                TRACE(("|%p|%p|UNI_DIGIT_REV\n", body, context.text_ptr));
 
3359
                while (context.text_ptr > end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
3360
                    context.text_ptr--;
 
3361
                break;
 
3362
            case SRE_OP_UNI_NOT_DIGIT_REV:
 
3363
                // <UNI_NOT_DIGIT_REV>
 
3364
                TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", body, context.text_ptr));
 
3365
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
3366
                    context.text_ptr--;
 
3367
                break;
 
3368
            case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
3369
                // <UNI_NOT_WHITESPACE_REV>
 
3370
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
3371
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
3372
                    context.text_ptr--;
 
3373
                break;
 
3374
            case SRE_OP_UNI_NOT_WORD_REV:
 
3375
                // <UNI_NOT_WORD_REV>
 
3376
                TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", body, context.text_ptr));
 
3377
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
3378
                    context.text_ptr--;
 
3379
                break;
 
3380
            case SRE_OP_UNI_WHITESPACE_REV:
 
3381
                // <UNI_WHITESPACE_REV>
 
3382
                TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", body, context.text_ptr));
 
3383
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
3384
                    context.text_ptr--;
 
3385
                break;
 
3386
            case SRE_OP_UNI_WORD_REV:
 
3387
                // <UNI_WORD_REV>
 
3388
                TRACE(("|%p|%p|UNI_WORD_REV\n", body, context.text_ptr));
 
3389
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
3390
                    context.text_ptr--;
 
3391
                break;
 
3392
            case SRE_OP_WHITESPACE_REV:
 
3393
                // <WHITESPACE_REV>
 
3394
                TRACE(("|%p|%p|WHITESPACE_REV\n", body, context.text_ptr));
 
3395
                while (context.text_ptr > end_ptr && SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
3396
                    context.text_ptr--;
 
3397
                break;
 
3398
            case SRE_OP_WORD_REV:
 
3399
                // <WORD_REV>
 
3400
                TRACE(("|%p|%p|WORD_REV\n", body, context.text_ptr));
 
3401
                while (context.text_ptr > end_ptr && SRE_IS_WORD(context.text_ptr[-1]))
 
3402
                    context.text_ptr--;
 
3403
                break;
 
3404
            }
 
3405
            // Matched at least the minimum?
 
3406
            if (context.text_ptr > end_ptr)
 
3407
                goto backtrack;
 
3408
            // Now try up to the maximum.
 
3409
            end_ptr = start_ptr - repeat_max;
 
3410
            while (look_literal[0] == SRE_OP_MARK)
 
3411
                look_literal += 2;
 
3412
next_min_rev:
 
3413
            // Look at what follows to avoid unnecessary backtracking.
 
3414
            if (SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal)) {
 
3415
                if (context.text_ptr > end_ptr) {
 
3416
                    result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_ONE_MIN_REV, repeat_ptr, index);
 
3417
                    if (result != 0)
 
3418
                        return SRE_CLEANUP(&context, state, result);
 
3419
                }
 
3420
                context.repeat_counter[index] = start_ptr - context.text_ptr;
 
3421
                context.pattern_ptr = tail;
 
3422
                goto advance;
 
3423
            }
 
3424
            // Try another.
 
3425
            if (context.text_ptr <= end_ptr)
 
3426
                goto backtrack;
 
3427
            switch (body[0]) {
 
3428
            case SRE_OP_ANY_REV:
 
3429
                // <ANY_REV>
 
3430
                TRACE(("|%p|%p|ANY_REV\n", body, context.text_ptr));
 
3431
                match = !SRE_IS_LINEBREAK(context.text_ptr[-1]);
 
3432
                break;
 
3433
            case SRE_OP_ANY_ALL_REV:
 
3434
                // <ANY_ALL_REV>
 
3435
                TRACE(("|%p|%p|ANY_ALL_REV\n", body, context.text_ptr));
 
3436
                match = 1;
 
3437
                break;
 
3438
            case SRE_OP_BIGCHARSET_REV:
 
3439
                // <BIGCHARSET_REV> <charset>
 
3440
                TRACE(("|%p|%p|BIGCHARSET_REV\n", body, context.text_ptr));
 
3441
                match = in_bigcharset(body + 1, context.text_ptr[-1]);
 
3442
                break;
 
3443
            case SRE_OP_BIGCHARSET_IGNORE_REV:
 
3444
                // <BIGCHARSET_IGNORE_REV> <charset>
 
3445
                TRACE(("|%p|%p|BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3446
                match = in_bigcharset(body + 1, state->lower(context.text_ptr[-1]));
 
3447
                break;
 
3448
            case SRE_OP_CHARSET_REV:
 
3449
                // <CHARSET_REV> <charset>
 
3450
                TRACE(("|%p|%p|CHARSET_REV\n", body, context.text_ptr));
 
3451
                match = in_charset(body + 1, context.text_ptr[-1]);
 
3452
                break;
 
3453
            case SRE_OP_CHARSET_IGNORE_REV:
 
3454
                // <CHARSET_IGNORE_REV> <charset>
 
3455
                TRACE(("|%p|%p|CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3456
                match = in_charset(body + 1, state->lower(context.text_ptr[-1]));
 
3457
                break;
 
3458
            case SRE_OP_DIGIT_REV:
 
3459
                // <DIGIT_REV>
 
3460
                TRACE(("|%p|%p|DIGIT_REV\n", body, context.text_ptr));
 
3461
                match = SRE_IS_DIGIT(context.text_ptr[-1]);
 
3462
                break;
 
3463
            case SRE_OP_IN_REV:
 
3464
                // <IN_REV> <set>
 
3465
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3466
                match = SRE_IN(body + 1, context.text_ptr[-1]);
 
3467
                break;
 
3468
            case SRE_OP_IN_IGNORE_REV:
 
3469
                // <IN_IGNORE_REV> <set>
 
3470
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3471
                match = SRE_IN(body + 1, state->lower(context.text_ptr[-1]));
 
3472
                break;
 
3473
            case SRE_OP_LITERAL_REV:
 
3474
                // <LITERAL_REV> <code>
 
3475
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3476
                match = context.text_ptr[-1] == (SRE_CHAR)body[1];
 
3477
                break;
 
3478
            case SRE_OP_LITERAL_IGNORE_REV:
 
3479
                // <LITERAL_IGNORE_REV> <code>
 
3480
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3481
                match = state->lower(context.text_ptr[-1]) == (SRE_CHAR)body[1];
 
3482
                break;
 
3483
            case SRE_OP_LOC_NOT_WORD_REV:
 
3484
                // <LOC_NOT_WORD_REV>
 
3485
                TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", body, context.text_ptr));
 
3486
                match = !SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
3487
                break;
 
3488
            case SRE_OP_LOC_WORD_REV:
 
3489
                // <LOC_WORD_REV>
 
3490
                TRACE(("|%p|%p|LOC_WORD_REV\n", body, context.text_ptr));
 
3491
                match = SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
3492
                break;
 
3493
            case SRE_OP_NOT_BIGCHARSET_REV:
 
3494
                // <NOT_BIGCHARSET_REV> <charset>
 
3495
                TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", body, context.text_ptr));
 
3496
                match = !in_bigcharset(body + 1, context.text_ptr[-1]);
 
3497
                break;
 
3498
            case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
3499
                // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
3500
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3501
                match = !in_bigcharset(body + 1, state->lower(context.text_ptr[-1]));
 
3502
                break;
 
3503
            case SRE_OP_NOT_CHARSET_REV:
 
3504
                // <NOT_CHARSET_REV> <charset>
 
3505
                TRACE(("|%p|%p|NOT_CHARSET_REV\n", body, context.text_ptr));
 
3506
                match = !in_charset(body + 1, context.text_ptr[-1]);
 
3507
                break;
 
3508
            case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
3509
                // <NOT_CHARSET_IGNORE_REV> <charset>
 
3510
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3511
                match = !in_charset(body + 1, state->lower(context.text_ptr[-1]));
 
3512
                break;
 
3513
            case SRE_OP_NOT_DIGIT_REV:
 
3514
                // <NOT_DIGIT_REV>
 
3515
                TRACE(("|%p|%p|NOT_DIGIT_REV\n", body, context.text_ptr));
 
3516
                match = !SRE_IS_DIGIT(context.text_ptr[-1]);
 
3517
                break;
 
3518
            case SRE_OP_NOT_IN_REV:
 
3519
                // <NOT_IN_REV> <set>
 
3520
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3521
                match = !SRE_IN(body + 1, context.text_ptr[-1]);
 
3522
                break;
 
3523
            case SRE_OP_NOT_IN_IGNORE_REV:
 
3524
                // <NOT_IN_IGNORE_REV> <set>
 
3525
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3526
                match = !SRE_IN(body + 1, state->lower(context.text_ptr[-1]));
 
3527
                break;
 
3528
            case SRE_OP_NOT_LITERAL_REV:
 
3529
                // <NOT_LITERAL_REV> <code>
 
3530
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3531
                match = context.text_ptr[-1] != (SRE_CHAR)body[1];
 
3532
                break;
 
3533
            case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
3534
                // <NOT_LITERAL_IGNORE_REV> <code>
 
3535
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3536
                match = state->lower(context.text_ptr[-1]) != (SRE_CHAR)body[1];
 
3537
                break;
 
3538
            case SRE_OP_NOT_RANGE_REV:
 
3539
                // <NOT_RANGE_REV> <lower> <upper>
 
3540
                TRACE(("|%p|%p|NOT_RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3541
                match = !SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]);
 
3542
                break;
 
3543
            case SRE_OP_NOT_RANGE_IGNORE_REV:
 
3544
                // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
3545
                TRACE(("|%p|%p|NOT_RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3546
                match = !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]);
 
3547
                break;
 
3548
            case SRE_OP_NOT_WHITESPACE_REV:
 
3549
                // <NOT_WHITESPACE_REV>
 
3550
                TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
3551
                match = !SRE_IS_WHITESPACE(context.text_ptr[-1]);
 
3552
                break;
 
3553
            case SRE_OP_NOT_WORD_REV:
 
3554
                // <NOT_WORD_REV>
 
3555
                TRACE(("|%p|%p|NOT_WORD_REV\n", body, context.text_ptr));
 
3556
                match = !SRE_IS_WORD(context.text_ptr[-1]);
 
3557
                break;
 
3558
            case SRE_OP_RANGE_REV:
 
3559
                // <RANGE_REV> <lower> <upper>
 
3560
                TRACE(("|%p|%p|RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3561
                match = SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]);
 
3562
                break;
 
3563
            case SRE_OP_RANGE_IGNORE_REV:
 
3564
                // <RANGE_IGNORE_REV> <lower> <upper>
 
3565
                TRACE(("|%p|%p|RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3566
                match = SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]);
 
3567
                break;
 
3568
            case SRE_OP_UNI_DIGIT_REV:
 
3569
                // <UNI_DIGIT_REV>
 
3570
                TRACE(("|%p|%p|UNI_DIGIT_REV\n", body, context.text_ptr));
 
3571
                match = SRE_UNI_IS_DIGIT(context.text_ptr[-1]);
 
3572
                break;
 
3573
            case SRE_OP_UNI_NOT_DIGIT_REV:
 
3574
                // <UNI_NOT_DIGIT_REV>
 
3575
                TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", body, context.text_ptr));
 
3576
                match = !SRE_UNI_IS_DIGIT(context.text_ptr[-1]);
 
3577
                break;
 
3578
            case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
3579
                // <UNI_NOT_WHITESPACE_REV>
 
3580
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
3581
                match = !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]);
 
3582
                break;
 
3583
            case SRE_OP_UNI_NOT_WORD_REV:
 
3584
                // <UNI_NOT_WORD_REV>
 
3585
                TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", body, context.text_ptr));
 
3586
                match = !SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
3587
                break;
 
3588
            case SRE_OP_UNI_WHITESPACE_REV:
 
3589
                // <UNI_WHITESPACE_REV>
 
3590
                TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", body, context.text_ptr));
 
3591
                match = SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]);
 
3592
                break;
 
3593
            case SRE_OP_UNI_WORD_REV:
 
3594
                // <UNI_WORD_REV>
 
3595
                TRACE(("|%p|%p|UNI_WORD_REV\n", body, context.text_ptr));
 
3596
                match = SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
3597
                break;
 
3598
            case SRE_OP_WHITESPACE_REV:
 
3599
                // <WHITESPACE_REV>
 
3600
                TRACE(("|%p|%p|WHITESPACE_REV\n", body, context.text_ptr));
 
3601
                match = SRE_IS_WHITESPACE(context.text_ptr[-1]);
 
3602
                break;
 
3603
            case SRE_OP_WORD_REV:
 
3604
                // <WORD_REV>
 
3605
                TRACE(("|%p|%p|WORD_REV\n", body, context.text_ptr));
 
3606
                match = SRE_IS_WORD(context.text_ptr[-1]);
 
3607
                break;
 
3608
            }
 
3609
            if (match)
 
3610
                goto backtrack;
 
3611
            context.text_ptr--;
 
3612
            goto next_min_rev;
 
3613
        }
 
3614
        case SRE_OP_REPEAT_ONE_POSS:
 
3615
        {
 
3616
            // Possessive repeat
 
3617
            // <REPEAT_ONE_POSS> <index> <skip to end> <min> <max> ...
 
3618
            int index = context.pattern_ptr[1];
 
3619
            int repeat_min = context.pattern_ptr[2];
 
3620
            int repeat_max = context.pattern_ptr[3];
 
3621
            SRE_CODE* body = context.pattern_ptr + 4;
 
3622
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
3623
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
3624
            SRE_CHAR* start_ptr = context.text_ptr;
 
3625
            SRE_CHAR* end_ptr;
 
3626
            TRACE(("|%p|%p|REPEAT_ONE_POSS %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
3627
            if (repeat_min > limit)
 
3628
                goto backtrack;
 
3629
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
3630
            end_ptr = start_ptr + repeat_max;
 
3631
            // Match up to the maximum.
 
3632
            switch (body[0]) {
 
3633
            case SRE_OP_ANY:
 
3634
                // <ANY>
 
3635
                TRACE(("|%p|%p|ANY\n", body, context.text_ptr));
 
3636
                while (context.text_ptr < end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[0]))
 
3637
                    context.text_ptr++;
 
3638
                break;
 
3639
            case SRE_OP_ANY_ALL:
 
3640
                // <ANY_ALL>
 
3641
                TRACE(("|%p|%p|ANY_ALL\n", body, context.text_ptr));
 
3642
                context.text_ptr = end_ptr;
 
3643
                break;
 
3644
            case SRE_OP_BIGCHARSET:
 
3645
                // <BIGCHARSET> <charset>
 
3646
                TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
3647
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, context.text_ptr[0]))
 
3648
                    context.text_ptr++;
 
3649
                break;
 
3650
            case SRE_OP_BIGCHARSET_IGNORE:
 
3651
                // <BIGCHARSET_IGNORE> <charset>
 
3652
                TRACE(("|%p|%p|BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
3653
                while (context.text_ptr < end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
3654
                    context.text_ptr++;
 
3655
                break;
 
3656
            case SRE_OP_CHARSET:
 
3657
                // <CHARSET> <charset>
 
3658
                TRACE(("|%p|%p|CHARSET\n", body, context.text_ptr));
 
3659
                while (context.text_ptr < end_ptr && in_charset(body + 1, context.text_ptr[0]))
 
3660
                    context.text_ptr++;
 
3661
                break;
 
3662
            case SRE_OP_CHARSET_IGNORE:
 
3663
                // <CHARSET_IGNORE> <charset>
 
3664
                TRACE(("|%p|%p|CHARSET_IGNORE\n", body, context.text_ptr));
 
3665
                while (context.text_ptr < end_ptr && in_charset(body + 1, state->lower(context.text_ptr[0])))
 
3666
                    context.text_ptr++;
 
3667
                break;
 
3668
            case SRE_OP_DIGIT:
 
3669
                // <DIGIT>
 
3670
                TRACE(("|%p|%p|DIGIT\n", body, context.text_ptr));
 
3671
                while (context.text_ptr < end_ptr && SRE_IS_DIGIT(context.text_ptr[0]))
 
3672
                    context.text_ptr++;
 
3673
                break;
 
3674
            case SRE_OP_IN:
 
3675
                // <IN> <set>
 
3676
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3677
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, context.text_ptr[0]))
 
3678
                    context.text_ptr++;
 
3679
                break;
 
3680
            case SRE_OP_IN_IGNORE:
 
3681
                // <IN_IGNORE> <set>
 
3682
                TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
3683
                while (context.text_ptr < end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
3684
                    context.text_ptr++;
 
3685
                break;
 
3686
            case SRE_OP_LITERAL:
 
3687
                // <LITERAL> <code>
 
3688
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
3689
                while (context.text_ptr < end_ptr && context.text_ptr[0] == (SRE_CHAR)body[1])
 
3690
                    context.text_ptr++;
 
3691
                break;
 
3692
            case SRE_OP_LITERAL_IGNORE:
 
3693
                // <LITERAL_IGNORE> <code>
 
3694
                TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
3695
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) == (SRE_CHAR)body[1])
 
3696
                    context.text_ptr++;
 
3697
                break;
 
3698
            case SRE_OP_LOC_NOT_WORD:
 
3699
                // <LOC_NOT_WORD>
 
3700
                TRACE(("|%p|%p|LOC_NOT_WORD\n", body, context.text_ptr));
 
3701
                while (context.text_ptr < end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[0]))
 
3702
                    context.text_ptr++;
 
3703
                break;
 
3704
            case SRE_OP_LOC_WORD:
 
3705
                // <LOC_WORD>
 
3706
                TRACE(("|%p|%p|LOC_WORD\n", body, context.text_ptr));
 
3707
                while (context.text_ptr < end_ptr && SRE_LOC_IS_WORD(context.text_ptr[0]))
 
3708
                    context.text_ptr++;
 
3709
                break;
 
3710
            case SRE_OP_NOT_BIGCHARSET:
 
3711
                // <NOT_BIGCHARSET> <charset>
 
3712
                TRACE(("|%p|%p|NOT_BIGCHARSET\n", body, context.text_ptr));
 
3713
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, context.text_ptr[0]))
 
3714
                    context.text_ptr++;
 
3715
                break;
 
3716
            case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
3717
                // <NOT_BIGCHARSET_IGNORE> <charset>
 
3718
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
3719
                while (context.text_ptr < end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[0])))
 
3720
                    context.text_ptr++;
 
3721
                break;
 
3722
            case SRE_OP_NOT_CHARSET:
 
3723
                // <NOT_CHARSET> <charset>
 
3724
                TRACE(("|%p|%p|NOT_CHARSET\n", body, context.text_ptr));
 
3725
                while (context.text_ptr < end_ptr && !in_charset(body + 1, context.text_ptr[0]))
 
3726
                    context.text_ptr++;
 
3727
                break;
 
3728
            case SRE_OP_NOT_CHARSET_IGNORE:
 
3729
                // <NOT_CHARSET_IGNORE> <charset>
 
3730
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", body, context.text_ptr));
 
3731
                while (context.text_ptr < end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[0])))
 
3732
                    context.text_ptr++;
 
3733
                break;
 
3734
            case SRE_OP_NOT_DIGIT:
 
3735
                // <NOT_DIGIT>
 
3736
                TRACE(("|%p|%p|NOT_DIGIT\n", body, context.text_ptr));
 
3737
                while (context.text_ptr < end_ptr && !SRE_IS_DIGIT(context.text_ptr[0]))
 
3738
                    context.text_ptr++;
 
3739
                break;
 
3740
            case SRE_OP_NOT_IN:
 
3741
                // <NOT_IN> <set>
 
3742
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
3743
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, context.text_ptr[0]))
 
3744
                    context.text_ptr++;
 
3745
                break;
 
3746
            case SRE_OP_NOT_IN_IGNORE:
 
3747
                // <NOT_IN_IGNORE> <set>
 
3748
                TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
3749
                while (context.text_ptr < end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[0])))
 
3750
                    context.text_ptr++;
 
3751
                break;
 
3752
            case SRE_OP_NOT_LITERAL:
 
3753
                // <NOT_LITERAL> <code>
 
3754
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[0]));
 
3755
                while (context.text_ptr < end_ptr && context.text_ptr[0] != (SRE_CHAR)body[1])
 
3756
                    context.text_ptr++;
 
3757
                break;
 
3758
            case SRE_OP_NOT_LITERAL_IGNORE:
 
3759
                // <NOT_LITERAL_IGNORE> <code>
 
3760
                TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[0]));
 
3761
                while (context.text_ptr < end_ptr && state->lower(context.text_ptr[0]) != (SRE_CHAR)body[1])
 
3762
                    context.text_ptr++;
 
3763
                break;
 
3764
            case SRE_OP_NOT_RANGE:
 
3765
                // <NOT_RANGE> <lower> <upper>
 
3766
                TRACE(("|%p|%p|NOT_RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3767
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
3768
                    context.text_ptr++;
 
3769
                break;
 
3770
            case SRE_OP_NOT_RANGE_IGNORE:
 
3771
                // <NOT_RANGE_IGNORE> <lower> <upper>
 
3772
                TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3773
                while (context.text_ptr < end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
3774
                    context.text_ptr++;
 
3775
                break;
 
3776
            case SRE_OP_NOT_WHITESPACE:
 
3777
                // <NOT_WHITESPACE>
 
3778
                TRACE(("|%p|%p|NOT_WHITESPACE\n", body, context.text_ptr));
 
3779
                while (context.text_ptr < end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[0]))
 
3780
                    context.text_ptr++;
 
3781
                break;
 
3782
            case SRE_OP_NOT_WORD:
 
3783
                // <NOT_WORD>
 
3784
                TRACE(("|%p|%p|NOT_WORD\n", body, context.text_ptr));
 
3785
                while (context.text_ptr < end_ptr && !SRE_IS_WORD(context.text_ptr[0]))
 
3786
                    context.text_ptr++;
 
3787
                break;
 
3788
            case SRE_OP_RANGE:
 
3789
                // <RANGE> <lower> <upper>
 
3790
                TRACE(("|%p|%p|RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3791
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]))
 
3792
                    context.text_ptr++;
 
3793
                break;
 
3794
            case SRE_OP_RANGE_IGNORE:
 
3795
                // <RANGE_IGNORE> <lower> <upper>
 
3796
                TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
3797
                while (context.text_ptr < end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]))
 
3798
                    context.text_ptr++;
 
3799
                break;
 
3800
            case SRE_OP_UNI_DIGIT:
 
3801
                // <UNI_DIGIT>
 
3802
                TRACE(("|%p|%p|UNI_DIGIT\n", body, context.text_ptr));
 
3803
                while (context.text_ptr < end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
3804
                    context.text_ptr++;
 
3805
                break;
 
3806
            case SRE_OP_UNI_NOT_DIGIT:
 
3807
                // <UNI_NOT_DIGIT>
 
3808
                TRACE(("|%p|%p|UNI_NOT_DIGIT\n", body, context.text_ptr));
 
3809
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
3810
                    context.text_ptr++;
 
3811
                break;
 
3812
            case SRE_OP_UNI_NOT_WHITESPACE:
 
3813
                // <UNI_NOT_WHITESPACE>
 
3814
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", body, context.text_ptr));
 
3815
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
3816
                    context.text_ptr++;
 
3817
                break;
 
3818
            case SRE_OP_UNI_NOT_WORD:
 
3819
                // <UNI_NOT_WORD>
 
3820
                TRACE(("|%p|%p|UNI_NOT_WORD\n", body, context.text_ptr));
 
3821
                while (context.text_ptr < end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[0]))
 
3822
                    context.text_ptr++;
 
3823
                break;
 
3824
            case SRE_OP_UNI_WHITESPACE:
 
3825
                // <UNI_WHITESPACE>
 
3826
                TRACE(("|%p|%p|UNI_WHITESPACE\n", body, context.text_ptr));
 
3827
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
3828
                    context.text_ptr++;
 
3829
                break;
 
3830
            case SRE_OP_UNI_WORD:
 
3831
                // <UNI_WORD>
 
3832
                TRACE(("|%p|%p|UNI_WORD\n", body, context.text_ptr));
 
3833
                while (context.text_ptr < end_ptr && SRE_UNI_IS_WORD(context.text_ptr[0]))
 
3834
                    context.text_ptr++;
 
3835
                break;
 
3836
            case SRE_OP_WHITESPACE:
 
3837
                // <WHITESPACE>
 
3838
                TRACE(("|%p|%p|WHITESPACE\n", body, context.text_ptr));
 
3839
                while (context.text_ptr < end_ptr && SRE_IS_WHITESPACE(context.text_ptr[0]))
 
3840
                    context.text_ptr++;
 
3841
                break;
 
3842
            case SRE_OP_WORD:
 
3843
                // <WORD>
 
3844
                TRACE(("|%p|%p|WORD\n", body, context.text_ptr));
 
3845
                while (context.text_ptr < end_ptr && SRE_IS_WORD(context.text_ptr[0]))
 
3846
                    context.text_ptr++;
 
3847
                break;
 
3848
            }
 
3849
            // Matched at least the minimum?
 
3850
            if (context.text_ptr < start_ptr + repeat_min)
 
3851
                goto backtrack;
 
3852
            context.pattern_ptr = tail;
 
3853
            break;
 
3854
        }
 
3855
        case SRE_OP_REPEAT_ONE_POSS_REV:
 
3856
        {
 
3857
            // Possessive repeat
 
3858
            // <REPEAT_ONE_POSS_REV> <index> <skip to end> <min> <max> ...
 
3859
            int index = context.pattern_ptr[1];
 
3860
            int repeat_min = context.pattern_ptr[2];
 
3861
            int repeat_max = context.pattern_ptr[3];
 
3862
            SRE_CODE* body = context.pattern_ptr + 4;
 
3863
            SRE_CODE* tail = context.pattern_ptr + context.pattern_ptr[0];
 
3864
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
3865
            SRE_CHAR* start_ptr = context.text_ptr;
 
3866
            SRE_CHAR* end_ptr;
 
3867
            TRACE(("|%p|%p|REPEAT_ONE_POSS_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
3868
            if (repeat_min > limit)
 
3869
                goto backtrack;
 
3870
            repeat_max = sre_repeat_limit(repeat_max, limit);
 
3871
            end_ptr = start_ptr - repeat_max;
 
3872
            // Now match up to the maximum.
 
3873
            switch (body[0]) {
 
3874
            case SRE_OP_ANY_REV:
 
3875
                // <ANY_REV>
 
3876
                TRACE(("|%p|%p|ANY_REV\n", body, context.text_ptr));
 
3877
                while (context.text_ptr > end_ptr && !SRE_IS_LINEBREAK(context.text_ptr[-1]))
 
3878
                    context.text_ptr--;
 
3879
                break;
 
3880
            case SRE_OP_ANY_ALL_REV:
 
3881
                // <ANY_ALL_REV>
 
3882
                TRACE(("|%p|%p|ANY_ALL_REV\n", body, context.text_ptr));
 
3883
                context.text_ptr = end_ptr;
 
3884
                break;
 
3885
            case SRE_OP_BIGCHARSET_REV:
 
3886
                // <BIGCHARSET_REV> <charset>
 
3887
                TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
3888
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, context.text_ptr[-1]))
 
3889
                    context.text_ptr--;
 
3890
                break;
 
3891
            case SRE_OP_BIGCHARSET_IGNORE_REV:
 
3892
                // <BIGCHARSET_IGNORE_REV> <charset>
 
3893
                TRACE(("|%p|%p|BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3894
                while (context.text_ptr > end_ptr && in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
3895
                    context.text_ptr--;
 
3896
                break;
 
3897
            case SRE_OP_CHARSET_REV:
 
3898
                // <CHARSET_REV> <charset>
 
3899
                TRACE(("|%p|%p|CHARSET_REV\n", body, context.text_ptr));
 
3900
                while (context.text_ptr > end_ptr && in_charset(body + 1, context.text_ptr[-1]))
 
3901
                    context.text_ptr--;
 
3902
                break;
 
3903
            case SRE_OP_CHARSET_IGNORE_REV:
 
3904
                // <CHARSET_IGNORE_REV> <charset>
 
3905
                TRACE(("|%p|%p|CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3906
                while (context.text_ptr > end_ptr && in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
3907
                    context.text_ptr--;
 
3908
                break;
 
3909
            case SRE_OP_DIGIT_REV:
 
3910
                // <DIGIT_REV>
 
3911
                TRACE(("|%p|%p|DIGIT_REV\n", body, context.text_ptr));
 
3912
                while (context.text_ptr > end_ptr && SRE_IS_DIGIT(context.text_ptr[-1]))
 
3913
                    context.text_ptr--;
 
3914
                break;
 
3915
            case SRE_OP_IN_REV:
 
3916
                // <IN_REV> <set>
 
3917
                TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
3918
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, context.text_ptr[-1]))
 
3919
                    context.text_ptr--;
 
3920
                break;
 
3921
            case SRE_OP_IN_IGNORE_REV:
 
3922
                // <IN_IGNORE_REV> <set>
 
3923
                TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
3924
                while (context.text_ptr > end_ptr && SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
3925
                    context.text_ptr--;
 
3926
                break;
 
3927
            case SRE_OP_LITERAL_REV:
 
3928
                // <LITERAL_REV> <code>
 
3929
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3930
                while (context.text_ptr > end_ptr && context.text_ptr[-1] == (SRE_CHAR)body[1])
 
3931
                    context.text_ptr--;
 
3932
                break;
 
3933
            case SRE_OP_LITERAL_IGNORE_REV:
 
3934
                // <LITERAL_IGNORE_REV> <code>
 
3935
                TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3936
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) == (SRE_CHAR)body[1])
 
3937
                    context.text_ptr--;
 
3938
                break;
 
3939
            case SRE_OP_LOC_NOT_WORD_REV:
 
3940
                // <LOC_NOT_WORD_REV>
 
3941
                TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", body, context.text_ptr));
 
3942
                while (context.text_ptr > end_ptr && !SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
3943
                    context.text_ptr--;
 
3944
                break;
 
3945
            case SRE_OP_LOC_WORD_REV:
 
3946
                // <LOC_WORD_REV>
 
3947
                TRACE(("|%p|%p|LOC_WORD_REV\n", body, context.text_ptr));
 
3948
                while (context.text_ptr > end_ptr && SRE_LOC_IS_WORD(context.text_ptr[-1]))
 
3949
                    context.text_ptr--;
 
3950
                break;
 
3951
            case SRE_OP_NOT_BIGCHARSET_REV:
 
3952
                // <NOT_BIGCHARSET_REV> <charset>
 
3953
                TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", body, context.text_ptr));
 
3954
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, context.text_ptr[-1]))
 
3955
                    context.text_ptr--;
 
3956
                break;
 
3957
            case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
3958
                // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
3959
                TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3960
                while (context.text_ptr > end_ptr && !in_bigcharset(body + 1, state->lower(context.text_ptr[-1])))
 
3961
                    context.text_ptr--;
 
3962
                break;
 
3963
            case SRE_OP_NOT_CHARSET_REV:
 
3964
                // <NOT_CHARSET_REV> <charset>
 
3965
                TRACE(("|%p|%p|NOT_CHARSET_REV\n", body, context.text_ptr));
 
3966
                while (context.text_ptr > end_ptr && !in_charset(body + 1, context.text_ptr[-1]))
 
3967
                    context.text_ptr--;
 
3968
                break;
 
3969
            case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
3970
                // <NOT_CHARSET_IGNORE_REV> <charset>
 
3971
                TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
3972
                while (context.text_ptr > end_ptr && !in_charset(body + 1, state->lower(context.text_ptr[-1])))
 
3973
                    context.text_ptr--;
 
3974
                break;
 
3975
            case SRE_OP_NOT_DIGIT_REV:
 
3976
                // <NOT_DIGIT_REV>
 
3977
                TRACE(("|%p|%p|NOT_DIGIT_REV\n", body, context.text_ptr));
 
3978
                while (context.text_ptr > end_ptr && !SRE_IS_DIGIT(context.text_ptr[-1]))
 
3979
                    context.text_ptr--;
 
3980
                break;
 
3981
            case SRE_OP_NOT_IN_REV:
 
3982
                // <NOT_IN_REV> <set>
 
3983
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3984
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, context.text_ptr[-1]))
 
3985
                    context.text_ptr--;
 
3986
                break;
 
3987
            case SRE_OP_NOT_IN_IGNORE_REV:
 
3988
                // <NOT_IN_IGNORE_REV> <set>
 
3989
                TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
3990
                while (context.text_ptr > end_ptr && !SRE_IN(body + 1, state->lower(context.text_ptr[-1])))
 
3991
                    context.text_ptr--;
 
3992
                break;
 
3993
            case SRE_OP_NOT_LITERAL_REV:
 
3994
                // <NOT_LITERAL_REV> <code>
 
3995
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
3996
                while (context.text_ptr > end_ptr && context.text_ptr[-1] != (SRE_CHAR)body[1])
 
3997
                    context.text_ptr--;
 
3998
                break;
 
3999
            case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
4000
                // <NOT_LITERAL_IGNORE_REV> <code>
 
4001
                TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
4002
                while (context.text_ptr > end_ptr && state->lower(context.text_ptr[-1]) != (SRE_CHAR)body[1])
 
4003
                    context.text_ptr--;
 
4004
                break;
 
4005
            case SRE_OP_NOT_RANGE_REV:
 
4006
                // <NOT_RANGE_REV> <lower> <upper>
 
4007
                TRACE(("|%p|%p|NOT_RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4008
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
4009
                    context.text_ptr--;
 
4010
                break;
 
4011
            case SRE_OP_NOT_RANGE_IGNORE_REV:
 
4012
                // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
4013
                TRACE(("|%p|%p|NOT_RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4014
                while (context.text_ptr > end_ptr && !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
4015
                    context.text_ptr--;
 
4016
                break;
 
4017
            case SRE_OP_NOT_WHITESPACE_REV:
 
4018
                // <NOT_WHITESPACE_REV>
 
4019
                TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
4020
                while (context.text_ptr > end_ptr && !SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
4021
                    context.text_ptr--;
 
4022
                break;
 
4023
            case SRE_OP_NOT_WORD_REV:
 
4024
                // <NOT_WORD_REV>
 
4025
                TRACE(("|%p|%p|NOT_WORD_REV\n", body, context.text_ptr));
 
4026
                while (context.text_ptr > end_ptr && !SRE_IS_WORD(context.text_ptr[-1]))
 
4027
                    context.text_ptr--;
 
4028
                break;
 
4029
            case SRE_OP_RANGE_REV:
 
4030
                // <RANGE_REV> <lower> <upper>
 
4031
                TRACE(("|%p|%p|RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4032
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]))
 
4033
                    context.text_ptr--;
 
4034
                break;
 
4035
            case SRE_OP_RANGE_IGNORE_REV:
 
4036
                // <RANGE_IGNORE_REV> <lower> <upper>
 
4037
                TRACE(("|%p|%p|RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4038
                while (context.text_ptr > end_ptr && SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]))
 
4039
                    context.text_ptr--;
 
4040
                break;
 
4041
            case SRE_OP_UNI_DIGIT_REV:
 
4042
                // <UNI_DIGIT_REV>
 
4043
                TRACE(("|%p|%p|UNI_DIGIT_REV\n", body, context.text_ptr));
 
4044
                while (context.text_ptr > end_ptr && SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
4045
                    context.text_ptr--;
 
4046
                break;
 
4047
            case SRE_OP_UNI_NOT_DIGIT_REV:
 
4048
                // <UNI_NOT_DIGIT_REV>
 
4049
                TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", body, context.text_ptr));
 
4050
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
4051
                    context.text_ptr--;
 
4052
                break;
 
4053
            case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
4054
                // <UNI_NOT_WHITESPACE_REV>
 
4055
                TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
4056
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
4057
                    context.text_ptr--;
 
4058
                break;
 
4059
            case SRE_OP_UNI_NOT_WORD_REV:
 
4060
                // <UNI_NOT_WORD_REV>
 
4061
                TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", body, context.text_ptr));
 
4062
                while (context.text_ptr > end_ptr && !SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
4063
                    context.text_ptr--;
 
4064
                break;
 
4065
            case SRE_OP_UNI_WHITESPACE_REV:
 
4066
                // <UNI_WHITESPACE_REV>
 
4067
                TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", body, context.text_ptr));
 
4068
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
4069
                    context.text_ptr--;
 
4070
                break;
 
4071
            case SRE_OP_UNI_WORD_REV:
 
4072
                // <UNI_WORD_REV>
 
4073
                TRACE(("|%p|%p|UNI_WORD_REV\n", body, context.text_ptr));
 
4074
                while (context.text_ptr > end_ptr && SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
4075
                    context.text_ptr--;
 
4076
                break;
 
4077
            case SRE_OP_WHITESPACE_REV:
 
4078
                // <WHITESPACE_REV>
 
4079
                TRACE(("|%p|%p|WHITESPACE_REV\n", body, context.text_ptr));
 
4080
                while (context.text_ptr > end_ptr && SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
4081
                    context.text_ptr--;
 
4082
                break;
 
4083
            case SRE_OP_WORD_REV:
 
4084
                // <WORD_REV>
 
4085
                TRACE(("|%p|%p|WORD_REV\n", body, context.text_ptr));
 
4086
                while (context.text_ptr > end_ptr && SRE_IS_WORD(context.text_ptr[-1]))
 
4087
                    context.text_ptr--;
 
4088
                break;
 
4089
            }
 
4090
            // Matched at least the minimum?
 
4091
            if (context.text_ptr > start_ptr + repeat_min)
 
4092
                goto backtrack;
 
4093
            context.pattern_ptr = tail;
 
4094
            break;
 
4095
        }
 
4096
        case SRE_OP_REPEAT_POSS:
 
4097
        {
 
4098
            // Possessive repeat.
 
4099
            // <REPEAT_POSS> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS> <skip to start>
 
4100
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
4101
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
4102
            SRE_CODE* tail = end_repeat_ptr + 1;
 
4103
            int index = repeat_ptr[1];
 
4104
            int repeat_min = repeat_ptr[2];
 
4105
            int repeat_max = repeat_ptr[3];
 
4106
            SRE_CODE* body = repeat_ptr + 4;
 
4107
            Py_ssize_t limit = context.text_end - context.text_ptr;
 
4108
            TRACE(("|%p|%p|REPEAT_POSS %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
4109
            if (repeat_min > limit)
 
4110
                goto backtrack;
 
4111
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_POSS, repeat_ptr, index);
 
4112
            if (result != 0)
 
4113
                return SRE_CLEANUP(&context, state, result);
 
4114
            result = SRE_SAVE_MARKS(&context);
 
4115
            if (result != 0)
 
4116
                return SRE_CLEANUP(&context, state, result);
 
4117
            context.repeat_counter[index] = 0;
 
4118
            if (repeat_min == 0) {
 
4119
                result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_POSS, end_repeat_ptr, -1);
 
4120
                if (result != 0)
 
4121
                    return SRE_CLEANUP(&context, state, result);
 
4122
                result = SRE_SAVE_MARKS(&context);
 
4123
                if (result != 0)
 
4124
                    return SRE_CLEANUP(&context, state, result);
 
4125
            }
 
4126
            context.pattern_ptr = body;
 
4127
            context.repeat_start[index] = context.text_ptr;
 
4128
            break;
 
4129
        }
 
4130
        case SRE_OP_REPEAT_POSS_REV:
 
4131
        {
 
4132
            // Possessive repeat.
 
4133
            // <REPEAT_POSS_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS_REV> <skip to start>
 
4134
            SRE_CODE* repeat_ptr = context.pattern_ptr;
 
4135
            SRE_CODE* end_repeat_ptr = context.pattern_ptr + context.pattern_ptr[0];
 
4136
            SRE_CODE* tail = end_repeat_ptr + 1;
 
4137
            int index = repeat_ptr[1];
 
4138
            int repeat_min = repeat_ptr[2];
 
4139
            int repeat_max = repeat_ptr[3];
 
4140
            SRE_CODE* body = repeat_ptr + 4;
 
4141
            Py_ssize_t limit = context.text_ptr - context.text_start;
 
4142
            TRACE(("|%p|%p|REPEAT_POSS_REV %d %d\n", context.pattern_ptr, context.text_ptr, repeat_min, repeat_max));
 
4143
            if (repeat_min > limit)
 
4144
                goto backtrack;
 
4145
            result = SRE_SAVE_BACKTRACK(&context, SRE_OP_REPEAT_POSS_REV, repeat_ptr, index);
 
4146
            if (result != 0)
 
4147
                return SRE_CLEANUP(&context, state, result);
 
4148
            result = SRE_SAVE_MARKS(&context);
 
4149
            if (result != 0)
 
4150
                return SRE_CLEANUP(&context, state, result);
 
4151
            context.repeat_counter[index] = 0;
 
4152
            if (repeat_min == 0) {
 
4153
                result = SRE_SAVE_BACKTRACK(&context, SRE_OP_END_REPEAT_POSS_REV, end_repeat_ptr, -1);
 
4154
                if (result != 0)
 
4155
                    return SRE_CLEANUP(&context, state, result);
 
4156
                result = SRE_SAVE_MARKS(&context);
 
4157
                if (result != 0)
 
4158
                    return SRE_CLEANUP(&context, state, result);
 
4159
            }
 
4160
            context.pattern_ptr = body;
 
4161
            context.repeat_start[index] = context.text_ptr;
 
4162
            break;
 
4163
        }
 
4164
        case SRE_OP_START_OF_LINE:
 
4165
            // Start of line.
 
4166
            // <START_OF_LINE>
 
4167
            TRACE(("|%p|%p|START_OF_LINE\n", context.pattern_ptr, context.text_ptr));
 
4168
            if (context.text_ptr > context.text_start && !SRE_IS_LINEBREAK(context.text_ptr[-1]))
 
4169
                goto backtrack;
 
4170
            break;
 
4171
        case SRE_OP_START_OF_STRING:
 
4172
            // Start of string.
 
4173
            // <START_OF_STRING>
 
4174
            TRACE(("|%p|%p|START_OF_STRING\n", context.pattern_ptr, context.text_ptr));
 
4175
            if (context.text_ptr > context.text_start)
 
4176
                goto backtrack;
 
4177
            break;
 
4178
        case SRE_OP_SUCCESS:
 
4179
        {
 
4180
            // End of pattern.
 
4181
            int m;
 
4182
            SRE_CHAR* end_ptr = NULL;
 
4183
            TRACE(("|%p|%p|SUCCESS\n", context.pattern_ptr, context.text_ptr));
 
4184
            // Find the mark which matched the furthest to the right.
 
4185
            for (m = 1; m < context.mark_count; m += 2) {
 
4186
                if (context.mark[m - 1] != NULL && context.mark[m] != NULL) {
 
4187
                    state->lastmark = m;
 
4188
                    if (end_ptr < context.mark[m]) {
 
4189
                        state->lastindex = 1 + m / 2;
 
4190
                        end_ptr = context.mark[m];
 
4191
                    }
 
4192
                }
 
4193
            }
 
4194
            state->ptr = context.text_ptr;
 
4195
            return SRE_CLEANUP(&context, state, 1);
 
4196
        }
 
4197
        case SRE_OP_UNI_BOUNDARY:
 
4198
        {
 
4199
            // Boundary between word and non-word.
 
4200
            // <UNI_BOUNDARY>
 
4201
            int before = context.text_ptr > context.text_start && SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
4202
            int after = context.text_ptr < context.text_end && SRE_UNI_IS_WORD(context.text_ptr[0]);
 
4203
            TRACE(("|%p|%p|UNI_BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
4204
            if (before == after)
 
4205
                goto backtrack;
 
4206
            break;
 
4207
        }
 
4208
        case SRE_OP_UNI_DIGIT:
 
4209
            // Digit.
 
4210
            // <UNI_DIGIT>
 
4211
            TRACE(("|%p|%p|UNI_DIGIT\n", context.pattern_ptr, context.text_ptr));
 
4212
            if (context.text_ptr >= context.text_end || !SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
4213
                goto backtrack;
 
4214
            context.text_ptr++;
 
4215
            break;
 
4216
        case SRE_OP_UNI_DIGIT_REV:
 
4217
            // Digit.
 
4218
            // <UNI_DIGIT_REV>
 
4219
            TRACE(("|%p|%p|UNI_DIGIT_REV\n", context.pattern_ptr, context.text_ptr));
 
4220
            if (context.text_ptr <= context.text_start || !SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
4221
                goto backtrack;
 
4222
            context.text_ptr--;
 
4223
            break;
 
4224
        case SRE_OP_UNI_NOT_BOUNDARY:
 
4225
        {
 
4226
            // Not boundary between word and non-word.
 
4227
            // <UNI_NOT_BOUNDARY>
 
4228
            int before = context.text_ptr > context.text_start && SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
4229
            int after = context.text_ptr < context.text_end && SRE_UNI_IS_WORD(context.text_ptr[0]);
 
4230
            TRACE(("|%p|%p|UNI_NOT_BOUNDARY\n", context.pattern_ptr, context.text_ptr));
 
4231
            if (before != after)
 
4232
                goto backtrack;
 
4233
            break;
 
4234
        }
 
4235
        case SRE_OP_UNI_NOT_DIGIT:
 
4236
            // Not digit.
 
4237
            // <UNI_NOT_DIGIT>
 
4238
            TRACE(("|%p|%p|UNI_NOT_DIGIT\n", context.pattern_ptr, context.text_ptr));
 
4239
            if (context.text_ptr >= context.text_end || SRE_UNI_IS_DIGIT(context.text_ptr[0]))
 
4240
                goto backtrack;
 
4241
            context.text_ptr++;
 
4242
            break;
 
4243
        case SRE_OP_UNI_NOT_DIGIT_REV:
 
4244
            // Not digit.
 
4245
            // <UNI_NOT_DIGIT_REV>
 
4246
            TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", context.pattern_ptr, context.text_ptr));
 
4247
            if (context.text_ptr <= context.text_start || SRE_UNI_IS_DIGIT(context.text_ptr[-1]))
 
4248
                goto backtrack;
 
4249
            context.text_ptr--;
 
4250
            break;
 
4251
        case SRE_OP_UNI_NOT_WHITESPACE:
 
4252
            // Not whitespace.
 
4253
            // <UNI_NOT_WHITESPACE>
 
4254
            TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", context.pattern_ptr, context.text_ptr));
 
4255
            if (context.text_ptr >= context.text_end || SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
4256
                goto backtrack;
 
4257
            context.text_ptr++;
 
4258
            break;
 
4259
        case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
4260
            // Not whitespace.
 
4261
            // <UNI_NOT_WHITESPACE_REV>
 
4262
            TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", context.pattern_ptr, context.text_ptr));
 
4263
            if (context.text_ptr <= context.text_start || SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
4264
                goto backtrack;
 
4265
            context.text_ptr--;
 
4266
            break;
 
4267
        case SRE_OP_UNI_NOT_WORD:
 
4268
            // Not word.
 
4269
            // <UNI_NOT_WORD>
 
4270
            TRACE(("|%p|%p|UNI_NOT_WORD\n", context.pattern_ptr, context.text_ptr));
 
4271
            if (context.text_ptr >= context.text_end || SRE_UNI_IS_WORD(context.text_ptr[0]))
 
4272
                goto backtrack;
 
4273
            context.text_ptr++;
 
4274
            break;
 
4275
        case SRE_OP_UNI_NOT_WORD_REV:
 
4276
            // Not word.
 
4277
            // <UNI_NOT_WORD_REV>
 
4278
            TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
4279
            if (context.text_ptr <= context.text_start || SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
4280
                goto backtrack;
 
4281
            context.text_ptr--;
 
4282
            break;
 
4283
        case SRE_OP_UNI_WHITESPACE:
 
4284
            // Whitespace.
 
4285
            // <UNI_WHITESPACE>
 
4286
            TRACE(("|%p|%p|UNI_WHITESPACE\n", context.pattern_ptr, context.text_ptr));
 
4287
            if (context.text_ptr >= context.text_end || !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]))
 
4288
                goto backtrack;
 
4289
            context.text_ptr++;
 
4290
            break;
 
4291
        case SRE_OP_UNI_WHITESPACE_REV:
 
4292
            // Whitespace.
 
4293
            // <UNI_WHITESPACE_REV>
 
4294
            TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", context.pattern_ptr, context.text_ptr));
 
4295
            if (context.text_ptr <= context.text_start || !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]))
 
4296
                goto backtrack;
 
4297
            context.text_ptr--;
 
4298
            break;
 
4299
        case SRE_OP_UNI_WORD:
 
4300
            // Word.
 
4301
            // <UNI_WORD>
 
4302
            TRACE(("|%p|%p|UNI_WORD\n", context.pattern_ptr, context.text_ptr));
 
4303
            if (context.text_ptr >= context.text_end || !SRE_UNI_IS_WORD(context.text_ptr[0]))
 
4304
                goto backtrack;
 
4305
            context.text_ptr++;
 
4306
            break;
 
4307
        case SRE_OP_UNI_WORD_REV:
 
4308
            // Word.
 
4309
            // <UNI_WORD_REV>
 
4310
            TRACE(("|%p|%p|UNI_WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
4311
            if (context.text_ptr <= context.text_start || !SRE_UNI_IS_WORD(context.text_ptr[-1]))
 
4312
                goto backtrack;
 
4313
            context.text_ptr--;
 
4314
            break;
 
4315
        case SRE_OP_WHITESPACE:
 
4316
            // Whitespace.
 
4317
            // <WHITESPACE>
 
4318
            TRACE(("|%p|%p|WHITESPACE\n", context.pattern_ptr, context.text_ptr));
 
4319
            if (context.text_ptr >= context.text_end || !SRE_IS_WHITESPACE(context.text_ptr[0]))
 
4320
                goto backtrack;
 
4321
            context.text_ptr++;
 
4322
            break;
 
4323
        case SRE_OP_WHITESPACE_REV:
 
4324
            // Whitespace.
 
4325
            // <WHITESPACE_REV>
 
4326
            TRACE(("|%p|%p|WHITESPACE_REV\n", context.pattern_ptr, context.text_ptr));
 
4327
            if (context.text_ptr <= context.text_start || !SRE_IS_WHITESPACE(context.text_ptr[-1]))
 
4328
                goto backtrack;
 
4329
            context.text_ptr--;
 
4330
            break;
 
4331
        case SRE_OP_WORD:
 
4332
            // Word.
 
4333
            // <WORD>
 
4334
            TRACE(("|%p|%p|WORD\n", context.pattern_ptr, context.text_ptr));
 
4335
            if (context.text_ptr >= context.text_end || !SRE_IS_WORD(context.text_ptr[0]))
 
4336
                goto backtrack;
 
4337
            context.text_ptr++;
 
4338
            break;
 
4339
        case SRE_OP_WORD_REV:
 
4340
            // Word.
 
4341
            // <WORD_REV>
 
4342
            TRACE(("|%p|%p|WORD_REV\n", context.pattern_ptr, context.text_ptr));
 
4343
            if (context.text_ptr <= context.text_start || !SRE_IS_WORD(context.text_ptr[-1]))
 
4344
                goto backtrack;
 
4345
            context.text_ptr--;
 
4346
            break;
 
4347
        default:
 
4348
            TRACE(("|%p|%p|UNKNOWN %d\n", context.pattern_ptr, context.text_ptr, context.pattern_ptr[-1]));
 
4349
            return SRE_CLEANUP(&context, state, SRE_ERROR_ILLEGAL);
 
4350
        }
 
4351
    }
 
4352
 
 
4353
backtrack:
 
4354
    TRACE(("|%p|%p|BACKTRACK ", context.pattern_ptr, context.text_ptr));
 
4355
    switch(context.backtrack_chunk->items[context.backtrack_chunk->count - 1].op) {
 
4356
    case SRE_OP_ASSERT:
 
4357
        // Assert subpattern.
 
4358
        // <ASSERT> <skip to end> ... <END_ASSERT>
 
4359
        TRACE(("ASSERT\n"));
 
4360
        SRE_RESTORE_MARKS(&context);
 
4361
        SRE_DISCARD_BACKTRACK(&context);
 
4362
        goto backtrack;
 
4363
    case SRE_OP_ASSERT_NOT:
 
4364
    {
 
4365
        // Assert not subpattern.
 
4366
        // <ASSERT_NOT> <skip to end> ... <END_ASSERT_NOT>
 
4367
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4368
        TRACE(("ASSERT_NOT\n"));
 
4369
        context.pattern_ptr = backtrack_item->pattern_ptr;
 
4370
        context.text_ptr = backtrack_item->text_ptr;
 
4371
        SRE_RESTORE_MARKS(&context);
 
4372
        SRE_DISCARD_BACKTRACK(&context);
 
4373
        context.pattern_ptr += context.pattern_ptr[0];
 
4374
        goto advance;
 
4375
    }
 
4376
    case SRE_OP_ATOMIC:
 
4377
        // Atomic subpattern.
 
4378
        // <ATOMIC> <skip to end> ... <END_ATOMIC>
 
4379
        TRACE(("ATOMIC\n"));
 
4380
        SRE_RESTORE_MARKS(&context);
 
4381
        SRE_DISCARD_BACKTRACK(&context);
 
4382
        goto backtrack;
 
4383
    case SRE_OP_BRANCH:
 
4384
    {
 
4385
        // Alternation.
 
4386
        // <BRANCH> <skip to next> ... <JUMP> <skip to end> <skip to next> ... <JUMP> <skip to end> 0
 
4387
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4388
        TRACE(("BRANCH\n"));
 
4389
        context.pattern_ptr = backtrack_item->pattern_ptr;
 
4390
        context.pattern_ptr += context.pattern_ptr[0];
 
4391
        SRE_RESTORE_MARKS(&context);
 
4392
        if (context.pattern_ptr[0] == 0) {
 
4393
            SRE_DISCARD_BACKTRACK(&context);
 
4394
            goto backtrack;
 
4395
        }
 
4396
        backtrack_item->pattern_ptr = context.pattern_ptr;
 
4397
        result = SRE_SAVE_MARKS(&context);
 
4398
        if (result != 0)
 
4399
            return SRE_CLEANUP(&context, state, result);
 
4400
        context.text_ptr = backtrack_item->text_ptr;
 
4401
        context.pattern_ptr++;
 
4402
        goto advance;
 
4403
    }
 
4404
    case SRE_OP_END_REPEAT_MAX:
 
4405
    {
 
4406
        // End of greedy repeat.
 
4407
        // <REPEAT_MAX> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX> <skip to start>
 
4408
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4409
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4410
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4411
        TRACE(("END_REPEAT_MAX\n"));
 
4412
        context.text_ptr = backtrack_item->text_ptr;
 
4413
        SRE_RESTORE_MARKS(&context);
 
4414
        SRE_DISCARD_BACKTRACK(&context);
 
4415
        context.pattern_ptr = tail;
 
4416
        goto advance;
 
4417
    }
 
4418
    case SRE_OP_END_REPEAT_MAX_REV:
 
4419
    {
 
4420
        // End of greedy repeat.
 
4421
        // <REPEAT_MAX_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX_REV> <skip to start>
 
4422
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4423
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4424
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4425
        TRACE(("END_REPEAT_MAX_REV\n"));
 
4426
        context.text_ptr = backtrack_item->text_ptr;
 
4427
        SRE_RESTORE_MARKS(&context);
 
4428
        SRE_DISCARD_BACKTRACK(&context);
 
4429
        context.pattern_ptr = tail;
 
4430
        goto advance;
 
4431
    }
 
4432
    case SRE_OP_END_REPEAT_MIN:
 
4433
    {
 
4434
        // End of lazy repeat.
 
4435
        // <REPEAT_MIN> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN> <skip to start>
 
4436
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4437
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4438
        SRE_CODE* repeat_ptr = end_repeat_ptr - end_repeat_ptr[0];
 
4439
        int index = repeat_ptr[1];
 
4440
        int repeat_max = repeat_ptr[3];
 
4441
        SRE_CODE* body = repeat_ptr + 4;
 
4442
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4443
        Py_ssize_t limit = context.text_end - context.text_ptr;
 
4444
        TRACE(("END_REPEAT_MIN\n"));
 
4445
        context.text_ptr = backtrack_item->text_ptr;
 
4446
        SRE_RESTORE_MARKS(&context);
 
4447
        SRE_DISCARD_BACKTRACK(&context);
 
4448
        if (limit == 0)
 
4449
            goto backtrack;
 
4450
        context.pattern_ptr = body;
 
4451
        goto advance;
 
4452
    }
 
4453
    case SRE_OP_END_REPEAT_MIN_REV:
 
4454
    {
 
4455
        // End of lazy repeat.
 
4456
        // <REPEAT_MIN_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN_REV> <skip to start>
 
4457
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4458
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4459
        SRE_CODE* repeat_ptr = end_repeat_ptr - end_repeat_ptr[0];
 
4460
        int index = repeat_ptr[1];
 
4461
        int repeat_max = repeat_ptr[3];
 
4462
        SRE_CODE* body = repeat_ptr + 4;
 
4463
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4464
        Py_ssize_t limit = context.text_ptr - context.text_start;
 
4465
        TRACE(("END_REPEAT_MIN_REV\n"));
 
4466
        context.text_ptr = backtrack_item->text_ptr;
 
4467
        SRE_RESTORE_MARKS(&context);
 
4468
        SRE_DISCARD_BACKTRACK(&context);
 
4469
        if (limit == 0)
 
4470
            goto backtrack;
 
4471
        context.pattern_ptr = body;
 
4472
        goto advance;
 
4473
    }
 
4474
    case SRE_OP_END_REPEAT_POSS:
 
4475
    {
 
4476
        // End of possessive repeat.
 
4477
        // <REPEAT_POSS> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS> <skip to start>
 
4478
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4479
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4480
        SRE_CODE* repeat_ptr = end_repeat_ptr - end_repeat_ptr[0];
 
4481
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4482
        TRACE(("END_REPEAT_POSS\n"));
 
4483
        context.text_ptr = backtrack_item->text_ptr;
 
4484
        SRE_RESTORE_MARKS(&context);
 
4485
        SRE_DISCARD_BACKTRACK(&context);
 
4486
        context.pattern_ptr = tail;
 
4487
        goto advance;
 
4488
    }
 
4489
    case SRE_OP_END_REPEAT_POSS_REV:
 
4490
    {
 
4491
        // End of possessive repeat.
 
4492
        // <REPEAT_POSS_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS_REV> <skip to start>
 
4493
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4494
        SRE_CODE* end_repeat_ptr = backtrack_item->pattern_ptr;
 
4495
        SRE_CODE* repeat_ptr = end_repeat_ptr - end_repeat_ptr[0];
 
4496
        SRE_CODE* tail = end_repeat_ptr + 1;
 
4497
        TRACE(("END_REPEAT_POSS_REV\n"));
 
4498
        context.text_ptr = backtrack_item->text_ptr;
 
4499
        SRE_RESTORE_MARKS(&context);
 
4500
        SRE_DISCARD_BACKTRACK(&context);
 
4501
        context.pattern_ptr = tail;
 
4502
        goto advance;
 
4503
    }
 
4504
    case SRE_OP_FAILURE:
 
4505
        // Failed to match.
 
4506
        return SRE_CLEANUP(&context, state, 0);
 
4507
    case SRE_OP_REPEAT_MAX:
 
4508
    {
 
4509
        // Greedy repeat.
 
4510
        // <REPEAT_MAX> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX> <skip to start>
 
4511
        TRACE(("REPEAT_MAX\n"));
 
4512
        SRE_RESTORE_MARKS(&context);
 
4513
        SRE_DISCARD_BACKTRACK(&context);
 
4514
        goto backtrack;
 
4515
    }
 
4516
    case SRE_OP_REPEAT_MAX_REV:
 
4517
    {
 
4518
        // Greedy repeat.
 
4519
        // <REPEAT_MAX_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MAX_REV> <skip to start>
 
4520
        TRACE(("REPEAT_MAX\n"));
 
4521
        SRE_RESTORE_MARKS(&context);
 
4522
        SRE_DISCARD_BACKTRACK(&context);
 
4523
        goto backtrack;
 
4524
    }
 
4525
    case SRE_OP_REPEAT_MIN:
 
4526
    {
 
4527
        // Lazy repeat.
 
4528
        // <REPEAT_MIN> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN> <skip to start>
 
4529
        TRACE(("REPEAT_MIN\n"));
 
4530
        SRE_RESTORE_MARKS(&context);
 
4531
        SRE_DISCARD_BACKTRACK(&context);
 
4532
        goto backtrack;
 
4533
    }
 
4534
    case SRE_OP_REPEAT_MIN_REV:
 
4535
    {
 
4536
        // Lazy repeat.
 
4537
        // <REPEAT_MIN_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_MIN_REV> <skip to start>
 
4538
        TRACE(("REPEAT_MIN\n"));
 
4539
        SRE_RESTORE_MARKS(&context);
 
4540
        SRE_DISCARD_BACKTRACK(&context);
 
4541
        goto backtrack;
 
4542
    }
 
4543
    case SRE_OP_REPEAT_ONE_MAX:
 
4544
    {
 
4545
        // Greedy repeat.
 
4546
        // <REPEAT_ONE_MAX> <skip to end> <index> <min> <max> ...
 
4547
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4548
        SRE_CODE* repeat_ptr = backtrack_item->pattern_ptr;
 
4549
        SRE_CODE* tail = repeat_ptr + repeat_ptr[0];
 
4550
        int index = repeat_ptr[1];
 
4551
        int repeat_min = repeat_ptr[2];
 
4552
        SRE_CHAR* start_ptr;
 
4553
        SRE_CODE* look_literal = tail;
 
4554
        context.text_ptr = backtrack_item->text_ptr;
 
4555
        start_ptr = context.text_ptr - context.repeat_counter[index] + repeat_min;
 
4556
        context.text_ptr--;
 
4557
        // Look at what follows to avoid unnecessary backtracking.
 
4558
        while (look_literal[0] == SRE_OP_MARK)
 
4559
            look_literal += 2;
 
4560
        SRE_LOOK_AHEAD_MANY(&context, start_ptr, state, look_literal);
 
4561
        // Matched at least the minimum?
 
4562
        if (context.text_ptr < start_ptr) {
 
4563
            SRE_DISCARD_BACKTRACK(&context);
 
4564
            goto backtrack;
 
4565
        }
 
4566
        backtrack_item->text_ptr = context.text_ptr;
 
4567
        context.repeat_counter[index] = repeat_min + (context.text_ptr - start_ptr);
 
4568
        context.pattern_ptr = tail;
 
4569
        goto advance;
 
4570
    }
 
4571
    case SRE_OP_REPEAT_ONE_MAX_REV:
 
4572
    {
 
4573
        // Greedy repeat.
 
4574
        // <REPEAT_ONE_MAX_REV> <skip to end> <index> <min> <max> ...
 
4575
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4576
        SRE_CODE* repeat_ptr = backtrack_item->pattern_ptr;
 
4577
        SRE_CODE* tail = repeat_ptr + repeat_ptr[0];
 
4578
        int index = repeat_ptr[1];
 
4579
        int repeat_min = repeat_ptr[2];
 
4580
        SRE_CHAR* start_ptr;
 
4581
        SRE_CODE* look_literal = tail;
 
4582
        context.text_ptr = backtrack_item->text_ptr;
 
4583
        start_ptr = context.text_ptr + context.repeat_counter[index] - repeat_min;
 
4584
        context.text_ptr++;
 
4585
        // Look at what follows to avoid unnecessary backtracking.
 
4586
        while (look_literal[0] == SRE_OP_MARK)
 
4587
            look_literal += 2;
 
4588
        SRE_LOOK_AHEAD_MANY_REV(&context, start_ptr, state, look_literal);
 
4589
        // Matched at least the minimum?
 
4590
        if (context.text_ptr > start_ptr) {
 
4591
            SRE_DISCARD_BACKTRACK(&context);
 
4592
            goto backtrack;
 
4593
        }
 
4594
        backtrack_item->text_ptr = context.text_ptr;
 
4595
        context.repeat_counter[index] = repeat_min + (start_ptr - context.text_ptr);
 
4596
        context.pattern_ptr = tail;
 
4597
        goto advance;
 
4598
    }
 
4599
    case SRE_OP_REPEAT_ONE_MIN:
 
4600
    {
 
4601
        // Lazy repeat.
 
4602
        // <REPEAT_ONE_MIN> <skip to end> <index> <min> <max> ...
 
4603
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4604
        SRE_CODE* repeat_ptr = backtrack_item->pattern_ptr;
 
4605
        int index = repeat_ptr[1];
 
4606
        int repeat_max = repeat_ptr[3];
 
4607
        SRE_CODE* body = repeat_ptr + 4;
 
4608
        SRE_CODE* tail = repeat_ptr + repeat_ptr[0];
 
4609
        SRE_CODE* look_literal = tail;
 
4610
        SRE_CHAR* start_ptr;
 
4611
        SRE_CHAR* end_ptr;
 
4612
        int match;
 
4613
        Py_ssize_t limit = context.text_end - context.text_ptr;
 
4614
        context.text_ptr = backtrack_item->text_ptr;
 
4615
        if (repeat_max > context.repeat_counter[index] + limit || repeat_max == UNLIMITED_REPEATS)
 
4616
            repeat_max = context.repeat_counter[index] + limit;
 
4617
        // Now match up to the maximum.
 
4618
        start_ptr = context.text_ptr - context.repeat_counter[index];
 
4619
        end_ptr = start_ptr + repeat_max;
 
4620
        if (context.text_ptr >= end_ptr) {
 
4621
            SRE_DISCARD_BACKTRACK(&context);
 
4622
            goto backtrack;
 
4623
        }
 
4624
        while (look_literal[0] == SRE_OP_MARK)
 
4625
            look_literal += 2;
 
4626
next_min_backtrack:
 
4627
        switch (body[0]) {
 
4628
        case SRE_OP_ANY:
 
4629
            // <ANY>
 
4630
            TRACE(("|%p|%p|ANY\n", body, context.text_ptr));
 
4631
            match = !SRE_IS_LINEBREAK(context.text_ptr[0]);
 
4632
            break;
 
4633
        case SRE_OP_ANY_ALL:
 
4634
            // <ANY_ALL>
 
4635
            TRACE(("|%p|%p|ANY_ALL\n", body, context.text_ptr));
 
4636
            match = 1;
 
4637
            break;
 
4638
        case SRE_OP_BIGCHARSET:
 
4639
            // <BIGCHARSET> <charset>
 
4640
            TRACE(("|%p|%p|BIGCHARSET\n", body, context.text_ptr));
 
4641
            match = in_bigcharset(body + 1, context.text_ptr[0]);
 
4642
            break;
 
4643
        case SRE_OP_BIGCHARSET_IGNORE:
 
4644
            // <BIGCHARSET_IGNORE> <charset>
 
4645
            TRACE(("|%p|%p|BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
4646
            match = in_bigcharset(body + 1, state->lower(context.text_ptr[0]));
 
4647
            break;
 
4648
        case SRE_OP_CHARSET:
 
4649
            // <CHARSET> <charset>
 
4650
            TRACE(("|%p|%p|CHARSET\n", body, context.text_ptr));
 
4651
            match = in_charset(body + 1, context.text_ptr[0]);
 
4652
            break;
 
4653
        case SRE_OP_CHARSET_IGNORE:
 
4654
            // <CHARSET_IGNORE> <charset>
 
4655
            TRACE(("|%p|%p|CHARSET_IGNORE\n", body, context.text_ptr));
 
4656
            match = in_charset(body + 1, state->lower(context.text_ptr[0]));
 
4657
            break;
 
4658
        case SRE_OP_DIGIT:
 
4659
            // <DIGIT>
 
4660
            TRACE(("|%p|%p|DIGIT\n", body, context.text_ptr));
 
4661
            match = SRE_IS_DIGIT(context.text_ptr[0]);
 
4662
            break;
 
4663
        case SRE_OP_IN:
 
4664
            // <IN> <set>
 
4665
            TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
4666
            match = SRE_IN(body + 1, context.text_ptr[0]);
 
4667
            break;
 
4668
        case SRE_OP_IN_IGNORE:
 
4669
            // <IN_IGNORE> <set>
 
4670
            TRACE(("|%p|%p|IN\n", body, context.text_ptr));
 
4671
            match = SRE_IN(body + 1, state->lower(context.text_ptr[0]));
 
4672
            break;
 
4673
        case SRE_OP_LITERAL:
 
4674
            // <LITERAL> <code>
 
4675
            TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
4676
            match = context.text_ptr[0] == (SRE_CHAR)body[1];
 
4677
            break;
 
4678
        case SRE_OP_LITERAL_IGNORE:
 
4679
            // <LITERAL_IGNORE> <code>
 
4680
            TRACE(("|%p|%p|LITERAL %d\n", body, context.text_ptr, body[1]));
 
4681
            match = state->lower(context.text_ptr[0]) == (SRE_CHAR)body[1];
 
4682
            break;
 
4683
        case SRE_OP_LOC_NOT_WORD:
 
4684
            // <LOC_NOT_WORD>
 
4685
            TRACE(("|%p|%p|LOC_NOT_WORD\n", body, context.text_ptr));
 
4686
            match = !SRE_LOC_IS_WORD(context.text_ptr[0]);
 
4687
            break;
 
4688
        case SRE_OP_LOC_WORD:
 
4689
            // <LOC_WORD>
 
4690
            TRACE(("|%p|%p|LOC_WORD\n", body, context.text_ptr));
 
4691
            match = SRE_LOC_IS_WORD(context.text_ptr[0]);
 
4692
            break;
 
4693
        case SRE_OP_NOT_BIGCHARSET:
 
4694
            // <NOT_BIGCHARSET> <charset>
 
4695
            TRACE(("|%p|%p|NOT_BIGCHARSET\n", body, context.text_ptr));
 
4696
            match = !in_bigcharset(body + 1, context.text_ptr[0]);
 
4697
            break;
 
4698
        case SRE_OP_NOT_BIGCHARSET_IGNORE:
 
4699
            // <NOT_BIGCHARSET_IGNORE> <charset>
 
4700
            TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE\n", body, context.text_ptr));
 
4701
            match = !in_bigcharset(body + 1, state->lower(context.text_ptr[0]));
 
4702
            break;
 
4703
        case SRE_OP_NOT_CHARSET:
 
4704
            // <NOT_CHARSET> <charset>
 
4705
            TRACE(("|%p|%p|NOT_CHARSET\n", body, context.text_ptr));
 
4706
            match = !in_charset(body + 1, context.text_ptr[0]);
 
4707
            break;
 
4708
        case SRE_OP_NOT_CHARSET_IGNORE:
 
4709
            // <NOT_CHARSET_IGNORE> <charset>
 
4710
            TRACE(("|%p|%p|NOT_CHARSET_IGNORE\n", body, context.text_ptr));
 
4711
            match = !in_charset(body + 1, state->lower(context.text_ptr[0]));
 
4712
            break;
 
4713
        case SRE_OP_NOT_DIGIT:
 
4714
            // <NOT_DIGIT>
 
4715
            TRACE(("|%p|%p|NOT_DIGIT\n", body, context.text_ptr));
 
4716
            match = !SRE_IS_DIGIT(context.text_ptr[0]);
 
4717
            break;
 
4718
        case SRE_OP_NOT_IN:
 
4719
            // <NOT_IN> <set>
 
4720
            TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
4721
            match = !SRE_IN(body + 1, context.text_ptr[0]);
 
4722
            break;
 
4723
        case SRE_OP_NOT_IN_IGNORE:
 
4724
            // <NOT_IN_IGNORE> <set>
 
4725
            TRACE(("|%p|%p|NOT_IN\n", body, context.text_ptr));
 
4726
            match = !SRE_IN(body + 1, state->lower(context.text_ptr[0]));
 
4727
            break;
 
4728
        case SRE_OP_NOT_LITERAL:
 
4729
            // <NOT_LITERAL> <code>
 
4730
            TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
4731
            match = context.text_ptr[0] != (SRE_CHAR)body[1];
 
4732
            break;
 
4733
        case SRE_OP_NOT_LITERAL_IGNORE:
 
4734
            // <NOT_LITERAL_IGNORE> <code>
 
4735
            TRACE(("|%p|%p|NOT_LITERAL %d\n", body, context.text_ptr, body[1]));
 
4736
            match = state->lower(context.text_ptr[0]) != (SRE_CHAR)body[1];
 
4737
            break;
 
4738
        case SRE_OP_NOT_RANGE:
 
4739
            // <NOT_RANGE> <lower> <upper>
 
4740
            TRACE(("|%p|%p|NOT_RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4741
            match = !SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]);
 
4742
            break;
 
4743
        case SRE_OP_NOT_RANGE_IGNORE:
 
4744
            // <NOT_RANGE_IGNORE> <lower> <upper>
 
4745
            TRACE(("|%p|%p|NOT_RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4746
            match = !SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]);
 
4747
            break;
 
4748
        case SRE_OP_NOT_WHITESPACE:
 
4749
            // <NOT_WHITESPACE>
 
4750
            TRACE(("|%p|%p|NOT_WHITESPACE\n", body, context.text_ptr));
 
4751
            match = !SRE_IS_WHITESPACE(context.text_ptr[0]);
 
4752
            break;
 
4753
        case SRE_OP_NOT_WORD:
 
4754
            // <NOT_WORD>
 
4755
            TRACE(("|%p|%p|NOT_WORD\n", body, context.text_ptr));
 
4756
            match = !SRE_IS_WORD(context.text_ptr[0]);
 
4757
            break;
 
4758
        case SRE_OP_RANGE:
 
4759
            // <RANGE> <lower> <upper>
 
4760
            TRACE(("|%p|%p|RANGE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4761
            match = SRE_IN_RANGE(context.text_ptr[0], body[1], body[2]);
 
4762
            break;
 
4763
        case SRE_OP_RANGE_IGNORE:
 
4764
            // <RANGE_IGNORE> <lower> <upper>
 
4765
            TRACE(("|%p|%p|RANGE_IGNORE %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4766
            match = SRE_IN_RANGE(state->lower(context.text_ptr[0]), body[1], body[2]);
 
4767
            break;
 
4768
        case SRE_OP_UNI_DIGIT:
 
4769
            // <UNI_DIGIT>
 
4770
            TRACE(("|%p|%p|UNI_DIGIT\n", body, context.text_ptr));
 
4771
            match = SRE_UNI_IS_DIGIT(context.text_ptr[0]);
 
4772
            break;
 
4773
        case SRE_OP_UNI_NOT_DIGIT:
 
4774
            // <UNI_NOT_DIGIT>
 
4775
            TRACE(("|%p|%p|UNI_NOT_DIGIT\n", body, context.text_ptr));
 
4776
            match = !SRE_UNI_IS_DIGIT(context.text_ptr[0]);
 
4777
            break;
 
4778
        case SRE_OP_UNI_NOT_WHITESPACE:
 
4779
            // <UNI_NOT_WHITESPACE>
 
4780
            TRACE(("|%p|%p|UNI_NOT_WHITESPACE\n", body, context.text_ptr));
 
4781
            match = !SRE_UNI_IS_WHITESPACE(context.text_ptr[0]);
 
4782
            break;
 
4783
        case SRE_OP_UNI_NOT_WORD:
 
4784
            // <UNI_NOT_WORD>
 
4785
            TRACE(("|%p|%p|UNI_NOT_WORD\n", body, context.text_ptr));
 
4786
            match = !SRE_UNI_IS_WORD(context.text_ptr[0]);
 
4787
            break;
 
4788
        case SRE_OP_UNI_WHITESPACE:
 
4789
            // <UNI_WHITESPACE>
 
4790
            TRACE(("|%p|%p|UNI_WHITESPACE\n", body, context.text_ptr));
 
4791
            match = SRE_UNI_IS_WHITESPACE(context.text_ptr[0]);
 
4792
            break;
 
4793
        case SRE_OP_UNI_WORD:
 
4794
            // <UNI_WORD>
 
4795
            TRACE(("|%p|%p|UNI_WORD\n", body, context.text_ptr));
 
4796
            match = SRE_UNI_IS_WORD(context.text_ptr[0]);
 
4797
            break;
 
4798
        case SRE_OP_WHITESPACE:
 
4799
            // <WHITESPACE>
 
4800
            TRACE(("|%p|%p|WHITESPACE\n", body, context.text_ptr));
 
4801
            match = SRE_IS_WHITESPACE(context.text_ptr[0]);
 
4802
            break;
 
4803
        case SRE_OP_WORD:
 
4804
            // <WORD>
 
4805
            TRACE(("|%p|%p|WORD\n", body, context.text_ptr));
 
4806
            match = SRE_IS_WORD(context.text_ptr[0]);
 
4807
            break;
 
4808
        }
 
4809
        if (! match) {
 
4810
            SRE_DISCARD_BACKTRACK(&context);
 
4811
            goto backtrack;
 
4812
        }
 
4813
        // The character does match.
 
4814
        context.text_ptr++;
 
4815
        // Look at what follows to avoid unnecessary backtracking.
 
4816
        if (SRE_LOOK_AHEAD_ONE(&context, state, look_literal)) {
 
4817
            backtrack_item->text_ptr = context.text_ptr;
 
4818
            context.repeat_counter[index] = context.text_ptr - start_ptr;
 
4819
            context.pattern_ptr = tail;
 
4820
            goto advance;
 
4821
        }
 
4822
        context.text_ptr++;
 
4823
        if (context.text_ptr >= end_ptr) {
 
4824
            SRE_DISCARD_BACKTRACK(&context);
 
4825
            goto backtrack;
 
4826
        }
 
4827
        goto next_min_backtrack;
 
4828
    }
 
4829
    case SRE_OP_REPEAT_ONE_MIN_REV:
 
4830
    {
 
4831
        // Lazy repeat.
 
4832
        // <REPEAT_ONE_MIN_REV> <skip to end> <index> <min> <max> ...
 
4833
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
4834
        SRE_CODE* repeat_ptr = backtrack_item->pattern_ptr;
 
4835
        int index = repeat_ptr[1];
 
4836
        int repeat_max = repeat_ptr[3];
 
4837
        SRE_CODE* body = repeat_ptr + 4;
 
4838
        SRE_CODE* tail = repeat_ptr + repeat_ptr[0];
 
4839
        SRE_CODE* look_literal = tail;
 
4840
        SRE_CHAR* start_ptr;
 
4841
        SRE_CHAR* end_ptr;
 
4842
        int match;
 
4843
        Py_ssize_t limit = context.text_ptr - context.text_start;
 
4844
        context.text_ptr = backtrack_item->text_ptr;
 
4845
        if (repeat_max > context.repeat_counter[index] + limit || repeat_max == UNLIMITED_REPEATS)
 
4846
            repeat_max = context.repeat_counter[index] + limit;
 
4847
        // Now match up to the maximum.
 
4848
        start_ptr = context.text_ptr + context.repeat_counter[index];
 
4849
        end_ptr = start_ptr - repeat_max;
 
4850
        if (context.text_ptr <= end_ptr) {
 
4851
            SRE_DISCARD_BACKTRACK(&context);
 
4852
            goto backtrack;
 
4853
        }
 
4854
        while (look_literal[0] == SRE_OP_MARK)
 
4855
            look_literal += 2;
 
4856
next_min_backtrack_rev:
 
4857
        switch (body[0]) {
 
4858
        case SRE_OP_ANY_REV:
 
4859
            // <ANY_REV>
 
4860
            TRACE(("|%p|%p|ANY_REV\n", body, context.text_ptr));
 
4861
            match = !SRE_IS_LINEBREAK(context.text_ptr[-1]);
 
4862
            break;
 
4863
        case SRE_OP_ANY_ALL_REV:
 
4864
            // <ANY_ALL_REV>
 
4865
            TRACE(("|%p|%p|ANY_ALL_REV\n", body, context.text_ptr));
 
4866
            match = 1;
 
4867
            break;
 
4868
        case SRE_OP_BIGCHARSET_REV:
 
4869
            // <BIGCHARSET_REV> <charset>
 
4870
            TRACE(("|%p|%p|BIGCHARSET_REV\n", body, context.text_ptr));
 
4871
            match = in_bigcharset(body + 1, context.text_ptr[-1]);
 
4872
            break;
 
4873
        case SRE_OP_BIGCHARSET_IGNORE_REV:
 
4874
            // <BIGCHARSET_IGNORE_REV> <charset>
 
4875
            TRACE(("|%p|%p|BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
4876
            match = in_bigcharset(body + 1, state->lower(context.text_ptr[-1]));
 
4877
            break;
 
4878
        case SRE_OP_CHARSET_REV:
 
4879
            // <CHARSET_REV> <charset>
 
4880
            TRACE(("|%p|%p|CHARSET_REV\n", body, context.text_ptr));
 
4881
            match = in_charset(body + 1, context.text_ptr[-1]);
 
4882
            break;
 
4883
        case SRE_OP_CHARSET_IGNORE_REV:
 
4884
            // <CHARSET_IGNORE_REV> <charset>
 
4885
            TRACE(("|%p|%p|CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
4886
            match = in_charset(body + 1, state->lower(context.text_ptr[-1]));
 
4887
            break;
 
4888
        case SRE_OP_DIGIT_REV:
 
4889
            // <DIGIT_REV>
 
4890
            TRACE(("|%p|%p|DIGIT_REV\n", body, context.text_ptr));
 
4891
            match = SRE_IS_DIGIT(context.text_ptr[-1]);
 
4892
            break;
 
4893
        case SRE_OP_IN_REV:
 
4894
            // <IN_REV> <set>
 
4895
            TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
4896
            match = SRE_IN(body, context.text_ptr[-1]);
 
4897
            break;
 
4898
        case SRE_OP_IN_IGNORE_REV:
 
4899
            // <IN_IGNORE_REV> <set>
 
4900
            TRACE(("|%p|%p|IN_REV\n", body, context.text_ptr));
 
4901
            match = SRE_IN(body + 1, state->lower(context.text_ptr[-1]));
 
4902
            break;
 
4903
        case SRE_OP_LITERAL_REV:
 
4904
            // <LITERAL_REV> <code>
 
4905
            TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
4906
            match = context.text_ptr[-1] == (SRE_CHAR)body[1];
 
4907
            break;
 
4908
        case SRE_OP_LITERAL_IGNORE_REV:
 
4909
            // <LITERAL_IGNORE_REV> <code>
 
4910
            TRACE(("|%p|%p|LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
4911
            match = state->lower(context.text_ptr[-1]) == (SRE_CHAR)body[1];
 
4912
            break;
 
4913
        case SRE_OP_LOC_NOT_WORD_REV:
 
4914
            // <LOC_NOT_WORD_REV>
 
4915
            TRACE(("|%p|%p|LOC_NOT_WORD_REV\n", body, context.text_ptr));
 
4916
            match = !SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
4917
            break;
 
4918
        case SRE_OP_LOC_WORD_REV:
 
4919
            // <LOC_WORD_REV>
 
4920
            TRACE(("|%p|%p|LOC_WORD_REV\n", body, context.text_ptr));
 
4921
            match = SRE_LOC_IS_WORD(context.text_ptr[-1]);
 
4922
            break;
 
4923
        case SRE_OP_NOT_BIGCHARSET_REV:
 
4924
            // <NOT_BIGCHARSET_REV> <charset>
 
4925
            TRACE(("|%p|%p|NOT_BIGCHARSET_REV\n", body, context.text_ptr));
 
4926
            match = !in_bigcharset(body + 1, context.text_ptr[-1]);
 
4927
            break;
 
4928
        case SRE_OP_NOT_BIGCHARSET_IGNORE_REV:
 
4929
            // <NOT_BIGCHARSET_IGNORE_REV> <charset>
 
4930
            TRACE(("|%p|%p|NOT_BIGCHARSET_IGNORE_REV\n", body, context.text_ptr));
 
4931
            match = !in_bigcharset(body + 1, state->lower(context.text_ptr[-1]));
 
4932
            break;
 
4933
        case SRE_OP_NOT_CHARSET_REV:
 
4934
            // <NOT_CHARSET_REV> <charset>
 
4935
            TRACE(("|%p|%p|NOT_CHARSET_REV\n", body, context.text_ptr));
 
4936
            match = !in_charset(body + 1, context.text_ptr[-1]);
 
4937
            break;
 
4938
        case SRE_OP_NOT_CHARSET_IGNORE_REV:
 
4939
            // <NOT_CHARSET_IGNORE_REV> <charset>
 
4940
            TRACE(("|%p|%p|NOT_CHARSET_IGNORE_REV\n", body, context.text_ptr));
 
4941
            match = !in_charset(body + 1, state->lower(context.text_ptr[-1]));
 
4942
            break;
 
4943
        case SRE_OP_NOT_DIGIT_REV:
 
4944
            // <NOT_DIGIT_REV>
 
4945
            TRACE(("|%p|%p|NOT_DIGIT_REV\n", body, context.text_ptr));
 
4946
            match = !SRE_IS_DIGIT(context.text_ptr[-1]);
 
4947
            break;
 
4948
        case SRE_OP_NOT_IN_REV:
 
4949
            // <NOT_IN_REV> <set>
 
4950
            TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
4951
            match = !SRE_IN(body + 1, context.text_ptr[-1]);
 
4952
            break;
 
4953
        case SRE_OP_NOT_IN_IGNORE_REV:
 
4954
            // <NOT_IN_IGNORE_REV> <set>
 
4955
            TRACE(("|%p|%p|NOT_IN_REV\n", body, context.text_ptr));
 
4956
            match = !SRE_IN(body + 1, state->lower(context.text_ptr[-1]));
 
4957
            break;
 
4958
        case SRE_OP_NOT_LITERAL_REV:
 
4959
            // <NOT_LITERAL_REV> <code>
 
4960
            TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
4961
            match = context.text_ptr[-1] != (SRE_CHAR)body[1];
 
4962
            break;
 
4963
        case SRE_OP_NOT_LITERAL_IGNORE_REV:
 
4964
            // <NOT_LITERAL_IGNORE_REV> <code>
 
4965
            TRACE(("|%p|%p|NOT_LITERAL_REV %d\n", body, context.text_ptr, body[1]));
 
4966
            match = state->lower(context.text_ptr[-1]) != (SRE_CHAR)body[1];
 
4967
            break;
 
4968
        case SRE_OP_NOT_RANGE_REV:
 
4969
            // <NOT_RANGE_REV> <lower> <upper>
 
4970
            TRACE(("|%p|%p|NOT_RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4971
            match = !SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]);
 
4972
            break;
 
4973
        case SRE_OP_NOT_RANGE_IGNORE_REV:
 
4974
            // <NOT_RANGE_IGNORE_REV> <lower> <upper>
 
4975
            TRACE(("|%p|%p|NOT_RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4976
            match = !SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]);
 
4977
            break;
 
4978
        case SRE_OP_NOT_WHITESPACE_REV:
 
4979
            // <NOT_WHITESPACE_REV>
 
4980
            TRACE(("|%p|%p|NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
4981
            match = !SRE_IS_WHITESPACE(context.text_ptr[-1]);
 
4982
            break;
 
4983
        case SRE_OP_NOT_WORD_REV:
 
4984
            // <NOT_WORD_REV>
 
4985
            TRACE(("|%p|%p|NOT_WORD_REV\n", body, context.text_ptr));
 
4986
            match = !SRE_IS_WORD(context.text_ptr[-1]);
 
4987
            break;
 
4988
        case SRE_OP_RANGE_REV:
 
4989
            // <RANGE_REV> <lower> <upper>
 
4990
            TRACE(("|%p|%p|RANGE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4991
            match = SRE_IN_RANGE(context.text_ptr[-1], body[1], body[2]);
 
4992
            break;
 
4993
        case SRE_OP_RANGE_IGNORE_REV:
 
4994
            // <RANGE_IGNORE_REV> <lower> <upper>
 
4995
            TRACE(("|%p|%p|RANGE_IGNORE_REV %d %d\n", body, context.text_ptr, body[1], body[2]));
 
4996
            match = SRE_IN_RANGE(state->lower(context.text_ptr[-1]), body[1], body[2]);
 
4997
            break;
 
4998
        case SRE_OP_UNI_DIGIT_REV:
 
4999
            // <UNI_DIGIT_REV>
 
5000
            TRACE(("|%p|%p|UNI_DIGIT_REV\n", body, context.text_ptr));
 
5001
            match = SRE_UNI_IS_DIGIT(context.text_ptr[-1]);
 
5002
            break;
 
5003
        case SRE_OP_UNI_NOT_DIGIT_REV:
 
5004
            // <UNI_NOT_DIGIT_REV>
 
5005
            TRACE(("|%p|%p|UNI_NOT_DIGIT_REV\n", body, context.text_ptr));
 
5006
            match = !SRE_UNI_IS_DIGIT(context.text_ptr[-1]);
 
5007
            break;
 
5008
        case SRE_OP_UNI_NOT_WHITESPACE_REV:
 
5009
            // <UNI_NOT_WHITESPACE_REV>
 
5010
            TRACE(("|%p|%p|UNI_NOT_WHITESPACE_REV\n", body, context.text_ptr));
 
5011
            match = !SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]);
 
5012
            break;
 
5013
        case SRE_OP_UNI_NOT_WORD_REV:
 
5014
            // <UNI_NOT_WORD_REV>
 
5015
            TRACE(("|%p|%p|UNI_NOT_WORD_REV\n", body, context.text_ptr));
 
5016
            match = !SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
5017
            break;
 
5018
        case SRE_OP_UNI_WHITESPACE_REV:
 
5019
            // <UNI_WHITESPACE_REV>
 
5020
            TRACE(("|%p|%p|UNI_WHITESPACE_REV\n", body, context.text_ptr));
 
5021
            match = SRE_UNI_IS_WHITESPACE(context.text_ptr[-1]);
 
5022
            break;
 
5023
        case SRE_OP_UNI_WORD_REV:
 
5024
            // <UNI_WORD_REV>
 
5025
            TRACE(("|%p|%p|UNI_WORD_REV\n", body, context.text_ptr));
 
5026
            match = SRE_UNI_IS_WORD(context.text_ptr[-1]);
 
5027
            break;
 
5028
        case SRE_OP_WHITESPACE_REV:
 
5029
            // <WHITESPACE_REV>
 
5030
            TRACE(("|%p|%p|WHITESPACE_REV\n", body, context.text_ptr));
 
5031
            match = SRE_IS_WHITESPACE(context.text_ptr[-1]);
 
5032
            break;
 
5033
        case SRE_OP_WORD_REV:
 
5034
            // <WORD_REV>
 
5035
            TRACE(("|%p|%p|WORD_REV\n", body, context.text_ptr));
 
5036
            match = SRE_IS_WORD(context.text_ptr[-1]);
 
5037
            break;
 
5038
        }
 
5039
        if (! match) {
 
5040
            SRE_DISCARD_BACKTRACK(&context);
 
5041
            goto backtrack;
 
5042
        }
 
5043
        // The character does match.
 
5044
        context.text_ptr--;
 
5045
        // Look at what follows to avoid unnecessary backtracking.
 
5046
        if (SRE_LOOK_AHEAD_ONE_REV(&context, state, look_literal)) {
 
5047
            backtrack_item->text_ptr = context.text_ptr;
 
5048
            context.repeat_counter[index] = start_ptr - context.text_ptr;
 
5049
            context.pattern_ptr = tail;
 
5050
            goto advance;
 
5051
        }
 
5052
        context.text_ptr--;
 
5053
        if (context.text_ptr <= end_ptr) {
 
5054
            SRE_DISCARD_BACKTRACK(&context);
 
5055
            goto backtrack;
 
5056
        }
 
5057
        goto next_min_backtrack_rev;
 
5058
    }
 
5059
    case SRE_OP_REPEAT_POSS:
 
5060
    {
 
5061
        // Possessive repeat.
 
5062
        // <REPEAT_POSS> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS> <skip to start>
 
5063
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
5064
        TRACE(("REPEAT_POSS\n"));
 
5065
        SRE_RESTORE_MARKS(&context);
 
5066
        SRE_DISCARD_BACKTRACK(&context);
 
5067
        goto backtrack;
 
5068
    }
 
5069
    case SRE_OP_REPEAT_POSS_REV:
 
5070
    {
 
5071
        // Possessive repeat.
 
5072
        // <REPEAT_POSS_REV> <skip to end> <index> <min> <max> ... <END_REPEAT_POSS_REV> <skip to start>
 
5073
        SRE_BACKTRACK_ITEM* backtrack_item = &context.backtrack_chunk->items[context.backtrack_chunk->count - 1];
 
5074
        TRACE(("REPEAT_POSS\n"));
 
5075
        SRE_RESTORE_MARKS(&context);
 
5076
        SRE_DISCARD_BACKTRACK(&context);
 
5077
        goto backtrack;
 
5078
    }
 
5079
    default:
 
5080
        TRACE(("UNKNOWN %d\n", backtrack_chunk->items[backtrack_chunk->count - 1].op));
 
5081
        return SRE_CLEANUP(&context, state, SRE_ERROR_ILLEGAL);
 
5082
    }
 
5083
 
 
5084
    return 0;
 
5085
}
 
5086
 
 
5087
LOCAL(SRE_CODE*) SRE_LOOK_LITERAL(SRE_CODE* look_ahead) {
 
5088
    for (;;) {
 
5089
        switch (look_ahead[0]) {
 
5090
        case SRE_OP_BOUNDARY:
 
5091
        case SRE_OP_LOC_BOUNDARY:
 
5092
        case SRE_OP_UNI_BOUNDARY:
 
5093
            look_ahead++;
 
5094
            break;
 
5095
        case SRE_OP_LITERAL:
 
5096
        case SRE_OP_LITERAL_IGNORE:
 
5097
        case SRE_OP_LITERAL_STRING:
 
5098
        case SRE_OP_LITERAL_STRING_IGNORE:
 
5099
            return look_ahead;
 
5100
        default:
 
5101
            return NULL;
 
5102
        }
 
5103
    }
1679
5104
}
1680
5105
 
1681
5106
LOCAL(Py_ssize_t)
1682
5107
SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
1683
5108
{
1684
 
    SRE_CHAR* ptr = (SRE_CHAR *)state->start;
1685
 
    SRE_CHAR* end = (SRE_CHAR *)state->end;
 
5109
    SRE_CODE* look_ahead;
 
5110
    SRE_CODE* look_literal;
 
5111
    SRE_CONTEXT context;
1686
5112
    Py_ssize_t status = 0;
1687
 
    Py_ssize_t prefix_len = 0;
1688
 
    Py_ssize_t prefix_skip = 0;
1689
 
    SRE_CODE* prefix = NULL;
1690
 
    SRE_CODE* charset = NULL;
1691
 
    SRE_CODE* overlap = NULL;
1692
 
    int flags = 0;
1693
 
 
1694
 
    if (pattern[0] == SRE_OP_INFO) {
1695
 
        /* optimization info block */
1696
 
        /* <INFO> <1=skip> <2=flags> <3=min> <4=max> <5=prefix info>  */
1697
 
 
1698
 
        flags = pattern[2];
1699
 
 
1700
 
        if (pattern[3] > 1) {
1701
 
            /* adjust end point (but make sure we leave at least one
1702
 
               character in there, so literal search will work) */
1703
 
            end -= pattern[3]-1;
1704
 
            if (end <= ptr)
1705
 
                end = ptr+1;
1706
 
        }
1707
 
 
1708
 
        if (flags & SRE_INFO_PREFIX) {
1709
 
            /* pattern starts with a known prefix */
1710
 
            /* <length> <skip> <prefix data> <overlap data> */
1711
 
            prefix_len = pattern[5];
1712
 
            prefix_skip = pattern[6];
1713
 
            prefix = pattern + 7;
1714
 
            overlap = prefix + prefix_len - 1;
1715
 
        } else if (flags & SRE_INFO_CHARSET)
1716
 
            /* pattern starts with a character from a known set */
1717
 
            /* <charset> */
1718
 
            charset = pattern + 5;
1719
 
 
1720
 
        pattern += 1 + pattern[1];
1721
 
    }
1722
 
 
1723
 
    TRACE(("prefix = %p %d %d\n", prefix, prefix_len, prefix_skip));
1724
 
    TRACE(("charset = %p\n", charset));
1725
 
 
1726
 
#if defined(USE_FAST_SEARCH)
1727
 
    if (prefix_len > 1) {
1728
 
        /* pattern starts with a known prefix.  use the overlap
1729
 
           table to skip forward as fast as we possibly can */
1730
 
        Py_ssize_t i = 0;
1731
 
        end = (SRE_CHAR *)state->end;
1732
 
        while (ptr < end) {
1733
 
            for (;;) {
1734
 
                if ((SRE_CODE) ptr[0] != prefix[i]) {
1735
 
                    if (!i)
1736
 
                        break;
1737
 
                    else
1738
 
                        i = overlap[i];
1739
 
                } else {
1740
 
                    if (++i == prefix_len) {
1741
 
                        /* found a potential match */
1742
 
                        TRACE(("|%p|%p|SEARCH SCAN\n", pattern, ptr));
1743
 
                        state->start = ptr + 1 - prefix_len;
1744
 
                        state->ptr = ptr + 1 - prefix_len + prefix_skip;
1745
 
                        if (flags & SRE_INFO_LITERAL)
1746
 
                            return 1; /* we got all of it */
1747
 
                        status = SRE_MATCH(state, pattern + 2*prefix_skip);
1748
 
                        if (status != 0)
1749
 
                            return status;
1750
 
                        /* close but no cigar -- try again */
1751
 
                        i = overlap[i];
1752
 
                    }
1753
 
                    break;
1754
 
                }
1755
 
            }
1756
 
            ptr++;
1757
 
        }
1758
 
        return 0;
1759
 
    }
1760
 
#endif
1761
 
 
1762
 
    if (pattern[0] == SRE_OP_LITERAL) {
1763
 
        /* pattern starts with a literal character.  this is used
1764
 
           for short prefixes, and if fast search is disabled */
1765
 
        SRE_CODE chr = pattern[1];
1766
 
        end = (SRE_CHAR *)state->end;
1767
 
        for (;;) {
1768
 
            while (ptr < end && (SRE_CODE) ptr[0] != chr)
1769
 
                ptr++;
1770
 
            if (ptr >= end)
1771
 
                return 0;
1772
 
            TRACE(("|%p|%p|SEARCH LITERAL\n", pattern, ptr));
1773
 
            state->start = ptr;
1774
 
            state->ptr = ++ptr;
1775
 
            if (flags & SRE_INFO_LITERAL)
1776
 
                return 1; /* we got all of it */
1777
 
            status = SRE_MATCH(state, pattern + 2);
1778
 
            if (status != 0)
1779
 
                break;
1780
 
        }
1781
 
    } else if (charset) {
1782
 
        /* pattern starts with a character from a known set */
1783
 
        end = (SRE_CHAR *)state->end;
1784
 
        for (;;) {
1785
 
            while (ptr < end && !SRE_CHARSET(charset, ptr[0]))
1786
 
                ptr++;
1787
 
            if (ptr >= end)
1788
 
                return 0;
1789
 
            TRACE(("|%p|%p|SEARCH CHARSET\n", pattern, ptr));
1790
 
            state->start = ptr;
1791
 
            state->ptr = ptr;
1792
 
            status = SRE_MATCH(state, pattern);
1793
 
            if (status != 0)
1794
 
                break;
1795
 
            ptr++;
1796
 
        }
1797
 
    } else
1798
 
        /* general case */
1799
 
        while (ptr <= end) {
1800
 
            TRACE(("|%p|%p|SEARCH\n", pattern, ptr));
1801
 
            state->start = state->ptr = ptr++;
1802
 
            status = SRE_MATCH(state, pattern);
1803
 
            if (status != 0)
1804
 
                break;
1805
 
        }
 
5113
 
 
5114
    look_ahead = pattern;
 
5115
    while (look_ahead[0] == SRE_OP_MARK)
 
5116
        look_ahead += 2;
 
5117
 
 
5118
    look_literal = SRE_LOOK_LITERAL(look_ahead);
 
5119
    if (look_literal != NULL)
 
5120
        look_ahead = look_literal;
 
5121
 
 
5122
    context.text_start = (SRE_CHAR *)state->beginning;
 
5123
    context.text_end = (SRE_CHAR *)state->end;
 
5124
    context.text_ptr = (SRE_CHAR *)state->start;
 
5125
 
 
5126
    while (context.text_ptr <= context.text_end) {
 
5127
        TRACE(("|%p|%p|SEARCH\n", pattern, context.text_ptr));
 
5128
        if (SRE_LOOK_AHEAD_ONE(&context, state, look_ahead)) {
 
5129
            state->start = state->ptr = context.text_ptr;
 
5130
            status = SRE_MATCH(state, state->pattern_code);
 
5131
            if (status != 0)
 
5132
                break;
 
5133
        }
 
5134
        context.text_ptr++;
 
5135
    }
1806
5136
 
1807
5137
    return status;
1808
5138
}
1857
5187
 
1858
5188
    state->lastmark = -1;
1859
5189
    state->lastindex = -1;
1860
 
 
1861
 
    state->repeat = NULL;
1862
 
 
1863
 
    data_stack_dealloc(state);
1864
5190
}
1865
5191
 
1866
5192
static void*
1887
5213
#endif
1888
5214
 
1889
5215
    /* get pointer to string buffer */
1890
 
    buffer = Py_TYPE(string)->tp_as_buffer;
 
5216
    buffer = string->ob_type->tp_as_buffer;
1891
5217
    if (!buffer || !buffer->bf_getreadbuffer || !buffer->bf_getsegcount ||
1892
5218
        buffer->bf_getsegcount(string, NULL) != 1) {
1893
5219
        PyErr_SetString(PyExc_TypeError, "expected string or buffer");
1931
5257
 
1932
5258
LOCAL(PyObject*)
1933
5259
state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
1934
 
           Py_ssize_t start, Py_ssize_t end)
 
5260
           Py_ssize_t start, Py_ssize_t end, SRE_CODE* pattern_code)
1935
5261
{
1936
5262
    /* prepare state object */
1937
5263
 
1941
5267
 
1942
5268
    memset(state, 0, sizeof(SRE_STATE));
1943
5269
 
 
5270
    state->pattern_code = pattern_code;
 
5271
 
 
5272
    /* There are actually 2 versions of backtrack_chunk and saved_marks_chunk,
 
5273
        8-bit and Unicode. This shouldn't be a problem because they have the same format
 
5274
        and contain pointers and an int, which are always the same size. */
 
5275
    state->backtrack_chunk = (SRE_BACKTRACK_CHUNK*)PyMem_MALLOC(sizeof(SRE_BACKTRACK_CHUNK));
 
5276
    if (state->backtrack_chunk == NULL)
 
5277
        goto error;
 
5278
 
 
5279
    state->backtrack_chunk->previous = NULL;
 
5280
    state->backtrack_chunk->count = 0;
 
5281
 
 
5282
    state->saved_marks_chunk = (SRE_SAVED_MARKS_CHUNK*)PyMem_MALLOC(sizeof(SRE_SAVED_MARKS_CHUNK));
 
5283
    if (state->saved_marks_chunk == NULL)
 
5284
        goto error;
 
5285
 
 
5286
    state->saved_marks_chunk->previous = NULL;
 
5287
    state->saved_marks_chunk->count = 0;
 
5288
 
 
5289
    state->mark_count = pattern->marks;
 
5290
    state->repeat_count = pattern->repeats;
 
5291
 
 
5292
    // Ensure that element 0 of the repeat_counter array always exists.
 
5293
    state->repeat_counter = (int*)PyMem_MALLOC((state->repeat_count + 1) * sizeof(int));
 
5294
    if (state->repeat_counter == NULL)
 
5295
        goto error;
 
5296
 
 
5297
    // Ensure that element 0 of the repeat_start array always exists.
 
5298
    state->repeat_start = (void**)PyMem_MALLOC((state->repeat_count + 1) * sizeof(void*));
 
5299
    if (state->repeat_start == NULL)
 
5300
        goto error;
 
5301
 
1944
5302
    state->lastmark = -1;
1945
5303
    state->lastindex = -1;
1946
5304
 
1947
5305
    ptr = getstring(string, &length, &charsize);
1948
5306
    if (!ptr)
1949
 
        return NULL;
 
5307
        goto error;
1950
5308
 
1951
5309
    /* adjust boundaries */
1952
5310
    if (start < 0)
1983
5341
        state->lower = sre_lower;
1984
5342
 
1985
5343
    return string;
 
5344
 
 
5345
error:
 
5346
    PyMem_FREE(state->repeat_start);
 
5347
    PyMem_FREE(state->repeat_counter);
 
5348
    PyMem_FREE(state->saved_marks_chunk);
 
5349
    PyMem_FREE(state->backtrack_chunk);
 
5350
    return NULL;
1986
5351
}
1987
5352
 
1988
5353
LOCAL(void)
1989
5354
state_fini(SRE_STATE* state)
1990
5355
{
 
5356
    /* There are actually 2 versions of backtrack_chunk and saved_marks_chunk,
 
5357
        8-bit and Unicode. This shouldn't be a problem because they have the same format
 
5358
        and contain pointers and an int, which are always the same size. */
 
5359
    SRE_SAVED_MARKS_CHUNK* saved_marks_chunk = state->saved_marks_chunk;
 
5360
    SRE_BACKTRACK_CHUNK* backtrack_chunk = state->backtrack_chunk;
 
5361
 
 
5362
    while (saved_marks_chunk != NULL) {
 
5363
        SRE_SAVED_MARKS_CHUNK* previous = saved_marks_chunk->previous;
 
5364
        PyMem_FREE(saved_marks_chunk);
 
5365
        saved_marks_chunk = previous;
 
5366
    }
 
5367
    state->saved_marks_chunk = NULL;
 
5368
 
 
5369
    while (backtrack_chunk != NULL) {
 
5370
        SRE_BACKTRACK_CHUNK* previous = backtrack_chunk->previous;
 
5371
        PyMem_FREE(backtrack_chunk);
 
5372
        backtrack_chunk = previous;
 
5373
    }
 
5374
    state->backtrack_chunk = NULL;
 
5375
 
 
5376
    PyMem_FREE(state->repeat_start);
 
5377
    PyMem_FREE(state->repeat_counter);
1991
5378
    Py_XDECREF(state->string);
1992
 
    data_stack_dealloc(state);
1993
5379
}
1994
5380
 
1995
5381
/* calculate offset from start of string */
2060
5446
{
2061
5447
    SRE_STATE state;
2062
5448
    int status;
2063
 
 
 
5449
    SRE_CODE* pattern_code;
2064
5450
    PyObject* string;
2065
5451
    Py_ssize_t start = 0;
2066
5452
    Py_ssize_t end = PY_SSIZE_T_MAX;
2069
5455
                                     &string, &start, &end))
2070
5456
        return NULL;
2071
5457
 
2072
 
    string = state_init(&state, self, string, start, end);
 
5458
    pattern_code = PatternObject_GetCode(self);
 
5459
 
 
5460
    string = state_init(&state, self, string, start, end, pattern_code);
2073
5461
    if (!string)
2074
5462
        return NULL;
2075
5463
 
2076
5464
    state.ptr = state.start;
2077
5465
 
2078
 
    TRACE(("|%p|%p|MATCH\n", PatternObject_GetCode(self), state.ptr));
 
5466
    TRACE(("|%p|%p|MATCH\n", pattern_code, state.ptr));
2079
5467
 
2080
5468
    if (state.charsize == 1) {
2081
 
        status = sre_match(&state, PatternObject_GetCode(self));
 
5469
        status = sre_match(&state, state.pattern_code);
2082
5470
    } else {
2083
5471
#if defined(HAVE_UNICODE)
2084
 
        status = sre_umatch(&state, PatternObject_GetCode(self));
 
5472
        status = sre_umatch(&state, state.pattern_code);
2085
5473
#endif
2086
5474
    }
2087
5475
 
2088
 
    TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr));
 
5476
    TRACE(("|%p|%p|END\n", pattern_code, state.ptr));
2089
5477
    if (PyErr_Occurred())
2090
5478
        return NULL;
2091
5479
 
2099
5487
{
2100
5488
    SRE_STATE state;
2101
5489
    int status;
2102
 
 
 
5490
    SRE_CODE* pattern_code;
2103
5491
    PyObject* string;
2104
5492
    Py_ssize_t start = 0;
2105
5493
    Py_ssize_t end = PY_SSIZE_T_MAX;
2108
5496
                                     &string, &start, &end))
2109
5497
        return NULL;
2110
5498
 
2111
 
    string = state_init(&state, self, string, start, end);
 
5499
    pattern_code = PatternObject_GetCode(self);
 
5500
 
 
5501
    string = state_init(&state, self, string, start, end, pattern_code);
2112
5502
    if (!string)
2113
5503
        return NULL;
2114
5504
 
2115
 
    TRACE(("|%p|%p|SEARCH\n", PatternObject_GetCode(self), state.ptr));
 
5505
    TRACE(("|%p|%p|SEARCH\n", pattern_code, state.ptr));
2116
5506
 
2117
5507
    if (state.charsize == 1) {
2118
 
        status = sre_search(&state, PatternObject_GetCode(self));
 
5508
        status = sre_search(&state, state.pattern_code);
2119
5509
    } else {
2120
5510
#if defined(HAVE_UNICODE)
2121
 
        status = sre_usearch(&state, PatternObject_GetCode(self));
 
5511
        status = sre_usearch(&state, state.pattern_code);
2122
5512
#endif
2123
5513
    }
2124
5514
 
2234
5624
    PyObject* list;
2235
5625
    int status;
2236
5626
    Py_ssize_t i, b, e;
2237
 
 
 
5627
    SRE_CODE* pattern_code;
2238
5628
    PyObject* string;
2239
5629
    Py_ssize_t start = 0;
2240
5630
    Py_ssize_t end = PY_SSIZE_T_MAX;
2243
5633
                                     &string, &start, &end))
2244
5634
        return NULL;
2245
5635
 
2246
 
    string = state_init(&state, self, string, start, end);
 
5636
    pattern_code = PatternObject_GetCode(self);
 
5637
 
 
5638
    string = state_init(&state, self, string, start, end, pattern_code);
2247
5639
    if (!string)
2248
5640
        return NULL;
2249
5641
 
2262
5654
        state.ptr = state.start;
2263
5655
 
2264
5656
        if (state.charsize == 1) {
2265
 
            status = sre_search(&state, PatternObject_GetCode(self));
 
5657
            status = sre_search(&state, state.pattern_code);
2266
5658
        } else {
2267
5659
#if defined(HAVE_UNICODE)
2268
 
            status = sre_usearch(&state, PatternObject_GetCode(self));
 
5660
            status = sre_usearch(&state, state.pattern_code);
2269
5661
#endif
2270
5662
        }
2271
5663
 
2361
5753
    PyObject* list;
2362
5754
    PyObject* item;
2363
5755
    int status;
 
5756
    SRE_CODE* pattern_code;
2364
5757
    Py_ssize_t n;
2365
5758
    Py_ssize_t i;
2366
5759
    void* last;
2372
5765
                                     &string, &maxsplit))
2373
5766
        return NULL;
2374
5767
 
2375
 
    string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX);
 
5768
    pattern_code = PatternObject_GetCode(self);
 
5769
 
 
5770
    string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX, pattern_code);
2376
5771
    if (!string)
2377
5772
        return NULL;
2378
5773
 
2392
5787
        state.ptr = state.start;
2393
5788
 
2394
5789
        if (state.charsize == 1) {
2395
 
            status = sre_search(&state, PatternObject_GetCode(self));
 
5790
            status = sre_search(&state, state.pattern_code);
2396
5791
        } else {
2397
5792
#if defined(HAVE_UNICODE)
2398
 
            status = sre_usearch(&state, PatternObject_GetCode(self));
 
5793
            status = sre_usearch(&state, state.pattern_code);
2399
5794
#endif
2400
5795
        }
2401
5796
 
2483
5878
    Py_ssize_t i, b, e;
2484
5879
    int bint;
2485
5880
    int filter_is_callable;
 
5881
    SRE_CODE* pattern_code;
2486
5882
 
2487
5883
    if (PyCallable_Check(ptemplate)) {
2488
5884
        /* sub/subn takes either a function or a template */
2522
5918
        }
2523
5919
    }
2524
5920
 
2525
 
    string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX);
 
5921
    pattern_code = PatternObject_GetCode(self);
 
5922
 
 
5923
    string = state_init(&state, self, string, 0, PY_SSIZE_T_MAX, pattern_code);
2526
5924
    if (!string) {
2527
5925
        Py_DECREF(filter);
2528
5926
        return NULL;
2544
5942
        state.ptr = state.start;
2545
5943
 
2546
5944
        if (state.charsize == 1) {
2547
 
            status = sre_search(&state, PatternObject_GetCode(self));
 
5945
            status = sre_search(&state, state.pattern_code);
2548
5946
        } else {
2549
5947
#if defined(HAVE_UNICODE)
2550
 
            status = sre_usearch(&state, PatternObject_GetCode(self));
 
5948
            status = sre_usearch(&state, state.pattern_code);
2551
5949
#endif
2552
5950
        }
2553
5951
 
2974
6372
        arg = *code++;                                  \
2975
6373
        VTRACE(("%lu (arg)\n", (unsigned long)arg));    \
2976
6374
    } while (0)
2977
 
#define GET_SKIP_ADJ(adj)                               \
 
6375
#define GET_SKIP                                        \
2978
6376
    do {                                                \
2979
6377
        VTRACE(("%p= ", code));                         \
2980
6378
        if (code >= end) FAIL;                          \
2981
6379
        skip = *code;                                   \
2982
6380
        VTRACE(("%lu (skip to %p)\n",                   \
2983
6381
               (unsigned long)skip, code+skip));        \
2984
 
        if (code+skip-adj < code || code+skip-adj > end)\
 
6382
        if (code+skip < code || code+skip > end)        \
2985
6383
            FAIL;                                       \
2986
6384
        code++;                                         \
2987
6385
    } while (0)
2988
 
#define GET_SKIP GET_SKIP_ADJ(0)
2989
 
 
2990
 
static int
2991
 
_validate_charset(SRE_CODE *code, SRE_CODE *end)
2992
 
{
2993
 
    /* Some variables are manipulated by the macros above */
2994
 
    SRE_CODE op;
2995
 
    SRE_CODE arg;
2996
 
    SRE_CODE offset;
2997
 
    int i;
2998
 
 
2999
 
    while (code < end) {
3000
 
        GET_OP;
3001
 
        switch (op) {
3002
 
 
3003
 
        case SRE_OP_NEGATE:
3004
 
            break;
3005
 
 
3006
 
        case SRE_OP_LITERAL:
3007
 
            GET_ARG;
3008
 
            break;
3009
 
 
3010
 
        case SRE_OP_RANGE:
3011
 
            GET_ARG;
3012
 
            GET_ARG;
3013
 
            break;
3014
 
 
3015
 
        case SRE_OP_CHARSET:
3016
 
            offset = 32/sizeof(SRE_CODE); /* 32-byte bitmap */
3017
 
            if (code+offset < code || code+offset > end)
3018
 
                FAIL;
3019
 
            code += offset;
3020
 
            break;
3021
 
 
3022
 
        case SRE_OP_BIGCHARSET:
3023
 
            GET_ARG; /* Number of blocks */
3024
 
            offset = 256/sizeof(SRE_CODE); /* 256-byte table */
3025
 
            if (code+offset < code || code+offset > end)
3026
 
                FAIL;
3027
 
            /* Make sure that each byte points to a valid block */
3028
 
            for (i = 0; i < 256; i++) {
3029
 
                if (((unsigned char *)code)[i] >= arg)
3030
 
                    FAIL;
3031
 
            }
3032
 
            code += offset;
3033
 
            offset = arg * 32/sizeof(SRE_CODE); /* 32-byte bitmap times arg */
3034
 
            if (code+offset < code || code+offset > end)
3035
 
                FAIL;
3036
 
            code += offset;
3037
 
            break;
3038
 
 
3039
 
        case SRE_OP_CATEGORY:
3040
 
            GET_ARG;
3041
 
            switch (arg) {
3042
 
            case SRE_CATEGORY_DIGIT:
3043
 
            case SRE_CATEGORY_NOT_DIGIT:
3044
 
            case SRE_CATEGORY_SPACE:
3045
 
            case SRE_CATEGORY_NOT_SPACE:
3046
 
            case SRE_CATEGORY_WORD:
3047
 
            case SRE_CATEGORY_NOT_WORD:
3048
 
            case SRE_CATEGORY_LINEBREAK:
3049
 
            case SRE_CATEGORY_NOT_LINEBREAK:
3050
 
            case SRE_CATEGORY_LOC_WORD:
3051
 
            case SRE_CATEGORY_LOC_NOT_WORD:
3052
 
            case SRE_CATEGORY_UNI_DIGIT:
3053
 
            case SRE_CATEGORY_UNI_NOT_DIGIT:
3054
 
            case SRE_CATEGORY_UNI_SPACE:
3055
 
            case SRE_CATEGORY_UNI_NOT_SPACE:
3056
 
            case SRE_CATEGORY_UNI_WORD:
3057
 
            case SRE_CATEGORY_UNI_NOT_WORD:
3058
 
            case SRE_CATEGORY_UNI_LINEBREAK:
3059
 
            case SRE_CATEGORY_UNI_NOT_LINEBREAK:
3060
 
                break;
3061
 
            default:
3062
 
                FAIL;
3063
 
            }
3064
 
            break;
3065
 
 
3066
 
        default:
3067
 
            FAIL;
3068
 
 
3069
 
        }
3070
 
    }
3071
 
 
3072
 
    return 1;
3073
 
}
3074
 
 
3075
 
static int
3076
 
_validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
3077
 
{
3078
 
    /* Some variables are manipulated by the macros above */
3079
 
    SRE_CODE op;
3080
 
    SRE_CODE arg;
3081
 
    SRE_CODE skip;
3082
 
 
3083
 
    VTRACE(("code=%p, end=%p\n", code, end));
3084
 
 
3085
 
    if (code > end)
3086
 
        FAIL;
3087
 
 
3088
 
    while (code < end) {
3089
 
        GET_OP;
3090
 
        switch (op) {
3091
 
 
3092
 
        case SRE_OP_MARK:
3093
 
            /* We don't check whether marks are properly nested; the
3094
 
               sre_match() code is robust even if they don't, and the worst
3095
 
               you can get is nonsensical match results. */
3096
 
            GET_ARG;
3097
 
            if (arg > 2*groups+1) {
3098
 
                VTRACE(("arg=%d, groups=%d\n", (int)arg, (int)groups));
3099
 
                FAIL;
3100
 
            }
3101
 
            break;
3102
 
 
3103
 
        case SRE_OP_LITERAL:
3104
 
        case SRE_OP_NOT_LITERAL:
3105
 
        case SRE_OP_LITERAL_IGNORE:
3106
 
        case SRE_OP_NOT_LITERAL_IGNORE:
3107
 
            GET_ARG;
3108
 
            /* The arg is just a character, nothing to check */
3109
 
            break;
3110
 
 
3111
 
        case SRE_OP_SUCCESS:
3112
 
        case SRE_OP_FAILURE:
3113
 
            /* Nothing to check; these normally end the matching process */
3114
 
            break;
3115
 
 
3116
 
        case SRE_OP_AT:
3117
 
            GET_ARG;
3118
 
            switch (arg) {
3119
 
            case SRE_AT_BEGINNING:
3120
 
            case SRE_AT_BEGINNING_STRING:
3121
 
            case SRE_AT_BEGINNING_LINE:
3122
 
            case SRE_AT_END:
3123
 
            case SRE_AT_END_LINE:
3124
 
            case SRE_AT_END_STRING:
3125
 
            case SRE_AT_BOUNDARY:
3126
 
            case SRE_AT_NON_BOUNDARY:
3127
 
            case SRE_AT_LOC_BOUNDARY:
3128
 
            case SRE_AT_LOC_NON_BOUNDARY:
3129
 
            case SRE_AT_UNI_BOUNDARY:
3130
 
            case SRE_AT_UNI_NON_BOUNDARY:
3131
 
                break;
3132
 
            default:
3133
 
                FAIL;
3134
 
            }
3135
 
            break;
3136
 
 
3137
 
        case SRE_OP_ANY:
3138
 
        case SRE_OP_ANY_ALL:
3139
 
            /* These have no operands */
3140
 
            break;
3141
 
 
3142
 
        case SRE_OP_IN:
3143
 
        case SRE_OP_IN_IGNORE:
3144
 
            GET_SKIP;
3145
 
            /* Stop 1 before the end; we check the FAILURE below */
3146
 
            if (!_validate_charset(code, code+skip-2))
3147
 
                FAIL;
3148
 
            if (code[skip-2] != SRE_OP_FAILURE)
3149
 
                FAIL;
3150
 
            code += skip-1;
3151
 
            break;
3152
 
 
3153
 
        case SRE_OP_INFO:
3154
 
            {
3155
 
                /* A minimal info field is
3156
 
                   <INFO> <1=skip> <2=flags> <3=min> <4=max>;
3157
 
                   If SRE_INFO_PREFIX or SRE_INFO_CHARSET is in the flags,
3158
 
                   more follows. */
3159
 
                SRE_CODE flags, min, max, i;
3160
 
                SRE_CODE *newcode;
3161
 
                GET_SKIP;
3162
 
                newcode = code+skip-1;
3163
 
                GET_ARG; flags = arg;
3164
 
                GET_ARG; min = arg;
3165
 
                GET_ARG; max = arg;
3166
 
                /* Check that only valid flags are present */
3167
 
                if ((flags & ~(SRE_INFO_PREFIX |
3168
 
                               SRE_INFO_LITERAL |
3169
 
                               SRE_INFO_CHARSET)) != 0)
3170
 
                    FAIL;
3171
 
                /* PREFIX and CHARSET are mutually exclusive */
3172
 
                if ((flags & SRE_INFO_PREFIX) &&
3173
 
                    (flags & SRE_INFO_CHARSET))
3174
 
                    FAIL;
3175
 
                /* LITERAL implies PREFIX */
3176
 
                if ((flags & SRE_INFO_LITERAL) &&
3177
 
                    !(flags & SRE_INFO_PREFIX))
3178
 
                    FAIL;
3179
 
                /* Validate the prefix */
3180
 
                if (flags & SRE_INFO_PREFIX) {
3181
 
                    SRE_CODE prefix_len, prefix_skip;
3182
 
                    GET_ARG; prefix_len = arg;
3183
 
                    GET_ARG; prefix_skip = arg;
3184
 
                    /* Here comes the prefix string */
3185
 
                    if (code+prefix_len < code || code+prefix_len > newcode)
3186
 
                        FAIL;
3187
 
                    code += prefix_len;
3188
 
                    /* And here comes the overlap table */
3189
 
                    if (code+prefix_len < code || code+prefix_len > newcode)
3190
 
                        FAIL;
3191
 
                    /* Each overlap value should be < prefix_len */
3192
 
                    for (i = 0; i < prefix_len; i++) {
3193
 
                        if (code[i] >= prefix_len)
3194
 
                            FAIL;
3195
 
                    }
3196
 
                    code += prefix_len;
3197
 
                }
3198
 
                /* Validate the charset */
3199
 
                if (flags & SRE_INFO_CHARSET) {
3200
 
                    if (!_validate_charset(code, newcode-1))
3201
 
                        FAIL;
3202
 
                    if (newcode[-1] != SRE_OP_FAILURE)
3203
 
                        FAIL;
3204
 
                    code = newcode;
3205
 
                }
3206
 
                else if (code != newcode) {
3207
 
                  VTRACE(("code=%p, newcode=%p\n", code, newcode));
3208
 
                    FAIL;
3209
 
                }
3210
 
            }
3211
 
            break;
3212
 
 
3213
 
        case SRE_OP_BRANCH:
3214
 
            {
3215
 
                SRE_CODE *target = NULL;
3216
 
                for (;;) {
3217
 
                    GET_SKIP;
3218
 
                    if (skip == 0)
3219
 
                        break;
3220
 
                    /* Stop 2 before the end; we check the JUMP below */
3221
 
                    if (!_validate_inner(code, code+skip-3, groups))
3222
 
                        FAIL;
3223
 
                    code += skip-3;
3224
 
                    /* Check that it ends with a JUMP, and that each JUMP
3225
 
                       has the same target */
3226
 
                    GET_OP;
3227
 
                    if (op != SRE_OP_JUMP)
3228
 
                        FAIL;
3229
 
                    GET_SKIP;
3230
 
                    if (target == NULL)
3231
 
                        target = code+skip-1;
3232
 
                    else if (code+skip-1 != target)
3233
 
                        FAIL;
3234
 
                }
3235
 
            }
3236
 
            break;
3237
 
 
3238
 
        case SRE_OP_REPEAT_ONE:
3239
 
        case SRE_OP_MIN_REPEAT_ONE:
3240
 
        case SRE_OP_POSSESSIVE_ONE:
3241
 
        case SRE_OP_POSSESSIVE_REPEAT:
3242
 
            {
3243
 
                SRE_CODE min, max;
3244
 
                GET_SKIP;
3245
 
                GET_ARG; min = arg;
3246
 
                GET_ARG; max = arg;
3247
 
                if (min > max)
3248
 
                    FAIL;
3249
 
#ifdef Py_UNICODE_WIDE
3250
 
                if (max > 65535)
3251
 
                    FAIL;
3252
 
#endif
3253
 
                if (!_validate_inner(code, code+skip-4, groups))
3254
 
                    FAIL;
3255
 
                code += skip-4;
3256
 
                GET_OP;
3257
 
                if (op != SRE_OP_SUCCESS)
3258
 
                    FAIL;
3259
 
            }
3260
 
            break;
3261
 
 
3262
 
        case SRE_OP_REPEAT:
3263
 
            {
3264
 
                SRE_CODE min, max;
3265
 
                GET_SKIP;
3266
 
                GET_ARG; min = arg;
3267
 
                GET_ARG; max = arg;
3268
 
                if (min > max)
3269
 
                    FAIL;
3270
 
#ifdef Py_UNICODE_WIDE
3271
 
                if (max > 65535)
3272
 
                    FAIL;
3273
 
#endif
3274
 
                if (!_validate_inner(code, code+skip-3, groups))
3275
 
                    FAIL;
3276
 
                code += skip-3;
3277
 
                GET_OP;
3278
 
                if (op != SRE_OP_MAX_UNTIL && op != SRE_OP_MIN_UNTIL)
3279
 
                    FAIL;
3280
 
            }
3281
 
            break;
3282
 
 
3283
 
        case SRE_OP_ATOMIC_GROUP:
3284
 
            {
3285
 
                GET_SKIP;
3286
 
                if (!_validate_inner(code, code+skip-2, groups))
3287
 
                    FAIL;
3288
 
                code += skip-2;
3289
 
                GET_OP;
3290
 
                if (op != SRE_OP_SUCCESS)
3291
 
                    FAIL;
3292
 
            }
3293
 
            break;
3294
 
 
3295
 
        case SRE_OP_GROUPREF:
3296
 
        case SRE_OP_GROUPREF_IGNORE:
3297
 
            GET_ARG;
3298
 
            if (arg >= groups)
3299
 
                FAIL;
3300
 
            break;
3301
 
 
3302
 
        case SRE_OP_GROUPREF_EXISTS:
3303
 
            /* The regex syntax for this is: '(?(group)then|else)', where
3304
 
               'group' is either an integer group number or a group name,
3305
 
               'then' and 'else' are sub-regexes, and 'else' is optional. */
3306
 
            GET_ARG;
3307
 
            if (arg >= groups)
3308
 
                FAIL;
3309
 
            GET_SKIP_ADJ(1);
3310
 
            code--; /* The skip is relative to the first arg! */
3311
 
            /* There are two possibilities here: if there is both a 'then'
3312
 
               part and an 'else' part, the generated code looks like:
3313
 
 
3314
 
               GROUPREF_EXISTS
3315
 
               <group>
3316
 
               <skipyes>
3317
 
               ...then part...
3318
 
               JUMP
3319
 
               <skipno>
3320
 
               (<skipyes> jumps here)
3321
 
               ...else part...
3322
 
               (<skipno> jumps here)
3323
 
 
3324
 
               If there is only a 'then' part, it looks like:
3325
 
 
3326
 
               GROUPREF_EXISTS
3327
 
               <group>
3328
 
               <skip>
3329
 
               ...then part...
3330
 
               (<skip> jumps here)
3331
 
 
3332
 
               There is no direct way to decide which it is, and we don't want
3333
 
               to allow arbitrary jumps anywhere in the code; so we just look
3334
 
               for a JUMP opcode preceding our skip target.
3335
 
            */
3336
 
            if (skip >= 3 && code+skip-3 >= code &&
3337
 
                code[skip-3] == SRE_OP_JUMP)
3338
 
            {
3339
 
                VTRACE(("both then and else parts present\n"));
3340
 
                if (!_validate_inner(code+1, code+skip-3, groups))
3341
 
                    FAIL;
3342
 
                code += skip-2; /* Position after JUMP, at <skipno> */
3343
 
                GET_SKIP;
3344
 
                if (!_validate_inner(code, code+skip-1, groups))
3345
 
                    FAIL;
3346
 
                code += skip-1;
3347
 
            }
3348
 
            else {
3349
 
                VTRACE(("only a then part present\n"));
3350
 
                if (!_validate_inner(code+1, code+skip-1, groups))
3351
 
                    FAIL;
3352
 
                code += skip-1;
3353
 
            }
3354
 
            break;
3355
 
 
3356
 
        case SRE_OP_ASSERT:
3357
 
        case SRE_OP_ASSERT_NOT:
3358
 
            GET_SKIP;
3359
 
            GET_ARG; /* 0 for lookahead, width for lookbehind */
3360
 
            code--; /* Back up over arg to simplify math below */
3361
 
            if (arg & 0x80000000)
3362
 
                FAIL; /* Width too large */
3363
 
            /* Stop 1 before the end; we check the SUCCESS below */
3364
 
            if (!_validate_inner(code+1, code+skip-2, groups))
3365
 
                FAIL;
3366
 
            code += skip-2;
3367
 
            GET_OP;
3368
 
            if (op != SRE_OP_SUCCESS)
3369
 
                FAIL;
3370
 
            break;
3371
 
 
3372
 
        default:
3373
 
            FAIL;
3374
 
 
3375
 
        }
3376
 
    }
3377
 
 
3378
 
    VTRACE(("okay\n"));
3379
 
    return 1;
3380
 
}
3381
 
 
3382
 
static int
3383
 
_validate_outer(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
3384
 
{
3385
 
    if (groups < 0 || groups > 100 || code >= end || end[-1] != SRE_OP_SUCCESS)
3386
 
        FAIL;
3387
 
    if (groups == 0)  /* fix for simplejson */
3388
 
        groups = 100; /* 100 groups should always be safe */
3389
 
    return _validate_inner(code, end-1, groups);
 
6386
 
 
6387
typedef struct SRE_Validation {
 
6388
    int mark_count;
 
6389
    int max_mark;
 
6390
    int max_group_ref;
 
6391
    int repeat_count;
 
6392
    int max_repeat;
 
6393
} SRE_Validation;
 
6394
 
 
6395
/*
 
6396
    Validates a big charset. Returns a pointer to the following op if valid
 
6397
    or NULL if invalid.
 
6398
*/
 
6399
SRE_CODE* validate_bigcharset(SRE_CODE* pattern, SRE_CODE* end_ptr) {
 
6400
    SRE_CODE* end_charset = pattern + pattern[0];
 
6401
    SRE_CODE* subsets;
 
6402
    int subset_count = 0;
 
6403
    int hi_byte;
 
6404
    if (pattern[0] < 1 || end_charset > end_ptr)
 
6405
        return NULL;
 
6406
 
 
6407
    pattern++;
 
6408
    // The subset indexes are in 256 bytes; the subsets themselves follow.
 
6409
    subsets = pattern + 256 / SRE_BYTES_PER_CODE;
 
6410
    if (subsets > end_ptr)
 
6411
        return NULL;
 
6412
 
 
6413
    for (hi_byte = 0; hi_byte < 256; hi_byte++) {
 
6414
        int index = (pattern[hi_byte / SRE_BYTES_PER_CODE] >> ((hi_byte % SRE_BYTES_PER_CODE) * 8)) & 0xFF;
 
6415
        if (index > subset_count)
 
6416
            return NULL;
 
6417
        if (index == subset_count)
 
6418
            subset_count++;
 
6419
    }
 
6420
 
 
6421
    // Each subset is 256 bits.
 
6422
    pattern = subsets + subset_count * (256 / SRE_BITS_PER_CODE);
 
6423
    if (pattern != end_charset)
 
6424
        return NULL;
 
6425
 
 
6426
    return pattern;
 
6427
}
 
6428
 
 
6429
/*
 
6430
    Validates a charset. Returns a pointer to the following op if valid
 
6431
    or NULL if invalid.
 
6432
*/
 
6433
SRE_CODE* validate_charset(SRE_CODE* pattern, SRE_CODE* end_ptr) {
 
6434
    SRE_CODE* ptr = skip_charset(pattern);
 
6435
    return ptr > end_ptr ? NULL : ptr;
 
6436
}
 
6437
 
 
6438
/*
 
6439
    Validates a set. Returns a pointer to the following op if valid
 
6440
    or NULL if invalid.
 
6441
*/
 
6442
SRE_CODE* validate_in(SRE_CODE* pattern, SRE_CODE* end_ptr) {
 
6443
    SRE_OpInfo* info_ptr;
 
6444
    SRE_CODE* charset_end = pattern + pattern[0];
 
6445
    if (pattern[0] < 1 || charset_end > end_ptr)
 
6446
        return NULL;
 
6447
 
 
6448
    pattern++;
 
6449
 
 
6450
    do {
 
6451
        if (pattern[0] > SRE_MAX_OP)
 
6452
            return NULL;
 
6453
        info_ptr = &op_info[*pattern++];
 
6454
        switch (info_ptr->type) {
 
6455
        case SRE_TYPE_BIGCHARSET: // <bigcharset> set
 
6456
            pattern = validate_bigcharset(pattern, charset_end);
 
6457
            if (pattern == NULL)
 
6458
                return NULL;
 
6459
            break;
 
6460
        case SRE_TYPE_CHARSET: // <charset> set
 
6461
            pattern = validate_charset(pattern, charset_end);
 
6462
            if (pattern == NULL)
 
6463
                return NULL;
 
6464
            break;
 
6465
        case SRE_TYPE_CATEGORY: // <category>
 
6466
            break;
 
6467
        case SRE_TYPE_LITERAL: // <literal> code
 
6468
            pattern++;
 
6469
            break;
 
6470
        case SRE_TYPE_RANGE: // RANGE min max
 
6471
            if (pattern[0] > pattern[1])
 
6472
                return NULL;
 
6473
            pattern += 2;
 
6474
            break;
 
6475
        default:
 
6476
            return NULL;
 
6477
        }
 
6478
    } while (pattern < charset_end);
 
6479
 
 
6480
    return pattern > charset_end ? NULL : pattern;
 
6481
}
 
6482
 
 
6483
/*
 
6484
    Validates a single-character op. Returns a pointer to the following op if valid
 
6485
    or NULL if invalid.
 
6486
*/
 
6487
SRE_CODE* validate_one_pattern(SRE_CODE* pattern, SRE_CODE* end_ptr, int direction) {
 
6488
    SRE_OpInfo* info_ptr;
 
6489
 
 
6490
    if (pattern[0] > SRE_MAX_OP)
 
6491
        return NULL;
 
6492
    info_ptr = &op_info[*pattern++];
 
6493
    switch (info_ptr->type) {
 
6494
    case SRE_TYPE_CATEGORY: // <category>
 
6495
        if (direction != 0 && direction != info_ptr->direction)
 
6496
            return NULL;
 
6497
        direction = info_ptr->direction;
 
6498
        break;
 
6499
    case SRE_TYPE_BIGCHARSET: // <bigcharset> bigcharset
 
6500
        if (direction != 0 && direction != info_ptr->direction)
 
6501
            return NULL;
 
6502
        direction = info_ptr->direction;
 
6503
        pattern = validate_bigcharset(pattern, end_ptr);
 
6504
        if (pattern == NULL)
 
6505
            return NULL;
 
6506
        break;
 
6507
    case SRE_TYPE_CHARSET: // <charset> charset
 
6508
        if (direction != 0 && direction != info_ptr->direction)
 
6509
            return NULL;
 
6510
        direction = info_ptr->direction;
 
6511
        pattern = validate_charset(pattern, end_ptr);
 
6512
        if (pattern == NULL)
 
6513
            return NULL;
 
6514
        break;
 
6515
    case SRE_TYPE_IN: // <in> set
 
6516
        if (direction != 0 && direction != info_ptr->direction)
 
6517
            return NULL;
 
6518
        direction = info_ptr->direction;
 
6519
        pattern = validate_in(pattern, end_ptr);
 
6520
        if (pattern == NULL)
 
6521
            return NULL;
 
6522
        break;
 
6523
    case SRE_TYPE_LITERAL: // <literal> code
 
6524
        if (direction != 0 && direction != info_ptr->direction)
 
6525
            return NULL;
 
6526
        direction = info_ptr->direction;
 
6527
        pattern++;
 
6528
        break;
 
6529
    case SRE_TYPE_RANGE: // <range> min max
 
6530
        if (direction != 0 && direction != info_ptr->direction)
 
6531
            return NULL;
 
6532
        direction = info_ptr->direction;
 
6533
        if (pattern[0] > pattern[1])
 
6534
            return NULL;
 
6535
        pattern += 2;
 
6536
        break;
 
6537
    default:
 
6538
        return NULL;
 
6539
    }
 
6540
 
 
6541
    return pattern > end_ptr ? NULL : pattern;
 
6542
}
 
6543
 
 
6544
SRE_CODE* validate_subpattern(SRE_CODE* pattern, SRE_CODE* end_ptr, int* direction, SRE_Validation* validation) {
 
6545
    int dir = *direction;
 
6546
    SRE_OpInfo* info_ptr;
 
6547
    SRE_CODE* skip_ptr;
 
6548
    SRE_CODE* ptr;
 
6549
    SRE_CODE* skip_end_ptr;
 
6550
    int subdir;
 
6551
 
 
6552
    while (pattern < end_ptr) {
 
6553
        if (pattern[0] > SRE_MAX_OP)
 
6554
            return NULL;
 
6555
        info_ptr = &op_info[*pattern++];
 
6556
        switch (info_ptr->type) {
 
6557
        case SRE_TYPE_CATEGORY: // <category>
 
6558
            if (dir != 0 && dir != info_ptr->direction)
 
6559
                return NULL;
 
6560
            dir = info_ptr->direction;
 
6561
            break;
 
6562
        case SRE_TYPE_ASSERT: // <assert> <skip to end> ... <end_assert>
 
6563
            skip_ptr = pattern + pattern[0];
 
6564
            if (pattern[0] < 2 || skip_ptr > end_ptr || skip_ptr[-1] != info_ptr->end_marker)
 
6565
                return NULL;
 
6566
            subdir = 0;
 
6567
            if (validate_subpattern(pattern + 1, skip_ptr - 1, &subdir, validation) != skip_ptr - 1)
 
6568
                return NULL;
 
6569
            pattern = skip_ptr;
 
6570
            break;
 
6571
        case SRE_TYPE_ATOMIC: // <ATOMIC> ... <END_ATOMIC>
 
6572
            // The call should return a pointer to the END_ATOMIC, which it doesn't understand.
 
6573
            ptr = validate_subpattern(pattern, end_ptr, &dir, validation);
 
6574
            if (ptr == NULL || ptr >= end_ptr || ptr[0] != info_ptr->end_marker)
 
6575
                return NULL;
 
6576
            pattern = ptr + 1;
 
6577
            break;
 
6578
        case SRE_TYPE_BIGCHARSET: // <bigcharset> bigcharset
 
6579
            if (dir != 0 && dir != info_ptr->direction)
 
6580
                return NULL;
 
6581
            dir = info_ptr->direction;
 
6582
            pattern = validate_bigcharset(pattern, end_ptr);
 
6583
            if (pattern == NULL)
 
6584
                return NULL;
 
6585
            break;
 
6586
        case SRE_TYPE_POSITION: // <position>
 
6587
            break;
 
6588
        case SRE_TYPE_BRANCH: // <BRANCH> <skip to next> ... <JUMP> <skip to end> <skip to next> ... <JUMP> <skip to end> 0
 
6589
            // All the jumps should end in the same place.
 
6590
            skip_end_ptr = NULL;
 
6591
            do {
 
6592
                // The offset to the next alternative's offset.
 
6593
                if (pattern[0] < 3)
 
6594
                    return NULL;
 
6595
                skip_ptr = pattern + pattern[0];
 
6596
                if (skip_ptr >= end_ptr)
 
6597
                    return NULL;
 
6598
                // Validate this alternative, which stops at the jump.
 
6599
                ptr = validate_subpattern(pattern + 1, skip_ptr - 2, &dir, validation);
 
6600
                if (ptr != skip_ptr - 2 || ptr[0] != SRE_OP_JUMP || ptr[1] < 1)
 
6601
                    return NULL;
 
6602
                // The jump to the end.
 
6603
                ptr = ptr + 1 + ptr[1];
 
6604
                if (skip_end_ptr == NULL)
 
6605
                    skip_end_ptr = ptr;
 
6606
                else if (ptr != skip_end_ptr)
 
6607
                    return NULL;
 
6608
                pattern = skip_ptr;
 
6609
            } while (pattern[0] != 0);
 
6610
            pattern++;
 
6611
            break;
 
6612
        case SRE_TYPE_CHARSET: // <charset> charset
 
6613
            if (dir != 0 && dir != info_ptr->direction)
 
6614
                return NULL;
 
6615
            dir = info_ptr->direction;
 
6616
            pattern = validate_charset(pattern, end_ptr);
 
6617
            if (pattern == NULL)
 
6618
                return NULL;
 
6619
            break;
 
6620
        case SRE_TYPE_GROUPREF: // <groupref> group_id
 
6621
            if (dir != 0 && dir != info_ptr->direction)
 
6622
                return NULL;
 
6623
            dir = info_ptr->direction;
 
6624
            if (validation->max_group_ref < pattern[0])
 
6625
                validation->max_group_ref = pattern[0];
 
6626
            pattern++;
 
6627
            break;
 
6628
        case SRE_TYPE_GROUPREF_EXISTS: // <GROUPREF_EXISTS> group_id <skip to code_no> code_yes <JUMP> <skip to end> code_no
 
6629
            // Locate code_no.
 
6630
            if (pattern[1] < 2)
 
6631
                return NULL;
 
6632
            skip_ptr = pattern + pattern[1];
 
6633
            if (skip_ptr > end_ptr)
 
6634
                return NULL;
 
6635
            // code_yes lies between the skip and code_no.
 
6636
            ptr = validate_subpattern(pattern + 2, skip_ptr, &dir, validation);
 
6637
            // 'ptr' will point after code_yes and at the jump, if present.
 
6638
            // (The jump will have been rejected by the call.)
 
6639
            // Validate code_no, if present.
 
6640
            if (ptr == skip_ptr - 2) {
 
6641
                if (ptr[0] != SRE_OP_JUMP || ptr[1] < 1)
 
6642
                    return NULL;
 
6643
                skip_ptr = ptr + 1 + ptr[1];
 
6644
                if (skip_ptr > end_ptr)
 
6645
                    return NULL;
 
6646
                ptr = validate_subpattern(ptr + 2, skip_ptr, &dir, validation);
 
6647
                if (ptr < skip_ptr)
 
6648
                    return NULL;
 
6649
            } else if (ptr != skip_ptr)
 
6650
                return NULL;
 
6651
            pattern = skip_ptr;
 
6652
            break;
 
6653
        case SRE_TYPE_IN: // <in> set
 
6654
            if (dir != 0 && dir != info_ptr->direction)
 
6655
                return NULL;
 
6656
            dir = info_ptr->direction;
 
6657
            pattern = validate_in(pattern, end_ptr);
 
6658
            if (pattern == NULL)
 
6659
                return NULL;
 
6660
            break;
 
6661
        case SRE_TYPE_LITERAL: // <literal> code
 
6662
            if (dir != 0 && dir != info_ptr->direction)
 
6663
                return NULL;
 
6664
            dir = info_ptr->direction;
 
6665
            pattern++;
 
6666
            break;
 
6667
        case SRE_TYPE_LITERAL_STRING: // <literal_string> length ...
 
6668
            if (dir != 0 && dir != info_ptr->direction)
 
6669
                return NULL;
 
6670
            dir = info_ptr->direction;
 
6671
            if (pattern[0] == 0)
 
6672
                return NULL;
 
6673
            pattern += 1 + pattern[0];
 
6674
            break;
 
6675
        case SRE_TYPE_MARK: // <MARK> mark_id
 
6676
            validation->mark_count++;
 
6677
            if (validation->max_mark < pattern[0])
 
6678
                validation->max_mark = pattern[0];
 
6679
            pattern++;
 
6680
            break;
 
6681
        case SRE_TYPE_RANGE: // <range> min max
 
6682
            if (dir != 0 && dir != info_ptr->direction)
 
6683
                return NULL;
 
6684
            dir = info_ptr->direction;
 
6685
            if (pattern[0] > pattern[1])
 
6686
                return NULL;
 
6687
            pattern += 2;
 
6688
            break;
 
6689
        case SRE_TYPE_REPEAT: // <repeat> <skip to end> <index> <min> <max> ... <end_repeat> <skip to start>
 
6690
            if (dir != 0 && dir != info_ptr->direction)
 
6691
                return NULL;
 
6692
            dir = info_ptr->direction;
 
6693
            if (pattern[0] < 6)
 
6694
                return NULL;
 
6695
            skip_ptr = pattern + pattern[0];
 
6696
            if (skip_ptr > end_ptr)
 
6697
                return NULL;
 
6698
            validation->repeat_count++;
 
6699
            if (validation->max_repeat < pattern[1])
 
6700
                validation->max_repeat = pattern[1];
 
6701
            if (pattern[2] > pattern[3])
 
6702
                return NULL;
 
6703
            if (skip_ptr[-1] != info_ptr->end_marker || skip_ptr - skip_ptr[0] != pattern)
 
6704
                return NULL;
 
6705
            if (validate_subpattern(pattern + 4, skip_ptr - 1, &dir, validation) != skip_ptr - 1)
 
6706
                return NULL;
 
6707
            pattern = skip_ptr + 1;
 
6708
            break;
 
6709
        case SRE_TYPE_REPEAT_ONE: // <repeat_one> <skip to end> <index> <min> <max> ...
 
6710
            if (dir != 0 && dir != info_ptr->direction)
 
6711
                return NULL;
 
6712
            dir = info_ptr->direction;
 
6713
            if (pattern[0] < 5)
 
6714
                return NULL;
 
6715
            skip_ptr = pattern + pattern[0];
 
6716
            if (skip_ptr > end_ptr)
 
6717
                return NULL;
 
6718
            validation->repeat_count++;
 
6719
            if (validation->max_repeat < pattern[1])
 
6720
                validation->max_repeat = pattern[1];
 
6721
            if (pattern[2] > pattern[3])
 
6722
                return NULL;
 
6723
            if (validate_one_pattern(pattern + 4, skip_ptr, dir) != skip_ptr)
 
6724
                return NULL;
 
6725
            pattern = skip_ptr;
 
6726
            break;
 
6727
        default:
 
6728
            // Anything else might be meaningful to the caller.
 
6729
            *direction = dir;
 
6730
            return pattern - 1;
 
6731
        }
 
6732
    }
 
6733
 
 
6734
    *direction = dir;
 
6735
    return pattern > end_ptr ? NULL : pattern;
3390
6736
}
3391
6737
 
3392
6738
static int
3393
6739
_validate(PatternObject *self)
3394
6740
{
3395
 
    if (!_validate_outer(self->code, self->code+self->codesize, self->groups))
3396
 
    {
3397
 
        PyErr_SetString(PyExc_RuntimeError, "invalid SRE code");
3398
 
        return 0;
3399
 
    }
3400
 
    else
3401
 
        VTRACE(("Success!\n"));
 
6741
    SRE_Validation validation;
 
6742
    int direction = 0;
 
6743
    SRE_CODE* end_ptr = self->code + self->codesize;
 
6744
 
 
6745
    validation.mark_count = 0;
 
6746
    validation.max_mark = -1;
 
6747
    validation.max_group_ref = -1;
 
6748
    validation.repeat_count = 0;
 
6749
    validation.max_repeat = -1;
 
6750
 
 
6751
    /* _validate_subpattern will return a pointer to the first op it doesn't understand
 
6752
       or NULL if the pattern is invalid. It doesn't understand SRE_OP_SUCCESS (which
 
6753
       occurs only at the end of the pattern), so the result should be a pointer to that. */
 
6754
    if (self->codesize < 1 || end_ptr[-1] != SRE_OP_SUCCESS)
 
6755
        goto error;
 
6756
    if (validate_subpattern(self->code, end_ptr, &direction, &validation) != end_ptr - 1)
 
6757
        goto error;
 
6758
    if (validation.max_mark != validation.mark_count - 1 || validation.max_repeat != validation.repeat_count - 1)
 
6759
        goto error;
 
6760
    if (validation.max_group_ref * 2 >= validation.mark_count || validation.mark_count % 2 != 0)
 
6761
        goto error;
 
6762
 
 
6763
    self->marks = validation.mark_count;
 
6764
    self->repeats = validation.repeat_count;
 
6765
 
 
6766
    VTRACE(("Success!\n"));
3402
6767
    return 1;
 
6768
 
 
6769
error:
 
6770
    PyErr_SetString(PyExc_RuntimeError, "invalid SRE code");
 
6771
    return 0;
3403
6772
}
3404
6773
 
3405
6774
/* -------------------------------------------------------------------- */
3657
7026
 
3658
7027
    return pair;
3659
7028
 
3660
 
  error:
 
7029
error:
3661
7030
    Py_DECREF(pair);
3662
7031
    return NULL;
3663
7032
}
3939
7308
    state_reset(state);
3940
7309
 
3941
7310
    state->ptr = state->start;
 
7311
    memset(state->mark, 0, state->pattern_code[0] * sizeof(SRE_CHAR*));
3942
7312
 
3943
7313
    if (state->charsize == 1) {
3944
 
        status = sre_match(state, PatternObject_GetCode(self->pattern));
 
7314
        status = sre_match(state, state->pattern_code);
3945
7315
    } else {
3946
7316
#if defined(HAVE_UNICODE)
3947
 
        status = sre_umatch(state, PatternObject_GetCode(self->pattern));
 
7317
        status = sre_umatch(state, state->pattern_code);
3948
7318
#endif
3949
7319
    }
3950
7320
    if (PyErr_Occurred())
3974
7344
    state->ptr = state->start;
3975
7345
 
3976
7346
    if (state->charsize == 1) {
3977
 
        status = sre_search(state, PatternObject_GetCode(self->pattern));
 
7347
        status = sre_search(state, state->pattern_code);
3978
7348
    } else {
3979
7349
#if defined(HAVE_UNICODE)
3980
 
        status = sre_usearch(state, PatternObject_GetCode(self->pattern));
 
7350
        status = sre_usearch(state, state->pattern_code);
3981
7351
#endif
3982
7352
    }
3983
7353
    if (PyErr_Occurred())
4040
7410
    PyObject* string;
4041
7411
    Py_ssize_t start = 0;
4042
7412
    Py_ssize_t end = PY_SSIZE_T_MAX;
 
7413
    SRE_CODE* pattern_code;
 
7414
 
4043
7415
    if (!PyArg_ParseTuple(args, "O|nn:scanner", &string, &start, &end))
4044
7416
        return NULL;
4045
7417
 
4048
7420
    if (!self)
4049
7421
        return NULL;
4050
7422
 
4051
 
    string = state_init(&self->state, pattern, string, start, end);
 
7423
    pattern_code = PatternObject_GetCode(pattern);
 
7424
 
 
7425
    string = state_init(&self->state, pattern, string, start, end, pattern_code);
4052
7426
    if (!string) {
4053
7427
        PyObject_DEL(self);
4054
7428
        return NULL;