~pythonregexp2.7/python/issue2636-01+09-01+10

« back to all changes in this revision

Viewing changes to Modules/_sre.c

  • Committer: Jeffrey C. "The TimeHorse" Jacobs
  • Date: 2008-05-24 21:02:03 UTC
  • mfrom: (39055.1.22 Regexp-2.6)
  • Revision ID: darklord@timehorse.com-20080524210203-7qmdoowfxbb3bgwy
Merged in changes from the Single-Loop Engine branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
485
485
#define SRE_MATCH_ON_PUSH_CTX_AND_POSITION sre_match_on_push_ctx_and_position
486
486
#define SRE_MATCH_ON_POP_CTX_AND_POSITION sre_match_on_pop_ctx_and_position
487
487
 
488
 
#define SRE_MATCHa sre_match_a
489
 
 
490
488
#if defined(HAVE_UNICODE)
491
489
 
492
490
#define SRE_RECURSIVE
595
593
#undef SRE_MATCH_ON_PUSH_CTX_AND_POSITION
596
594
#undef SRE_MATCH_ON_POP_CTX_AND_POSITION
597
595
 
598
 
#undef SRE_MATCHa
599
 
 
600
596
/* generate 16-bit unicode version */
601
597
 
602
598
#define SRE_CHAR Py_UNICODE
700
696
#define SRE_MATCH_UNWIND_LOOKUP_TABLE sre_umatch_unwind_lookup_table
701
697
#define SRE_MATCH_ON_PUSH_CTX_AND_POSITION sre_umatch_on_push_ctx_and_position
702
698
#define SRE_MATCH_ON_POP_CTX_AND_POSITION sre_umatch_on_pop_ctx_and_position
703
 
 
704
 
#define SRE_MATCHa sre_umatch_a
705
699
#endif
706
700
 
707
701
#endif /* SRE_RECURSIVE */
1067
1061
    case SRE_OP_ANY:
1068
1062
        /* repeated dot wildcard. */
1069
1063
        TRACE(("|%p|%p|COUNT ANY\n", pattern, ptr));
1070
 
        while (ptr < end && !SRE_IS_LINEBREAK(*ptr))
 
1064
        while (ptr < end && !sre_category_is_linebreak(*ptr))
1071
1065
            ptr++;
1072
1066
        break;
1073
1067
 
1185
1179
 *
1186
1180
 * For more information, check the discussion at SF patch #712900.
1187
1181
 */
1188
 
#if !REMOVE_SRE_MATCH_MACROS
1189
 
#define LASTMARK_SAVE()     \
1190
 
    do { \
1191
 
        ctx->lastmark = state->lastmark; \
1192
 
        ctx->lastindex = state->lastindex; \
1193
 
    } while (0)
1194
 
#define LASTMARK_RESTORE()  \
1195
 
    do { \
1196
 
        state->lastmark = ctx->lastmark; \
1197
 
        state->lastindex = ctx->lastindex; \
1198
 
    } while (0)
1199
 
 
1200
 
#define RETURN_ERROR(i) do { return i; } while(0)
1201
 
#define RETURN_FAILURE do { ret = 0; goto exit; } while(0)
1202
 
#define RETURN_SUCCESS do { ret = 1; goto exit; } while(0)
1203
 
 
1204
 
#define RETURN_ON_ERROR(i) \
1205
 
    do { if (i < 0) RETURN_ERROR(i); } while (0)
1206
 
#define RETURN_ON_SUCCESS(i) \
1207
 
    do { RETURN_ON_ERROR(i); if (i > 0) RETURN_SUCCESS; } while (0)
1208
 
#define RETURN_ON_FAILURE(i) \
1209
 
    do { RETURN_ON_ERROR(i); if (i == 0) RETURN_FAILURE; } while (0)
1210
 
 
1211
 
#define SFY(x) #x
1212
 
 
1213
 
#define DATA_STACK_ALLOC(state, type, ptr) \
1214
 
do { \
1215
 
    alloc_pos = state->data_stack_base; \
1216
 
    TRACE(("allocating %s in %d (%d)\n", \
1217
 
           SFY(type), alloc_pos, sizeof(type))); \
1218
 
    if (state->data_stack_size < alloc_pos+sizeof(type)) { \
1219
 
        int j = data_stack_grow(state, sizeof(type)); \
1220
 
        if (j < 0) return j; \
1221
 
        if (ctx_pos != -1) \
1222
 
            DATA_STACK_LOOKUP_AT(state, SRE_MATCH_CONTEXT, ctx, ctx_pos); \
1223
 
    } \
1224
 
    ptr = (type*)(state->data_stack+alloc_pos); \
1225
 
    state->data_stack_base += sizeof(type); \
1226
 
} while (0)
1227
 
 
1228
 
#define DATA_STACK_LOOKUP_AT(state, type, ptr, pos) \
1229
 
do { \
1230
 
    TRACE(("looking up %s at %d\n", SFY(type), pos)); \
1231
 
    ptr = (type*)(state->data_stack+pos); \
1232
 
} while (0)
1233
 
 
1234
 
#define DATA_STACK_PUSH(state, data, size) \
1235
 
do { \
1236
 
    TRACE(("copy data in %p to %d (%d)\n", \
1237
 
           data, state->data_stack_base, size)); \
1238
 
    if (state->data_stack_size < state->data_stack_base+size) { \
1239
 
        int j = data_stack_grow(state, size); \
1240
 
        if (j < 0) return j; \
1241
 
        if (ctx_pos != -1) \
1242
 
            DATA_STACK_LOOKUP_AT(state, SRE_MATCH_CONTEXT, ctx, ctx_pos); \
1243
 
    } \
1244
 
    memcpy(state->data_stack+state->data_stack_base, data, size); \
1245
 
    state->data_stack_base += size; \
1246
 
} while (0)
1247
 
 
1248
 
#define DATA_STACK_POP(state, data, size, discard) \
1249
 
do { \
1250
 
    TRACE(("copy data to %p from %d (%d)\n", \
1251
 
           data, state->data_stack_base-size, size)); \
1252
 
    memcpy(data, state->data_stack+state->data_stack_base-size, size); \
1253
 
    if (discard) \
1254
 
        state->data_stack_base -= size; \
1255
 
} while (0)
1256
 
 
1257
 
#define DATA_STACK_POP_DISCARD(state, size) \
1258
 
do { \
1259
 
    TRACE(("discard data from %d (%d)\n", \
1260
 
           state->data_stack_base-size, size)); \
1261
 
    state->data_stack_base -= size; \
1262
 
} while(0)
1263
 
 
1264
 
#define DATA_PUSH(x) \
1265
 
    DATA_STACK_PUSH(state, (x), sizeof(*(x)))
1266
 
#define DATA_POP(x) \
1267
 
    DATA_STACK_POP(state, (x), sizeof(*(x)), 1)
1268
 
#define DATA_POP_DISCARD(x) \
1269
 
    DATA_STACK_POP_DISCARD(state, sizeof(*(x)))
1270
 
#define DATA_ALLOC(t,p) \
1271
 
    DATA_STACK_ALLOC(state, t, p)
1272
 
#define DATA_LOOKUP_AT(t,p,pos) \
1273
 
    DATA_STACK_LOOKUP_AT(state,t,p,pos)
1274
 
 
1275
 
#define MARK_PUSH(lastmark) \
1276
 
    do if (lastmark > 0) { \
1277
 
        i = lastmark; /* ctx->lastmark may change if reallocated */ \
1278
 
        DATA_STACK_PUSH(state, state->mark, (i+1)*sizeof(void*)); \
1279
 
    } while (0)
1280
 
#define MARK_POP(lastmark) \
1281
 
    do if (lastmark > 0) { \
1282
 
        DATA_STACK_POP(state, state->mark, (lastmark+1)*sizeof(void*), 1); \
1283
 
    } while (0)
1284
 
#define MARK_POP_KEEP(lastmark) \
1285
 
    do if (lastmark > 0) { \
1286
 
        DATA_STACK_POP(state, state->mark, (lastmark+1)*sizeof(void*), 0); \
1287
 
    } while (0)
1288
 
#define MARK_POP_DISCARD(lastmark) \
1289
 
    do if (lastmark > 0) { \
1290
 
        DATA_STACK_POP_DISCARD(state, (lastmark+1)*sizeof(void*)); \
1291
 
    } while (0)
1292
 
 
1293
 
#endif /* !REMOVE_SRE_MATCH_MACROS */
1294
1182
#define JUMP_NONE            0
1295
1183
#define JUMP_MAX_UNTIL_1     1
1296
1184
#define JUMP_MAX_UNTIL_2     2
1307
1195
#define JUMP_ASSERT_NOT      13
1308
1196
#define JUMP__COUNT          14
1309
1197
 
1310
 
#if !REMOVE_SRE_MATCH_MACROS
1311
 
#define DO_JUMP(jumpvalue, jumplabel, nextpattern) \
1312
 
    DATA_ALLOC(SRE_MATCH_CONTEXT, nextctx); \
1313
 
    nextctx->last_ctx_pos = ctx_pos; \
1314
 
    nextctx->jump = jumpvalue; \
1315
 
    nextctx->pattern = nextpattern; \
1316
 
    ctx_pos = alloc_pos; \
1317
 
    ctx = nextctx; \
1318
 
    goto entrance; \
1319
 
    jumplabel: \
1320
 
    while (0) /* gcc doesn't like labels at end of scopes */ \
1321
 
 
1322
 
#endif /* !REMOVE_SRE_MATCH_MACROS */
1323
1198
typedef struct {
1324
1199
    Py_ssize_t last_ctx_pos;
1325
1200
    Py_ssize_t jump;
1336
1211
 
1337
1212
/* check if string matches the given pattern.  returns <0 for
1338
1213
   error, 0 for failure, and 1 for success */
1339
 
#if !REMOVE_SRE_MATCH_MACROS
1340
 
LOCAL(Py_ssize_t)
1341
 
SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
1342
 
{
1343
 
    SRE_CHAR* end = (SRE_CHAR *)state->end;
1344
 
    Py_ssize_t alloc_pos, ctx_pos = -1;
1345
 
    Py_ssize_t i, ret = 0;
1346
 
    Py_ssize_t jump;
1347
 
    unsigned int sigcount=0; /* Iteration Counter; for signalling */ 
1348
 
 
1349
 
    SRE_MATCH_CONTEXT* ctx;
1350
 
    SRE_MATCH_CONTEXT* nextctx;
1351
 
 
1352
 
    TRACE(("|%p|%p|ENTER\n", pattern, state->ptr));
1353
 
 
1354
 
    DATA_ALLOC(SRE_MATCH_CONTEXT, ctx);
1355
 
    ctx->last_ctx_pos = -1;
1356
 
    ctx->jump = JUMP_NONE;
1357
 
    ctx->pattern = pattern;
1358
 
    ctx_pos = alloc_pos;
1359
 
 
1360
 
entrance:
1361
 
 
1362
 
    ctx->ptr = (SRE_CHAR *)state->ptr;
1363
 
 
1364
 
    if (ctx->pattern[0] == SRE_OP_INFO) {
1365
 
        /* optimization info block */
1366
 
        /* <INFO> <1=skip> <2=flags> <3=min> ... */
1367
 
        if (ctx->pattern[3] && (end - ctx->ptr) < ctx->pattern[3]) {
1368
 
            TRACE(("reject (got %d chars, need %d)\n",
1369
 
                   (end - ctx->ptr), ctx->pattern[3]));
1370
 
            RETURN_FAILURE;
1371
 
        }
1372
 
        ctx->pattern += ctx->pattern[1] + 1;
1373
 
    }
1374
 
 
1375
 
    for (;;) {
1376
 
        ++sigcount;
1377
 
        if ((0 == (sigcount & 0xfff)) && PyErr_CheckSignals())
1378
 
            RETURN_ERROR(SRE_ERROR_INTERRUPTED);
1379
 
 
1380
 
        switch (*ctx->pattern++) {
1381
 
 
1382
 
        case SRE_OP_MARK:
1383
 
            /* set mark */
1384
 
            /* <MARK> <gid> */
1385
 
            TRACE(("|%p|%p|MARK %d\n", ctx->pattern,
1386
 
                   ctx->ptr, ctx->pattern[0]));
1387
 
            i = ctx->pattern[0];
1388
 
            if (i & 1)
1389
 
                state->lastindex = i/2 + 1;
1390
 
            if (i > state->lastmark) {
1391
 
                /* state->lastmark is the highest valid index in the
1392
 
                   state->mark array.  If it is increased by more than 1,
1393
 
                   the intervening marks must be set to NULL to signal
1394
 
                   that these marks have not been encountered. */
1395
 
                Py_ssize_t j = state->lastmark + 1;
1396
 
                while (j < i)
1397
 
                    state->mark[j++] = NULL;
1398
 
                state->lastmark = i;
1399
 
            }
1400
 
            state->mark[i] = ctx->ptr;
1401
 
            ctx->pattern++;
1402
 
            break;
1403
 
 
1404
 
        case SRE_OP_LITERAL:
1405
 
            /* match literal string */
1406
 
            /* <LITERAL> <code> */
1407
 
            TRACE(("|%p|%p|LITERAL %d\n", ctx->pattern,
1408
 
                   ctx->ptr, *ctx->pattern));
1409
 
            if (ctx->ptr >= end || (SRE_CODE) ctx->ptr[0] != ctx->pattern[0])
1410
 
                RETURN_FAILURE;
1411
 
            ctx->pattern++;
1412
 
            ctx->ptr++;
1413
 
            break;
1414
 
 
1415
 
        case SRE_OP_NOT_LITERAL:
1416
 
            /* match anything that is not literal character */
1417
 
            /* <NOT_LITERAL> <code> */
1418
 
            TRACE(("|%p|%p|NOT_LITERAL %d\n", ctx->pattern,
1419
 
                   ctx->ptr, *ctx->pattern));
1420
 
            if (ctx->ptr >= end || (SRE_CODE) ctx->ptr[0] == ctx->pattern[0])
1421
 
                RETURN_FAILURE;
1422
 
            ctx->pattern++;
1423
 
            ctx->ptr++;
1424
 
            break;
1425
 
 
1426
 
        case SRE_OP_SUCCESS:
1427
 
            /* end of pattern */
1428
 
            TRACE(("|%p|%p|SUCCESS\n", ctx->pattern, ctx->ptr));
1429
 
            state->ptr = ctx->ptr;
1430
 
            RETURN_SUCCESS;
1431
 
 
1432
 
        case SRE_OP_AT:
1433
 
            /* match at given position */
1434
 
            /* <AT> <code> */
1435
 
            TRACE(("|%p|%p|AT %d\n", ctx->pattern, ctx->ptr, *ctx->pattern));
1436
 
            if (!SRE_AT(state, ctx->ptr, *ctx->pattern))
1437
 
                RETURN_FAILURE;
1438
 
            ctx->pattern++;
1439
 
            break;
1440
 
 
1441
 
        case SRE_OP_CATEGORY:
1442
 
            /* match at given category */
1443
 
            /* <CATEGORY> <code> */
1444
 
            TRACE(("|%p|%p|CATEGORY %d\n", ctx->pattern,
1445
 
                   ctx->ptr, *ctx->pattern));
1446
 
            if (ctx->ptr >= end || !sre_category(ctx->pattern[0], ctx->ptr[0]))
1447
 
                RETURN_FAILURE;
1448
 
            ctx->pattern++;
1449
 
            ctx->ptr++;
1450
 
            break;
1451
 
 
1452
 
        case SRE_OP_ANY:
1453
 
            /* match anything (except a newline) */
1454
 
            /* <ANY> */
1455
 
            TRACE(("|%p|%p|ANY\n", ctx->pattern, ctx->ptr));
1456
 
            if (ctx->ptr >= end || SRE_IS_LINEBREAK(ctx->ptr[0]))
1457
 
                RETURN_FAILURE;
1458
 
            ctx->ptr++;
1459
 
            break;
1460
 
 
1461
 
        case SRE_OP_ANY_ALL:
1462
 
            /* match anything */
1463
 
            /* <ANY_ALL> */
1464
 
            TRACE(("|%p|%p|ANY_ALL\n", ctx->pattern, ctx->ptr));
1465
 
            if (ctx->ptr >= end)
1466
 
                RETURN_FAILURE;
1467
 
            ctx->ptr++;
1468
 
            break;
1469
 
 
1470
 
        case SRE_OP_IN:
1471
 
            /* match set member (or non_member) */
1472
 
            /* <IN> <skip> <set> */
1473
 
            TRACE(("|%p|%p|IN\n", ctx->pattern, ctx->ptr));
1474
 
            if (ctx->ptr >= end || !SRE_CHARSET(ctx->pattern + 1, *ctx->ptr))
1475
 
                RETURN_FAILURE;
1476
 
            ctx->pattern += ctx->pattern[0];
1477
 
            ctx->ptr++;
1478
 
            break;
1479
 
 
1480
 
        case SRE_OP_LITERAL_IGNORE:
1481
 
            TRACE(("|%p|%p|LITERAL_IGNORE %d\n",
1482
 
                   ctx->pattern, ctx->ptr, ctx->pattern[0]));
1483
 
            if (ctx->ptr >= end ||
1484
 
                state->lower(*ctx->ptr) != state->lower(*ctx->pattern))
1485
 
                RETURN_FAILURE;
1486
 
            ctx->pattern++;
1487
 
            ctx->ptr++;
1488
 
            break;
1489
 
 
1490
 
        case SRE_OP_NOT_LITERAL_IGNORE:
1491
 
            TRACE(("|%p|%p|NOT_LITERAL_IGNORE %d\n",
1492
 
                   ctx->pattern, ctx->ptr, *ctx->pattern));
1493
 
            if (ctx->ptr >= end ||
1494
 
                state->lower(*ctx->ptr) == state->lower(*ctx->pattern))
1495
 
                RETURN_FAILURE;
1496
 
            ctx->pattern++;
1497
 
            ctx->ptr++;
1498
 
            break;
1499
 
 
1500
 
        case SRE_OP_IN_IGNORE:
1501
 
            TRACE(("|%p|%p|IN_IGNORE\n", ctx->pattern, ctx->ptr));
1502
 
            if (ctx->ptr >= end
1503
 
                || !SRE_CHARSET(ctx->pattern+1,
1504
 
                                (SRE_CODE)state->lower(*ctx->ptr)))
1505
 
                RETURN_FAILURE;
1506
 
            ctx->pattern += ctx->pattern[0];
1507
 
            ctx->ptr++;
1508
 
            break;
1509
 
 
1510
 
        case SRE_OP_JUMP:
1511
 
        case SRE_OP_INFO:
1512
 
            /* jump forward */
1513
 
            /* <JUMP> <offset> */
1514
 
            TRACE(("|%p|%p|JUMP %d\n", ctx->pattern,
1515
 
                   ctx->ptr, ctx->pattern[0]));
1516
 
            ctx->pattern += ctx->pattern[0];
1517
 
            break;
1518
 
 
1519
 
        case SRE_OP_BRANCH:
1520
 
            /* alternation */
1521
 
            /* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
1522
 
            TRACE(("|%p|%p|BRANCH\n", ctx->pattern, ctx->ptr));
1523
 
            LASTMARK_SAVE();
1524
 
            ctx->u.rep = state->repeat;
1525
 
            if (ctx->u.rep)
1526
 
                MARK_PUSH(ctx->lastmark);
1527
 
            for (; ctx->pattern[0]; ctx->pattern += ctx->pattern[0]) {
1528
 
                if (ctx->pattern[1] == SRE_OP_LITERAL &&
1529
 
                    (ctx->ptr >= end ||
1530
 
                     (SRE_CODE) *ctx->ptr != ctx->pattern[2]))
1531
 
                    continue;
1532
 
                if (ctx->pattern[1] == SRE_OP_IN &&
1533
 
                    (ctx->ptr >= end ||
1534
 
                     !SRE_CHARSET(ctx->pattern + 3, (SRE_CODE) *ctx->ptr)))
1535
 
                    continue;
1536
 
                state->ptr = ctx->ptr;
1537
 
                DO_JUMP(JUMP_BRANCH, jump_branch, ctx->pattern+1);
1538
 
                if (ret) {
1539
 
                    if (ctx->u.rep)
1540
 
                        MARK_POP_DISCARD(ctx->lastmark);
1541
 
                    RETURN_ON_ERROR(ret);
1542
 
                    RETURN_SUCCESS;
1543
 
                }
1544
 
                if (ctx->u.rep)
1545
 
                    MARK_POP_KEEP(ctx->lastmark);
1546
 
                LASTMARK_RESTORE();
1547
 
            }
1548
 
            if (ctx->u.rep)
1549
 
                MARK_POP_DISCARD(ctx->lastmark);
1550
 
            RETURN_FAILURE;
1551
 
 
1552
 
        case SRE_OP_REPEAT_ONE:
1553
 
            /* match repeated sequence (maximizing regexp) */
1554
 
 
1555
 
            /* this operator only works if the repeated item is
1556
 
               exactly one character wide, and we're not already
1557
 
               collecting backtracking points.  for other cases,
1558
 
               use the MAX_REPEAT operator */
1559
 
 
1560
 
            /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
1561
 
 
1562
 
            TRACE(("|%p|%p|REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
1563
 
                   ctx->pattern[1], ctx->pattern[2]));
1564
 
 
1565
 
            if (ctx->ptr + ctx->pattern[1] > end)
1566
 
                RETURN_FAILURE; /* cannot match */
1567
 
 
1568
 
            state->ptr = ctx->ptr;
1569
 
 
1570
 
            ret = SRE_COUNT(state, ctx->pattern+3, ctx->pattern[2]);
1571
 
            RETURN_ON_ERROR(ret);
1572
 
            DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1573
 
            ctx->count = ret;
1574
 
            ctx->ptr += ctx->count;
1575
 
 
1576
 
            /* when we arrive here, count contains the number of
1577
 
               matches, and ctx->ptr points to the tail of the target
1578
 
               string.  check if the rest of the pattern matches,
1579
 
               and backtrack if not. */
1580
 
 
1581
 
            if (ctx->count < (Py_ssize_t) ctx->pattern[1])
1582
 
                RETURN_FAILURE;
1583
 
 
1584
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS) {
1585
 
                /* tail is empty.  we're finished */
1586
 
                state->ptr = ctx->ptr;
1587
 
                RETURN_SUCCESS;
1588
 
            }
1589
 
 
1590
 
            LASTMARK_SAVE();
1591
 
 
1592
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_LITERAL) {
1593
 
                /* tail starts with a literal. skip positions where
1594
 
                   the rest of the pattern cannot possibly match */
1595
 
                ctx->u.chr = ctx->pattern[ctx->pattern[0]+1];
1596
 
                for (;;) {
1597
 
                    while (ctx->count >= (Py_ssize_t) ctx->pattern[1] &&
1598
 
                           (ctx->ptr >= end || *ctx->ptr != ctx->u.chr)) {
1599
 
                        ctx->ptr--;
1600
 
                        ctx->count--;
1601
 
                    }
1602
 
                    if (ctx->count < (Py_ssize_t) ctx->pattern[1])
1603
 
                        break;
1604
 
                    state->ptr = ctx->ptr;
1605
 
                    DO_JUMP(JUMP_REPEAT_ONE_1, jump_repeat_one_1,
1606
 
                            ctx->pattern+ctx->pattern[0]);
1607
 
                    if (ret) {
1608
 
                        RETURN_ON_ERROR(ret);
1609
 
                        RETURN_SUCCESS;
1610
 
                    }
1611
 
 
1612
 
                    LASTMARK_RESTORE();
1613
 
 
1614
 
                    ctx->ptr--;
1615
 
                    ctx->count--;
1616
 
                }
1617
 
 
1618
 
            } else {
1619
 
                /* general case */
1620
 
                while (ctx->count >= (Py_ssize_t) ctx->pattern[1]) {
1621
 
                    state->ptr = ctx->ptr;
1622
 
                    DO_JUMP(JUMP_REPEAT_ONE_2, jump_repeat_one_2,
1623
 
                            ctx->pattern+ctx->pattern[0]);
1624
 
                    if (ret) {
1625
 
                        RETURN_ON_ERROR(ret);
1626
 
                        RETURN_SUCCESS;
1627
 
                    }
1628
 
                    ctx->ptr--;
1629
 
                    ctx->count--;
1630
 
                    LASTMARK_RESTORE();
1631
 
                }
1632
 
            }
1633
 
            RETURN_FAILURE;
1634
 
 
1635
 
        case SRE_OP_MIN_REPEAT_ONE:
1636
 
            /* match repeated sequence (minimizing regexp) */
1637
 
 
1638
 
            /* this operator only works if the repeated item is
1639
 
               exactly one character wide, and we're not already
1640
 
               collecting backtracking points.  for other cases,
1641
 
               use the MIN_REPEAT operator */
1642
 
 
1643
 
            /* <MIN_REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
1644
 
 
1645
 
            TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", ctx->pattern, ctx->ptr,
1646
 
                   ctx->pattern[1], ctx->pattern[2]));
1647
 
 
1648
 
            if (ctx->ptr + ctx->pattern[1] > end)
1649
 
                RETURN_FAILURE; /* cannot match */
1650
 
 
1651
 
            state->ptr = ctx->ptr;
1652
 
 
1653
 
            if (ctx->pattern[1] == 0)
1654
 
                ctx->count = 0;
1655
 
            else {
1656
 
                /* count using pattern min as the maximum */
1657
 
                ret = SRE_COUNT(state, ctx->pattern+3, ctx->pattern[1]);
1658
 
                RETURN_ON_ERROR(ret);
1659
 
                DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1660
 
                if (ret < (Py_ssize_t) ctx->pattern[1])
1661
 
                    /* didn't match minimum number of times */
1662
 
                    RETURN_FAILURE;
1663
 
                /* advance past minimum matches of repeat */
1664
 
                ctx->count = ret;
1665
 
                ctx->ptr += ctx->count;
1666
 
            }
1667
 
 
1668
 
            if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS) {
1669
 
                /* tail is empty.  we're finished */
1670
 
                state->ptr = ctx->ptr;
1671
 
                RETURN_SUCCESS;
1672
 
 
1673
 
            } else {
1674
 
                /* general case */
1675
 
                LASTMARK_SAVE();
1676
 
                while ((Py_ssize_t)ctx->pattern[2] == SRE_MAX_REPEAT
1677
 
                       || ctx->count <= (Py_ssize_t)ctx->pattern[2]) {
1678
 
                    state->ptr = ctx->ptr;
1679
 
                    DO_JUMP(JUMP_MIN_REPEAT_ONE,jump_min_repeat_one,
1680
 
                            ctx->pattern+ctx->pattern[0]);
1681
 
                    if (ret) {
1682
 
                        RETURN_ON_ERROR(ret);
1683
 
                        RETURN_SUCCESS;
1684
 
                    }
1685
 
                    state->ptr = ctx->ptr;
1686
 
                    ret = SRE_COUNT(state, ctx->pattern+3, 1);
1687
 
                    RETURN_ON_ERROR(ret);
1688
 
                    DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1689
 
                    if (ret == 0)
1690
 
                        break;
1691
 
                    assert(ret == 1);
1692
 
                    ctx->ptr++;
1693
 
                    ctx->count++;
1694
 
                    LASTMARK_RESTORE();
1695
 
                }
1696
 
            }
1697
 
            RETURN_FAILURE;
1698
 
 
1699
 
        case SRE_OP_REPEAT:
1700
 
            /* create repeat context.  all the hard work is done
1701
 
               by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */
1702
 
            /* <REPEAT> <skip> <1=min> <2=max> item <UNTIL> tail */
1703
 
            TRACE(("|%p|%p|REPEAT %d %d\n", ctx->pattern, ctx->ptr,
1704
 
                   ctx->pattern[1], ctx->pattern[2]));
1705
 
 
1706
 
            /* install new repeat context */
1707
 
            ctx->u.rep = (SRE_REPEAT*) PyObject_MALLOC(sizeof(*ctx->u.rep));
1708
 
            if (!ctx->u.rep) {
1709
 
                PyErr_NoMemory();
1710
 
                RETURN_FAILURE;
1711
 
            }
1712
 
            ctx->u.rep->count = -1;
1713
 
            ctx->u.rep->pattern = ctx->pattern;
1714
 
            ctx->u.rep->prev = state->repeat;
1715
 
            ctx->u.rep->last_ptr = NULL;
1716
 
            state->repeat = ctx->u.rep;
1717
 
 
1718
 
            state->ptr = ctx->ptr;
1719
 
            DO_JUMP(JUMP_REPEAT, jump_repeat, ctx->pattern+ctx->pattern[0]);
1720
 
            state->repeat = ctx->u.rep->prev;
1721
 
            PyObject_FREE(ctx->u.rep);
1722
 
 
1723
 
            if (ret) {
1724
 
                RETURN_ON_ERROR(ret);
1725
 
                RETURN_SUCCESS;
1726
 
            }
1727
 
            RETURN_FAILURE;
1728
 
 
1729
 
        case SRE_OP_MAX_UNTIL:
1730
 
            /* maximizing repeat */
1731
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
1732
 
 
1733
 
            /* FIXME: we probably need to deal with zero-width
1734
 
               matches in here... */
1735
 
 
1736
 
            ctx->u.rep = state->repeat;
1737
 
            if (!ctx->u.rep)
1738
 
                RETURN_ERROR(SRE_ERROR_STATE);
1739
 
 
1740
 
            state->ptr = ctx->ptr;
1741
 
 
1742
 
            ctx->count = ctx->u.rep->count+1;
1743
 
 
1744
 
            TRACE(("|%p|%p|MAX_UNTIL %d\n", ctx->pattern,
1745
 
                   ctx->ptr, ctx->count));
1746
 
 
1747
 
            if (ctx->count < ctx->u.rep->pattern[1]) {
1748
 
                /* not enough matches */
1749
 
                ctx->u.rep->count = ctx->count;
1750
 
                DO_JUMP(JUMP_MAX_UNTIL_1, jump_max_until_1,
1751
 
                        ctx->u.rep->pattern+3);
1752
 
                if (ret) {
1753
 
                    RETURN_ON_ERROR(ret);
1754
 
                    RETURN_SUCCESS;
1755
 
                }
1756
 
                ctx->u.rep->count = ctx->count-1;
1757
 
                state->ptr = ctx->ptr;
1758
 
                RETURN_FAILURE;
1759
 
            }
1760
 
 
1761
 
            if ((ctx->count < ctx->u.rep->pattern[2] ||
1762
 
                ctx->u.rep->pattern[2] == SRE_MAX_REPEAT) &&
1763
 
                state->ptr != ctx->u.rep->last_ptr) {
1764
 
                /* we may have enough matches, but if we can
1765
 
                   match another item, do so */
1766
 
                ctx->u.rep->count = ctx->count;
1767
 
                LASTMARK_SAVE();
1768
 
                MARK_PUSH(ctx->lastmark);
1769
 
                /* zero-width match protection */
1770
 
                DATA_PUSH(&ctx->u.rep->last_ptr);
1771
 
                ctx->u.rep->last_ptr = state->ptr;
1772
 
                DO_JUMP(JUMP_MAX_UNTIL_2, jump_max_until_2,
1773
 
                        ctx->u.rep->pattern+3);
1774
 
                DATA_POP(&ctx->u.rep->last_ptr);
1775
 
                if (ret) {
1776
 
                    MARK_POP_DISCARD(ctx->lastmark);
1777
 
                    RETURN_ON_ERROR(ret);
1778
 
                    RETURN_SUCCESS;
1779
 
                }
1780
 
                MARK_POP(ctx->lastmark);
1781
 
                LASTMARK_RESTORE();
1782
 
                ctx->u.rep->count = ctx->count-1;
1783
 
                state->ptr = ctx->ptr;
1784
 
            }
1785
 
 
1786
 
            /* cannot match more repeated items here.  make sure the
1787
 
               tail matches */
1788
 
            state->repeat = ctx->u.rep->prev;
1789
 
            DO_JUMP(JUMP_MAX_UNTIL_3, jump_max_until_3, ctx->pattern);
1790
 
            RETURN_ON_SUCCESS(ret);
1791
 
            state->repeat = ctx->u.rep;
1792
 
            state->ptr = ctx->ptr;
1793
 
            RETURN_FAILURE;
1794
 
 
1795
 
        case SRE_OP_MIN_UNTIL:
1796
 
            /* minimizing repeat */
1797
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
1798
 
 
1799
 
            ctx->u.rep = state->repeat;
1800
 
            if (!ctx->u.rep)
1801
 
                RETURN_ERROR(SRE_ERROR_STATE);
1802
 
 
1803
 
            state->ptr = ctx->ptr;
1804
 
 
1805
 
            ctx->count = ctx->u.rep->count+1;
1806
 
 
1807
 
            TRACE(("|%p|%p|MIN_UNTIL %d %p\n", ctx->pattern,
1808
 
                   ctx->ptr, ctx->count, ctx->u.rep->pattern));
1809
 
 
1810
 
            if (ctx->count < ctx->u.rep->pattern[1]) {
1811
 
                /* not enough matches */
1812
 
                ctx->u.rep->count = ctx->count;
1813
 
                DO_JUMP(JUMP_MIN_UNTIL_1, jump_min_until_1,
1814
 
                        ctx->u.rep->pattern+3);
1815
 
                if (ret) {
1816
 
                    RETURN_ON_ERROR(ret);
1817
 
                    RETURN_SUCCESS;
1818
 
                }
1819
 
                ctx->u.rep->count = ctx->count-1;
1820
 
                state->ptr = ctx->ptr;
1821
 
                RETURN_FAILURE;
1822
 
            }
1823
 
 
1824
 
            LASTMARK_SAVE();
1825
 
 
1826
 
            /* see if the tail matches */
1827
 
            state->repeat = ctx->u.rep->prev;
1828
 
            DO_JUMP(JUMP_MIN_UNTIL_2, jump_min_until_2, ctx->pattern);
1829
 
            if (ret) {
1830
 
                RETURN_ON_ERROR(ret);
1831
 
                RETURN_SUCCESS;
1832
 
            }
1833
 
 
1834
 
            state->repeat = ctx->u.rep;
1835
 
            state->ptr = ctx->ptr;
1836
 
 
1837
 
            LASTMARK_RESTORE();
1838
 
 
1839
 
            if (ctx->count >= ctx->u.rep->pattern[2]
1840
 
                && ctx->u.rep->pattern[2] != SRE_MAX_REPEAT)
1841
 
                RETURN_FAILURE;
1842
 
 
1843
 
            ctx->u.rep->count = ctx->count;
1844
 
            DO_JUMP(JUMP_MIN_UNTIL_3,jump_min_until_3,
1845
 
                    ctx->u.rep->pattern+3);
1846
 
            if (ret) {
1847
 
                RETURN_ON_ERROR(ret);
1848
 
                RETURN_SUCCESS;
1849
 
            }
1850
 
            ctx->u.rep->count = ctx->count-1;
1851
 
            state->ptr = ctx->ptr;
1852
 
            RETURN_FAILURE;
1853
 
 
1854
 
        case SRE_OP_GROUPREF:
1855
 
            /* match backreference */
1856
 
            TRACE(("|%p|%p|GROUPREF %d\n", ctx->pattern,
1857
 
                   ctx->ptr, ctx->pattern[0]));
1858
 
            i = ctx->pattern[0];
1859
 
            {
1860
 
                Py_ssize_t groupref = i+i;
1861
 
                if (groupref >= state->lastmark) {
1862
 
                    RETURN_FAILURE;
1863
 
                } else {
1864
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1865
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1866
 
                    if (!p || !e || e < p)
1867
 
                        RETURN_FAILURE;
1868
 
                    while (p < e) {
1869
 
                        if (ctx->ptr >= end || *ctx->ptr != *p)
1870
 
                            RETURN_FAILURE;
1871
 
                        p++; ctx->ptr++;
1872
 
                    }
1873
 
                }
1874
 
            }
1875
 
            ctx->pattern++;
1876
 
            break;
1877
 
 
1878
 
        case SRE_OP_GROUPREF_IGNORE:
1879
 
            /* match backreference */
1880
 
            TRACE(("|%p|%p|GROUPREF_IGNORE %d\n", ctx->pattern,
1881
 
                   ctx->ptr, ctx->pattern[0]));
1882
 
            i = ctx->pattern[0];
1883
 
            {
1884
 
                Py_ssize_t groupref = i+i;
1885
 
                if (groupref >= state->lastmark) {
1886
 
                    RETURN_FAILURE;
1887
 
                } else {
1888
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1889
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1890
 
                    if (!p || !e || e < p)
1891
 
                        RETURN_FAILURE;
1892
 
                    while (p < e) {
1893
 
                        if (ctx->ptr >= end ||
1894
 
                            state->lower(*ctx->ptr) != state->lower(*p))
1895
 
                            RETURN_FAILURE;
1896
 
                        p++; ctx->ptr++;
1897
 
                    }
1898
 
                }
1899
 
            }
1900
 
            ctx->pattern++;
1901
 
            break;
1902
 
 
1903
 
        case SRE_OP_GROUPREF_EXISTS:
1904
 
            TRACE(("|%p|%p|GROUPREF_EXISTS %d\n", ctx->pattern,
1905
 
                   ctx->ptr, ctx->pattern[0]));
1906
 
            /* <GROUPREF_EXISTS> <group> <skip> codeyes <JUMP> codeno ... */
1907
 
            i = ctx->pattern[0];
1908
 
            {
1909
 
                Py_ssize_t groupref = i+i;
1910
 
                if (groupref >= state->lastmark) {
1911
 
                    ctx->pattern += ctx->pattern[1];
1912
 
                    break;
1913
 
                } else {
1914
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
1915
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
1916
 
                    if (!p || !e || e < p) {
1917
 
                        ctx->pattern += ctx->pattern[1];
1918
 
                        break;
1919
 
                    }
1920
 
                }
1921
 
            }
1922
 
            ctx->pattern += 2;
1923
 
            break;
1924
 
 
1925
 
        case SRE_OP_ASSERT:
1926
 
            /* assert subpattern */
1927
 
            /* <ASSERT> <skip> <back> <pattern> */
1928
 
            TRACE(("|%p|%p|ASSERT %d\n", ctx->pattern,
1929
 
                   ctx->ptr, ctx->pattern[1]));
1930
 
            state->ptr = ctx->ptr - ctx->pattern[1];
1931
 
            if (state->ptr < state->beginning)
1932
 
                RETURN_FAILURE;
1933
 
            DO_JUMP(JUMP_ASSERT, jump_assert, ctx->pattern+2);
1934
 
            RETURN_ON_FAILURE(ret);
1935
 
            ctx->pattern += ctx->pattern[0];
1936
 
            break;
1937
 
 
1938
 
        case SRE_OP_ASSERT_NOT:
1939
 
            /* assert not subpattern */
1940
 
            /* <ASSERT_NOT> <skip> <back> <pattern> */
1941
 
            TRACE(("|%p|%p|ASSERT_NOT %d\n", ctx->pattern,
1942
 
                   ctx->ptr, ctx->pattern[1]));
1943
 
            state->ptr = ctx->ptr - ctx->pattern[1];
1944
 
            if (state->ptr >= state->beginning) {
1945
 
                DO_JUMP(JUMP_ASSERT_NOT, jump_assert_not, ctx->pattern+2);
1946
 
                if (ret) {
1947
 
                    RETURN_ON_ERROR(ret);
1948
 
                    RETURN_FAILURE;
1949
 
                }
1950
 
            }
1951
 
            ctx->pattern += ctx->pattern[0];
1952
 
            break;
1953
 
 
1954
 
        case SRE_OP_FAILURE:
1955
 
            /* immediate failure */
1956
 
            TRACE(("|%p|%p|FAILURE\n", ctx->pattern, ctx->ptr));
1957
 
            RETURN_FAILURE;
1958
 
 
1959
 
        default:
1960
 
            TRACE(("|%p|%p|UNKNOWN %d\n", ctx->pattern, ctx->ptr,
1961
 
                   ctx->pattern[-1]));
1962
 
            RETURN_ERROR(SRE_ERROR_ILLEGAL);
1963
 
        }
1964
 
    }
1965
 
 
1966
 
exit:
1967
 
    ctx_pos = ctx->last_ctx_pos;
1968
 
    jump = ctx->jump;
1969
 
    DATA_POP_DISCARD(ctx);
1970
 
    if (ctx_pos == -1)
1971
 
        return ret;
1972
 
    DATA_LOOKUP_AT(SRE_MATCH_CONTEXT, ctx, ctx_pos);
1973
 
 
1974
 
    switch (jump) {
1975
 
        case JUMP_MAX_UNTIL_2:
1976
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_2\n", ctx->pattern, ctx->ptr));
1977
 
            goto jump_max_until_2;
1978
 
        case JUMP_MAX_UNTIL_3:
1979
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_3\n", ctx->pattern, ctx->ptr));
1980
 
            goto jump_max_until_3;
1981
 
        case JUMP_MIN_UNTIL_2:
1982
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_2\n", ctx->pattern, ctx->ptr));
1983
 
            goto jump_min_until_2;
1984
 
        case JUMP_MIN_UNTIL_3:
1985
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_3\n", ctx->pattern, ctx->ptr));
1986
 
            goto jump_min_until_3;
1987
 
        case JUMP_BRANCH:
1988
 
            TRACE(("|%p|%p|JUMP_BRANCH\n", ctx->pattern, ctx->ptr));
1989
 
            goto jump_branch;
1990
 
        case JUMP_MAX_UNTIL_1:
1991
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_1\n", ctx->pattern, ctx->ptr));
1992
 
            goto jump_max_until_1;
1993
 
        case JUMP_MIN_UNTIL_1:
1994
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_1\n", ctx->pattern, ctx->ptr));
1995
 
            goto jump_min_until_1;
1996
 
        case JUMP_REPEAT:
1997
 
            TRACE(("|%p|%p|JUMP_REPEAT\n", ctx->pattern, ctx->ptr));
1998
 
            goto jump_repeat;
1999
 
        case JUMP_REPEAT_ONE_1:
2000
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_1\n", ctx->pattern, ctx->ptr));
2001
 
            goto jump_repeat_one_1;
2002
 
        case JUMP_REPEAT_ONE_2:
2003
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_2\n", ctx->pattern, ctx->ptr));
2004
 
            goto jump_repeat_one_2;
2005
 
        case JUMP_MIN_REPEAT_ONE:
2006
 
            TRACE(("|%p|%p|JUMP_MIN_REPEAT_ONE\n", ctx->pattern, ctx->ptr));
2007
 
            goto jump_min_repeat_one;
2008
 
        case JUMP_ASSERT:
2009
 
            TRACE(("|%p|%p|JUMP_ASSERT\n", ctx->pattern, ctx->ptr));
2010
 
            goto jump_assert;
2011
 
        case JUMP_ASSERT_NOT:
2012
 
            TRACE(("|%p|%p|JUMP_ASSERT_NOT\n", ctx->pattern, ctx->ptr));
2013
 
            goto jump_assert_not;
2014
 
        case JUMP_NONE:
2015
 
            TRACE(("|%p|%p|RETURN %d\n", ctx->pattern, ctx->ptr, ret));
2016
 
            break;
2017
 
    }
2018
 
 
2019
 
    return ret; /* should never get here */
2020
 
}
2021
 
 
2022
 
#else /* REMOVE_SRE_MATCH_MACROS */
 
1214
/* TODO: Look into making alloc_pos a local varaible as it should really be a return value for the ALLOC functions. */
 
1215
/* TODO: Look into removing op_code as it is only used when a bad op code is passed and only for debugging */
2023
1216
typedef struct {
2024
1217
    SRE_CHAR *end; /* Pointer to the end of the input state->ptr */
2025
1218
    Py_ssize_t alloc_pos; /* Offset in state->data_state of newly */
2341
1534
    TRACE(("|%p|%p|FAILURE\n", self->ctx->pattern, self->ctx->ptr));
2342
1535
 
2343
1536
    return SRE_MATCH_RETURN_FAILURE(self);
2344
 
    /* TODO: Go to exit */
2345
1537
}
2346
1538
 
2347
1539
Py_LOCAL_INLINE(Py_ssize_t)
2355
1547
    state->ptr = self->ctx->ptr;
2356
1548
 
2357
1549
    return SRE_MATCH_RETURN_SUCCESS(self);
2358
 
    /* TODO: Go to exit */
2359
1550
}
2360
1551
 
2361
1552
Py_LOCAL_INLINE(Py_ssize_t)
2368
1559
    if (self->ctx->ptr >= self->end ||
2369
1560
        sre_category_is_linebreak(self->ctx->ptr[0])) {
2370
1561
        return SRE_MATCH_RETURN_FAILURE(self);
2371
 
        /* TODO: Go to exit */
2372
1562
    }
2373
1563
 
2374
1564
    /* Move to next Character */
2386
1576
 
2387
1577
    if (self->ctx->ptr >= self->end) {
2388
1578
        return SRE_MATCH_RETURN_FAILURE(self);
2389
 
        /* TODO: Go to exit */
2390
1579
    }
2391
1580
 
2392
1581
    /* Move to next Character */
2395
1584
    return SRE_MATCH_PASS;
2396
1585
}
2397
1586
 
2398
 
/* TODO: SRE_MATCH_ON_ASSERT */
2399
 
/* TODO: SRE_MATCH_ON_ASSERT_NOT */
 
1587
Py_LOCAL_INLINE(Py_ssize_t)
 
1588
SRE_MATCH_ON_ASSERT(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
1589
{
 
1590
    /* assert subpattern */
 
1591
    /* <ASSERT> <skip> <back> <pattern> <SUCCESS> tail */
 
1592
    /* <skip> points to tail */ 
 
1593
    /* <back> is 0 for look-ahead */
 
1594
    /* skip is not used */
 
1595
    int back = (int)self->ctx->pattern[1];
 
1596
    SRE_CODE *pattern = &self->ctx->pattern[2];
 
1597
 
 
1598
    TRACE(("|%p|%p|ASSERT %d\n", self->ctx->pattern, self->ctx->ptr,
 
1599
           back));
 
1600
 
 
1601
    /* Roll back the input stream by back */
 
1602
    state->ptr = self->ctx->ptr - back;
 
1603
 
 
1604
    /* Did we roll past the beginning? */
 
1605
    if (state->ptr < state->beginning) {
 
1606
        return SRE_MATCH_RETURN_FAILURE(self);
 
1607
    }
 
1608
 
 
1609
    /* Examine the input stream in the region represented by back */
 
1610
    /* Move the match pattern to the pattern parameter of the Assert */
 
1611
    /* and create a new parse sub-context */
 
1612
    /* Go to SRE_MATCH_ON_JUMP_ASSERT when stack is popped */
 
1613
    return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state, JUMP_ASSERT,
 
1614
                                              pattern);
 
1615
}
 
1616
 
 
1617
Py_LOCAL_INLINE(Py_ssize_t)
 
1618
SRE_MATCH_ON_ASSERT_NOT(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
1619
{
 
1620
    /* assert not subpattern */
 
1621
    /* <ASSERT_NOT> <skip> <back> <pattern> <SUCCESS> tail */
 
1622
    /* <skip> points to tail */ 
 
1623
    /* <back> is 0 for look-ahead */
 
1624
    int skip = (int)self->ctx->pattern[0];
 
1625
    int back = (int)self->ctx->pattern[1];
 
1626
    SRE_CODE *pattern = &self->ctx->pattern[2];
 
1627
 
 
1628
    TRACE(("|%p|%p|ASSERT_NOT %d\n", self->ctx->pattern, self->ctx->ptr,
 
1629
           back));
 
1630
 
 
1631
    /* Roll back the input stream by back */
 
1632
    state->ptr = self->ctx->ptr - back;
 
1633
 
 
1634
    /* Did we roll past the beginning? */
 
1635
    if (state->ptr >= state->beginning) {
 
1636
        /* Examine the input stream in the region represented by back */
 
1637
        /* Move the match pattern to the pattern parameter of the Not */
 
1638
        /* Assert and create a new parse sub-context */
 
1639
        /* Go to SRE_MATCH_ON_JUMP_ASSERT_NOT when stack is popped */
 
1640
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
1641
                                                  JUMP_ASSERT_NOT,
 
1642
                                                  pattern);
 
1643
    }
 
1644
    else {
 
1645
        /* Advance Pattern to Next Op Code */
 
1646
        self->ctx->pattern += skip;
 
1647
 
 
1648
        /* Successful Return */
 
1649
        return SRE_MATCH_PASS;
 
1650
    }
 
1651
}
2400
1652
 
2401
1653
Py_LOCAL_INLINE(Py_ssize_t)
2402
1654
SRE_MATCH_ON_AT(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
2411
1663
    /* self->ctx->ptr and if it is not where code indicates, fail. */
2412
1664
    if (!SRE_AT(state, self->ctx->ptr, code)) {
2413
1665
        return SRE_MATCH_RETURN_FAILURE(self);
2414
 
        /* TODO: Go to exit */
2415
1666
    }
2416
1667
 
2417
1668
    /* Move to next op code */
2424
1675
SRE_MATCH_ON_BRANCH(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
2425
1676
{
2426
1677
    /* alternation */
2427
 
    /* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
 
1678
    /* <BRANCH> <0=skip> code <JUMP> <skip-end> */
 
1679
    /*           (<skip> code <JUMP> <skip-end>)* <FAILURE> tail */
 
1680
    /* Each <skip> points to the one passed the next <skip-end>, */
 
1681
    /* i.e. the next <skip> or <FAILURE> if the last one */
 
1682
    /* Each <skip-end> always points to the end of the Branching, */
 
1683
    /* i.e. tail */
2428
1684
    int skip = (int)self->ctx->pattern[0];
 
1685
    SRE_CODE *p_next_op = &self->ctx->pattern[1];
 
1686
    SRE_CHAR literal = (SRE_CHAR)self->ctx->pattern[2];
 
1687
    SRE_CODE *set = &self->ctx->pattern[3];
2429
1688
 
2430
1689
    TRACE(("|%p|%p|BRANCH\n", self->ctx->pattern, self->ctx->ptr));
2431
1690
 
 
1691
    /* Save the state's current Mark */
2432
1692
    SRE_MATCH_LASTMARK_SAVE(self, state);
2433
1693
 
 
1694
    /* Save the current Repeat Context in the current Match Context */
2434
1695
    self->ctx->u.rep = state->repeat;
2435
1696
 
 
1697
    /* Verfiy that there is a current Repeat Context */
2436
1698
    if (self->ctx->u.rep) {
 
1699
        /* There is a prior Repeat context; save the current */
 
1700
        /* Context's previous Mark in the current State */
2437
1701
        SRE_MATCH_MARK_PUSH(self, state, self->ctx->lastmark);
2438
1702
    }
2439
1703
 
2440
 
    for (; self->ctx->pattern[0];
2441
 
         self->ctx->pattern += self->ctx->pattern[0]) {
2442
 
        if (self->ctx->pattern[1] == SRE_OP_LITERAL &&
2443
 
            (self->ctx->ptr >= self->end ||
2444
 
             (SRE_CODE)*self->ctx->ptr != self->ctx->pattern[2])) {
2445
 
             /* Literal Miss-Match, continue */
2446
 
            continue;
2447
 
        }
2448
 
 
2449
 
        else if (self->ctx->pattern[1] == SRE_OP_IN &&
2450
 
                 (self->ctx->ptr >= self->end ||
2451
 
                  !SRE_CHARSET(self->ctx->pattern + 3,
2452
 
                               (SRE_CODE)*self->ctx->ptr))) {
2453
 
             /* Character Class Miss-Match, continue */
2454
 
            continue;
2455
 
        }
2456
 
 
 
1704
    /* Skip simple match cases; e.g. Literal and In op codes */
 
1705
    /* If skip is the <FAILURE> op code, it will be zero and the */
 
1706
    /* loop will exit */
 
1707
    while (skip &&
 
1708
 
 
1709
            /* Check for Literal Miss-Match */
 
1710
           ((*p_next_op == SRE_OP_LITERAL &&
 
1711
              /* Check for End of Input Stream */
 
1712
             (self->ctx->ptr >= self->end ||
 
1713
              /* Check for Literal Miss-match */
 
1714
              (SRE_CODE)*self->ctx->ptr != literal)) ||
 
1715
 
 
1716
            /* Check for Character Class Miss-Match */
 
1717
            (*p_next_op == SRE_OP_IN &&
 
1718
              /* Check for End of Input Stream */
 
1719
             (self->ctx->ptr >= self->end ||
 
1720
              /* Check for Character not in Class */
 
1721
              !SRE_CHARSET(set, (SRE_CODE)*self->ctx->ptr))))) {
 
1722
 
 
1723
        /* This branch option will not match */
 
1724
        /* Increment the pattern to the next branch point */
 
1725
        self->ctx->pattern += skip;
 
1726
 
 
1727
        /* Update the named aliases list */
 
1728
        skip = (int)self->ctx->pattern[0];
 
1729
        p_next_op = &self->ctx->pattern[1];
 
1730
        literal = (SRE_CHAR)self->ctx->pattern[2];
 
1731
        set = &self->ctx->pattern[3];
 
1732
    }
 
1733
 
 
1734
    /* If skip is the <FAILURE> op code, it will be zero and the */
 
1735
    /* pseudo-recursion will be skipped. */
 
1736
    if (skip) {
 
1737
        /* Set the current input buffer position to that stored in */
 
1738
        /* the Current Context */
2457
1739
        state->ptr = self->ctx->ptr;
2458
1740
 
 
1741
        /* Move the match pattern to the next code block's op code */
 
1742
        /* and create a new parse sub-context */
 
1743
        /* Go to SRE_MATCH_ON_JUMP_BRANCH when stack is popped */
2459
1744
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
2460
1745
                                                  JUMP_BRANCH,
2461
 
                                                  self->ctx->pattern +
2462
 
                                                  1);
2463
 
    }
2464
 
 
2465
 
    if (self->ctx->u.rep) {
2466
 
        SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
2467
 
    }
2468
 
 
2469
 
    return SRE_MATCH_RETURN_FAILURE(self);
2470
 
    /* TODO: Go to exit */
 
1746
                                                  p_next_op);
 
1747
    }
 
1748
    else {
 
1749
        /* There are no more codes sections in the Branch, and none */
 
1750
        /* of the previous ones matched, so fail and pop stack. */
 
1751
 
 
1752
        if (self->ctx->u.rep) {
 
1753
            /* A mark was left in the Context's Repeat Context; */
 
1754
            /* discard it */
 
1755
            SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
 
1756
        }
 
1757
 
 
1758
        /* Fail and Pop Context */
 
1759
        return SRE_MATCH_RETURN_FAILURE(self);
 
1760
    }
2471
1761
}
2472
1762
 
2473
1763
/* TODO: SRE_MATCH_ON_CALL */
2483
1773
           code));
2484
1774
 
2485
1775
    /* If not at the end of input, check the next character to see if */
2486
 
    /* it is in ther given character class */
 
1776
    /* it is in the given Character Class */
2487
1777
    if (self->ctx->ptr >= self->end ||
2488
1778
        !sre_category(code, self->ctx->ptr[0])) {
 
1779
 
 
1780
        /* Failed to match; Pop Context */
2489
1781
        return SRE_MATCH_RETURN_FAILURE(self);
2490
 
        /* TODO: Go to exit */
2491
1782
    }
2492
1783
 
2493
1784
    /* Move to next Op Code and Character */
2499
1790
 
2500
1791
/* TODO: SRE_MATCH_ON_CHARSET */
2501
1792
/* TODO: SRE_MATCH_ON_BIGCHARSET */
2502
 
/* TODO: SRE_MATCH_ON_GROUPREF */
2503
 
/* TODO: SRE_MATCH_ON_GROUPREF_EXISTS */
2504
 
/* TODO: SRE_MATCH_ON_GROUPREF_IGNORE */
 
1793
 
 
1794
Py_LOCAL_INLINE(Py_ssize_t)
 
1795
SRE_MATCH_ON_GROUPREF(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
1796
{
 
1797
    /* match backreference */
 
1798
 
 
1799
    /* <GROUPREF> <group> ... */
 
1800
    Py_ssize_t group = (Py_ssize_t)self->ctx->pattern[0];
 
1801
 
 
1802
    /* For every group ID, there are 2 grouprefs, one for beginning, */
 
1803
    /* one for end; so groupref is twice group */
 
1804
    Py_ssize_t groupref = group + group;
 
1805
 
 
1806
    TRACE(("|%p|%p|GROUPREF %d\n", self->ctx->pattern, self->ctx->ptr,
 
1807
           group));
 
1808
 
 
1809
    /* Check if the groupref is in the valid range */
 
1810
    if (groupref >= state->lastmark) {
 
1811
        /* Failed to Match; Pop Stack */
 
1812
        return SRE_MATCH_RETURN_FAILURE(self);
 
1813
    }
 
1814
    else {
 
1815
        /* Get the beginning and end of the Group captured from the */
 
1816
        /* Input Stream */
 
1817
 
 
1818
        SRE_CHAR *b = (SRE_CHAR *)state->mark[groupref];
 
1819
        /* b is the beginning position in the Input Stream of the */
 
1820
        /*   previously matched group */
 
1821
 
 
1822
        SRE_CHAR *e = (SRE_CHAR *)state->mark[groupref + 1];
 
1823
        /* e is the ending position in the Input Stream of the */
 
1824
        /*   previously matched group */
 
1825
 
 
1826
        /* Verify that the beginning and ending pointers are valid */
 
1827
        /* and that the beginning occurs before the ending */
 
1828
        if (!b || !e || e < b) {
 
1829
            /* Failed to Match; Pop Stack */
 
1830
            return SRE_MATCH_RETURN_FAILURE(self);
 
1831
        }
 
1832
 
 
1833
        else {
 
1834
            /* For each matched character of the corresponding group: */
 
1835
            while (b < e) {
 
1836
                /* Check it against the current Input Stream to */
 
1837
                /* verify that it matches */
 
1838
                /* Stop if the Input Stream is at its end */
 
1839
                if (self->ctx->ptr >= self->end ||
 
1840
                    *self->ctx->ptr != *b) {
 
1841
 
 
1842
                    /* Failed to Match; Pop Stack */
 
1843
                    return SRE_MATCH_RETURN_FAILURE(self);
 
1844
                }
 
1845
 
 
1846
                /* Increment the group match reference */
 
1847
                b++;
 
1848
 
 
1849
                /* Increment the Input Stream */
 
1850
                self->ctx->ptr++;
 
1851
            }
 
1852
        }
 
1853
    }
 
1854
 
 
1855
    /* Move to next Op Code */
 
1856
    self->ctx->pattern++;
 
1857
 
 
1858
    return SRE_MATCH_PASS;
 
1859
}
 
1860
 
 
1861
Py_LOCAL_INLINE(Py_ssize_t)
 
1862
SRE_MATCH_ON_GROUPREF_EXISTS(SRE_MATCH_GLOBAL_CONTEXT *self,
 
1863
                             SRE_STATE *state)
 
1864
{
 
1865
    /* Match codeyes if group matched, otherwise match codeno */
 
1866
 
 
1867
    /* <GROUPREF_EXISTS> <group> <skipyes> codeyes (<JUMP> <skipno> */
 
1868
    /* codeno)? tail */
 
1869
    /* <skipyes> points to codeno, one after the <skipno>, if codeno */
 
1870
    /* exists, otherwise to tail */
 
1871
    /* <skipno> points to tail */
 
1872
    /* Note: because <skipyes> is the SECOND parameter to */
 
1873
    /* <GROUPREF_EXISTS>, it contains one more than its proper offset */
 
1874
    /* from its position and is thus relative to the current value of */
 
1875
    /* self->ctx->pattern */
 
1876
    Py_ssize_t group = (Py_ssize_t)self->ctx->pattern[0];
 
1877
    int skipyes = (int)self->ctx->pattern[1];
 
1878
 
 
1879
    /* For every group ID, there are 2 grouprefs, one for beginning, */
 
1880
    /* one for end; so groupref is twice group */
 
1881
    Py_ssize_t groupref = group + group;
 
1882
 
 
1883
    TRACE(("|%p|%p|GROUPREF_EXISTS %d\n", self->ctx->pattern,
 
1884
           self->ctx->ptr, group));
 
1885
 
 
1886
    /* Check if the groupref is in the valid range */
 
1887
    if (groupref >= state->lastmark) {
 
1888
        /* Skip the codeyes and go directly to codeno */
 
1889
        self->ctx->pattern += skipyes;
 
1890
 
 
1891
        /* Continue to codeno */
 
1892
        return SRE_MATCH_PASS;
 
1893
    }
 
1894
 
 
1895
    else {
 
1896
        /* Check to see if the indicated groupref has previously been */
 
1897
        /* captured */
 
1898
 
 
1899
        SRE_CHAR *b = (SRE_CHAR *)state->mark[groupref];
 
1900
        /* b is the beginning position in the Input Stream of the */
 
1901
        /*   previously matched group */
 
1902
 
 
1903
        SRE_CHAR *e = (SRE_CHAR *)state->mark[groupref + 1];
 
1904
        /* e is the ending position in the Input Stream of the */
 
1905
        /*   previously matched group */
 
1906
 
 
1907
        /* Verify that the beginning and ending pointers are valid */
 
1908
        /* and that the beginning occurs before the ending */
 
1909
        if (!b || !e || e < b) {
 
1910
            /* Skip the codeyes and go directly to codeno */
 
1911
            self->ctx->pattern += skipyes;
 
1912
 
 
1913
            /* Continue to codeno */
 
1914
            return SRE_MATCH_PASS;
 
1915
        }
 
1916
    }
 
1917
 
 
1918
    /* Move to next Op Code, i.e. codeyes (skipping the 2 parameters) */
 
1919
    self->ctx->pattern += 2;
 
1920
 
 
1921
    return SRE_MATCH_PASS;
 
1922
}
 
1923
 
 
1924
Py_LOCAL_INLINE(Py_ssize_t)
 
1925
SRE_MATCH_ON_GROUPREF_IGNORE(SRE_MATCH_GLOBAL_CONTEXT *self,
 
1926
                             SRE_STATE *state)
 
1927
{
 
1928
    /* match backreference, ignoring case */
 
1929
 
 
1930
    /* <GROUPREF_IGNORE> <group> ... */
 
1931
    Py_ssize_t group = (Py_ssize_t)self->ctx->pattern[0];
 
1932
 
 
1933
    /* For every group ID, there are 2 grouprefs, one for beginning, */
 
1934
    /* one for end; so groupref is twice group */
 
1935
    Py_ssize_t groupref = group + group;
 
1936
 
 
1937
    TRACE(("|%p|%p|GROUPREF_IGNORE %d\n", self->ctx->pattern,
 
1938
           self->ctx->ptr, group));
 
1939
 
 
1940
    /* Check if the groupref is in the valid range */
 
1941
    if (groupref >= state->lastmark) {
 
1942
        /* Failed to Match; Pop Stack */
 
1943
        return SRE_MATCH_RETURN_FAILURE(self);
 
1944
    }
 
1945
    else {
 
1946
        /* Get the beginning and end of the Group captured from the */
 
1947
        /* Input Stream */
 
1948
 
 
1949
        SRE_CHAR *b = (SRE_CHAR *)state->mark[groupref];
 
1950
        /* b is the beginning position in the Input Stream of the */
 
1951
        /*   previously matched group */
 
1952
 
 
1953
        SRE_CHAR *e = (SRE_CHAR *)state->mark[groupref + 1];
 
1954
        /* e is the ending position in the Input Stream of the */
 
1955
        /*   previously matched group */
 
1956
 
 
1957
        /* Verify that the beginning and ending pointers are valid */
 
1958
        /* and that the beginning occurs before the ending */
 
1959
        if (!b || !e || e < b) {
 
1960
            /* Failed to Match; Pop Stack */
 
1961
            return SRE_MATCH_RETURN_FAILURE(self);
 
1962
        }
 
1963
 
 
1964
        else {
 
1965
            /* For each matched character of the corresponding group: */
 
1966
            while (b < e) {
 
1967
                /* Check it against the current Input Stream to */
 
1968
                /* verify that it matches case-insensitvily */
 
1969
                /* Stop if the Input Stream is at its end */
 
1970
                if (self->ctx->ptr >= self->end ||
 
1971
                    state->lower(*self->ctx->ptr) != state->lower(*b)) {
 
1972
 
 
1973
                    /* Failed to Match; Pop Stack */
 
1974
                    return SRE_MATCH_RETURN_FAILURE(self);
 
1975
                }
 
1976
 
 
1977
                /* Increment the group match reference */
 
1978
                b++;
 
1979
 
 
1980
                /* Increment the Input Stream */
 
1981
                self->ctx->ptr++;
 
1982
            }
 
1983
        }
 
1984
    }
 
1985
 
 
1986
    /* Move to next Op Code */
 
1987
    self->ctx->pattern++;
 
1988
 
 
1989
    return SRE_MATCH_PASS;
 
1990
}
2505
1991
 
2506
1992
Py_LOCAL_INLINE(Py_ssize_t)
2507
1993
SRE_MATCH_ON_IN(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
2508
1994
{
2509
1995
    /* match set member (or non_member) */
2510
 
    /* <IN> <skip> <set> */
 
1996
    /* <IN> <skip> <set> tail */
 
1997
    /* <skip> points to tail */
2511
1998
    int skip = (int)self->ctx->pattern[0];
2512
1999
    SRE_CODE *set = &self->ctx->pattern[1];
2513
2000
 
2514
2001
    TRACE(("|%p|%p|IN\n", self->ctx->pattern, self->ctx->ptr));
2515
2002
 
 
2003
    /* If not at the end of input, check the next character to see if */
 
2004
    /* it is in the given Character Set */
2516
2005
    if (self->ctx->ptr >= self->end ||
2517
2006
        !SRE_CHARSET(set, *self->ctx->ptr)) {
 
2007
 
 
2008
        /* Failed to Match; Pop Context */
2518
2009
        return SRE_MATCH_RETURN_FAILURE(self);
2519
 
        /* TODO: Go to exit */
2520
2010
    }
2521
2011
 
2522
2012
    /* Move to next Op Code and Character */
2530
2020
SRE_MATCH_ON_IN_IGNORE(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
2531
2021
{
2532
2022
    /* match set member (or non_member), ignoring case */
2533
 
    /* <IN_IGNORE> <skip> <set> */
 
2023
    /* <IN_IGNORE> <skip> <set> tail */
 
2024
    /* <skip> points to tail */
2534
2025
    int skip = (int)self->ctx->pattern[0];
2535
2026
    SRE_CODE *set = &self->ctx->pattern[1];
2536
2027
 
2537
2028
    TRACE(("|%p|%p|IN_IGNORE\n", self->ctx->pattern, self->ctx->ptr));
2538
2029
 
 
2030
    /* If not at the end of input, check the next character to see if */
 
2031
    /* it is in the given Character Set, without regard to case */
2539
2032
    if (self->ctx->ptr >= self->end ||
2540
2033
        !SRE_CHARSET(set, (SRE_CODE)state->lower(*self->ctx->ptr))) {
 
2034
 
 
2035
        /* Failed to Match; Pop Context */
2541
2036
        return SRE_MATCH_RETURN_FAILURE(self);
2542
 
        /* TODO: Go to exit */
2543
2037
    }
2544
2038
 
2545
2039
    /* Move to next Op Code and Character */
2558
2052
SRE_MATCH_ON_JUMP(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
2559
2053
{
2560
2054
    /* jump forward */
2561
 
    /* <JUMP> <offset> */
 
2055
    /* <JUMP> <offset> ... tail */
 
2056
    /* <offest> points to tail */
2562
2057
    int offset = (int)self->ctx->pattern[0];
2563
2058
 
2564
2059
    /* Note: This function can be used for any OpCode of the form */
2587
2082
    /* NOT match */
2588
2083
    if (self->ctx->ptr >= self->end ||
2589
2084
        (SRE_CODE)self->ctx->ptr[0] != code) {
 
2085
 
 
2086
        /* Failed to Match; Pop Context */
2590
2087
        return SRE_MATCH_RETURN_FAILURE(self);
2591
 
        /* TODO: Go to exit */
2592
2088
    }
2593
2089
 
2594
2090
    /* Move to next Op Code and Character */
2609
2105
    TRACE(("|%p|%p|LITERAL_IGNORE %d\n", self->ctx->pattern,
2610
2106
           self->ctx->ptr, code));
2611
2107
 
 
2108
    /* If there are no more characters or the current chatacter does */
 
2109
    /* NOT match, without regard to case */
2612
2110
    if (self->ctx->ptr >= self->end ||
2613
2111
        state->lower(*self->ctx->ptr) != state->lower(code)) {
 
2112
 
 
2113
        /* Failed to Match; Pop Context */
2614
2114
        return SRE_MATCH_RETURN_FAILURE(self);
2615
 
        /* TODO: Go to exit */
2616
2115
    }
2617
2116
 
2618
2117
    /* Move to next Op Code and Character */
2666
2165
    return SRE_MATCH_PASS;
2667
2166
}
2668
2167
 
2669
 
/* TODO: SRE_MATCH_ON_MAX_UNTIL */
2670
 
/* TODO: SRE_MATCH_ON_MIN_UNTIL */
 
2168
Py_LOCAL_INLINE(Py_ssize_t)
 
2169
SRE_MATCH_ON_MAX_UNTIL(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
2170
{
 
2171
    /* maximizing repeat */
 
2172
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX/MIN_UNTIL> tail */
 
2173
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2174
    /* skip is not used */
 
2175
    int min; /* Initialized Later */
 
2176
    int max; /* Initialized Later */
 
2177
    SRE_CODE *item; /* Initialized Later */
 
2178
 
 
2179
    /* FIXME: we probably need to deal with zero-width
 
2180
       matches in here... */
 
2181
 
 
2182
    /* Get the Repeat Context from the one created by the */
 
2183
    /* corresponding (in terms of nesting, i.e. if it goes repeat */
 
2184
    /* repeat until repeat until until, ther outermost until */
 
2185
    /* corresponding to the first repeat) repeat, which should have */
 
2186
    /* been stored in the global state when the corresponding Repeat */
 
2187
    /* was encountered */
 
2188
    /* Store current Repeat Context in this Context */
 
2189
    /* Note: This is done because although the Repeat Context is */
 
2190
    /* created in the call before the Push Stack (i.e. in the Repeat */
 
2191
    /* handler), because Push Stack is done generically, the current */
 
2192
    /* Repeat Context is instead stored in the global State and then */
 
2193
    /* placed in the newly created context here after the context has */
 
2194
    /* been created or when returned to after another repeat match. */
 
2195
    self->ctx->u.rep = state->repeat;
 
2196
 
 
2197
    /* Check to see if the Repeat Context is valid; if not, we have */
 
2198
    /* Until without Repeat, and need to return an error immediately */
 
2199
    /* as the pattern is invalid */
 
2200
    if (!self->ctx->u.rep) {
 
2201
        return SRE_MATCH_RETURN_ERROR(self, SRE_ERROR_STATE);
 
2202
    }
 
2203
 
 
2204
    /* Set the current input stream position to the one saved in the */
 
2205
    /* Current Context */
 
2206
    state->ptr = self->ctx->ptr;
 
2207
 
 
2208
    /* Set the count of sub-matches found (if first time, increments */
 
2209
    /* from -1 to 0) to the current context */
 
2210
    self->ctx->count = self->ctx->u.rep->count + 1;
 
2211
 
 
2212
    TRACE(("|%p|%p|MAX_UNTIL %d\n", self->ctx->pattern, self->ctx->ptr,
 
2213
           self->ctx->count));
 
2214
 
 
2215
    /* The pattern in the Context's Repeat Context points to just */
 
2216
    /* past the corresponding REPEAT op code; set the name aliases */
 
2217
    /* based on this */
 
2218
    min = (int)self->ctx->u.rep->pattern[1];
 
2219
    max = (int)self->ctx->u.rep->pattern[2];
 
2220
    item = &self->ctx->u.rep->pattern[3];
 
2221
 
 
2222
    if (self->ctx->count < min) {
 
2223
        /* not enough matches */
 
2224
 
 
2225
        /* Put the number of matches back in the Repeat Context */
 
2226
        self->ctx->u.rep->count = self->ctx->count;
 
2227
 
 
2228
        /* Parse the Repeated Pattern once again */
 
2229
        /* Move the match pattern to item to be repeatedly matched */
 
2230
        /* and create a new parse sub-context */
 
2231
        /* Go to SRE_MATCH_ON_JUMP_JUMP_MAX_UNTIL_1 when stack is */
 
2232
        /* popped */
 
2233
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2234
                                                  JUMP_MAX_UNTIL_1,
 
2235
                                                  item);
 
2236
    }
 
2237
    else if ((self->ctx->count < max || max == SRE_MAX_REPEAT) &&
 
2238
             state->ptr != self->ctx->u.rep->last_ptr) {
 
2239
        /* we may have enough matches, but if we can
 
2240
           match another item, do so */
 
2241
 
 
2242
        /* Put the number of matches back in the Repeat Context */
 
2243
        self->ctx->u.rep->count = self->ctx->count;
 
2244
 
 
2245
        /* Save the state's current Mark */
 
2246
        SRE_MATCH_LASTMARK_SAVE(self, state);
 
2247
 
 
2248
        /* Save the current Context's previous Mark into the current */
 
2249
        /* State's Stack */
 
2250
        SRE_MATCH_MARK_PUSH(self, state, self->ctx->lastmark);
 
2251
 
 
2252
        /* zero-width match protection */
 
2253
        /* Save the previous Input Stream position stored in the */
 
2254
        /* Context's Repeat Context into the current State's Stack */
 
2255
        SRE_MATCH_DATA_PUSH(self, state, &self->ctx->u.rep->last_ptr);
 
2256
 
 
2257
        /* Set the Current Repeat Context's previous Input Stream to */
 
2258
        /* the Current Input Stream position */
 
2259
        self->ctx->u.rep->last_ptr = state->ptr;
 
2260
 
 
2261
        /* Parse the Repeated Pattern once again */
 
2262
        /* Move the match pattern to item to be repeatedly matched */
 
2263
        /* and create a new parse sub-context */
 
2264
        /* Go to SRE_MATCH_ON_JUMP_JUMP_MAX_UNTIL_2 when stack is */
 
2265
        /* popped */
 
2266
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2267
                                                  JUMP_MAX_UNTIL_2,
 
2268
                                                  item);
 
2269
    }
 
2270
    else {
 
2271
        /* cannot match more repeated items here.  make sure the
 
2272
           tail matches */
 
2273
 
 
2274
        /* Restore the previous Repeat Context to be the current */
 
2275
        /* Repeat Context */
 
2276
        state->repeat = self->ctx->u.rep->prev;
 
2277
 
 
2278
        /* Parse the tail */
 
2279
        /* Move the match pattern to tail to verify that matches and */
 
2280
        /* create a new parse sub-context */
 
2281
        /* Go to SRE_MATCH_ON_JUMP_JUMP_MAX_UNTIL_3 when stack is */
 
2282
        /* popped */
 
2283
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2284
                                                  JUMP_MAX_UNTIL_3,
 
2285
                                                  self->ctx->pattern);
 
2286
    }
 
2287
}
 
2288
 
 
2289
Py_LOCAL_INLINE(Py_ssize_t)
 
2290
SRE_MATCH_ON_MIN_UNTIL(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
2291
{
 
2292
    /* minimizing repeat */
 
2293
    /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
 
2294
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2295
    /* skip is not used */
 
2296
    int min; /* Initialized Later */
 
2297
    /* max is not used */
 
2298
    SRE_CODE *item; /* Initialized Later */
 
2299
 
 
2300
    /* Get the Repeat Context from the one created by the */
 
2301
    /* corresponding (in terms of nesting, i.e. if it goes repeat */
 
2302
    /* repeat until repeat until until, ther outermost until */
 
2303
    /* corresponding to the first repeat) repeat, which should have */
 
2304
    /* been stored in the global state when the corresponding Repeat */
 
2305
    /* was encountered */
 
2306
    /* Store current Repeat Context in this Context */
 
2307
    /* Note: This is done because although the Repeat Context is */
 
2308
    /* created in the call before the Push Stack (i.e. in the Repeat */
 
2309
    /* handler), because Push Stack is done generically, the current */
 
2310
    /* Repeat Context is instead stored in the global State and then */
 
2311
    /* placed in the newly created context here after the context has */
 
2312
    /* been created or when returned to after another repeat match. */
 
2313
    self->ctx->u.rep = state->repeat;
 
2314
 
 
2315
    /* Check to see if the Repeat Context is valid; if not, we have */
 
2316
    /* Until without Repeat, and need to return an error immediately */
 
2317
    /* as the pattern is invalid */
 
2318
    if (!self->ctx->u.rep) {
 
2319
        return SRE_MATCH_RETURN_ERROR(self, SRE_ERROR_STATE);
 
2320
    }
 
2321
 
 
2322
    /* Set the current input stream position to the one saved in the */
 
2323
    /* Current Context */
 
2324
    state->ptr = self->ctx->ptr;
 
2325
 
 
2326
    /* Set the count of sub-matches found (if first time, increments */
 
2327
    /* from -1 to 0) to the current context */
 
2328
    self->ctx->count = self->ctx->u.rep->count + 1;
 
2329
 
 
2330
    TRACE(("|%p|%p|MIN_UNTIL %d %p\n", self->ctx->pattern,
 
2331
           self->ctx->ptr, self->ctx->count,
 
2332
           self->ctx->u.rep->pattern));
 
2333
 
 
2334
    /* The pattern in the Context's Repeat Context points to just */
 
2335
    /* past the corresponding REPEAT op code; set the name aliases */
 
2336
    /* based on this */
 
2337
    min = (int)self->ctx->u.rep->pattern[1];
 
2338
    item = &self->ctx->u.rep->pattern[3];
 
2339
 
 
2340
    if (self->ctx->count < min) {
 
2341
        /* not enough matches */
 
2342
 
 
2343
        /* Put the number of matches back in the Repeat Context */
 
2344
        self->ctx->u.rep->count = self->ctx->count;
 
2345
 
 
2346
        /* Parse the Repeated Pattern once again */
 
2347
        /* Move the match pattern to item to be repeatedly matched */
 
2348
        /* and create a new parse sub-context */
 
2349
        /* Go to SRE_MATCH_ON_JUMP_JUMP_MAX_UNTIL_1 when stack is */
 
2350
        /* popped */
 
2351
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2352
                                                  JUMP_MIN_UNTIL_1,
 
2353
                                                  item);
 
2354
    }
 
2355
 
 
2356
    /* Save the state's current Mark */
 
2357
    SRE_MATCH_LASTMARK_SAVE(self, state);
 
2358
 
 
2359
    /* see if the tail matches */
 
2360
 
 
2361
    /* Restore the previous Repeat Context to be the current Repeat */
 
2362
    /* Context */
 
2363
    state->repeat = self->ctx->u.rep->prev;
 
2364
 
 
2365
    return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2366
                                              JUMP_MIN_UNTIL_2,
 
2367
                                              self->ctx->pattern);
 
2368
}
2671
2369
 
2672
2370
Py_LOCAL_INLINE(Py_ssize_t)
2673
2371
SRE_MATCH_ON_NOT_LITERAL(SRE_MATCH_GLOBAL_CONTEXT *self,
2684
2382
    /* match */
2685
2383
    if (self->ctx->ptr >= self->end ||
2686
2384
        (SRE_CODE)self->ctx->ptr[0] == code) {
 
2385
 
 
2386
        /* Failed to Match; Pop Context */
2687
2387
        return SRE_MATCH_RETURN_FAILURE(self);
2688
 
        /* TODO: Go to exit */
2689
2388
    }
2690
2389
 
2691
2390
    /* Move to next Op Code and Character */
2709
2408
    if (self->ctx->ptr >= self->end ||
2710
2409
        state->lower(*self->ctx->ptr) == state->lower(code)) {
2711
2410
        return SRE_MATCH_RETURN_FAILURE(self);
2712
 
        /* TODO: Go to exit */
2713
2411
    }
2714
2412
 
2715
2413
    /* Move to next Op Code and Character */
2721
2419
 
2722
2420
/* TODO: SRE_MATCH_ON_NEGATE */
2723
2421
/* TODO: SRE_MATCH_ON_RANGE */
2724
 
/* TODO: SRE_MATCH_ON_REPEAT */
 
2422
 
 
2423
Py_LOCAL_INLINE(Py_ssize_t)
 
2424
SRE_MATCH_ON_REPEAT(SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state)
 
2425
{
 
2426
    /* create repeat context.  all the hard work is done
 
2427
       by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */
 
2428
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX/MIN_UNTIL> tail */
 
2429
    /* <skip> points to <MAX/MIN_UNITL> */
 
2430
    int skip = (int)self->ctx->pattern[0];
 
2431
    /* min is not used */
 
2432
    /* max is not used */
 
2433
 
 
2434
    TRACE(("|%p|%p|REPEAT %d %d\n", self->ctx->pattern, self->ctx->ptr,
 
2435
           min, max));
 
2436
 
 
2437
    /* install new repeat context */
 
2438
    /* Allocate Repeat Context */
 
2439
    self->ctx->u.rep = (SRE_REPEAT *)PyObject_MALLOC(sizeof(*self->ctx->
 
2440
                                                            u.rep));
 
2441
 
 
2442
    /* Was the memory allocated */
 
2443
    if (!self->ctx->u.rep) {
 
2444
        PyErr_NoMemory();
 
2445
 
 
2446
        return SRE_MATCH_RETURN_FAILURE(self);
 
2447
    }
 
2448
 
 
2449
    /* Set the Repeat Context attributes and make it the current */
 
2450
    /* repeat */
 
2451
    /* Number of Repeats encountered; initialize to -1 */
 
2452
    self->ctx->u.rep->count = -1;
 
2453
 
 
2454
    /* Store the location of the repeat parameters in the Repeat */
 
2455
    /* object */
 
2456
    self->ctx->u.rep->pattern = self->ctx->pattern;
 
2457
 
 
2458
    /* Back up the current Repeat Context as the previous Repeat */
 
2459
    /* Context in the Repeat object */
 
2460
    self->ctx->u.rep->prev = state->repeat;
 
2461
 
 
2462
    /* Clear the Previous Input Stream pointer in the Repeat object */
 
2463
    self->ctx->u.rep->last_ptr = NULL;
 
2464
 
 
2465
    /* Update the current Repeat Context to be the one just created */
 
2466
    state->repeat = self->ctx->u.rep;
 
2467
 
 
2468
    /* Update the global input stream pointer ptr from the current */
 
2469
    /* Context */
 
2470
    state->ptr = self->ctx->ptr;
 
2471
 
 
2472
    /* Parse the Repeated Pattern */
 
2473
    /* Move the match pattern to the end of the Pseudo-Recursion */
 
2474
    /* group, denoted by Repeat's <skip> parameter, which should be */
 
2475
    /* either a Min Until or a Max Until op code and create a new */
 
2476
    /* parse sub-context */
 
2477
    /* Go to SRE_MATCH_ON_JUMP_REPEAT when stack is popped */
 
2478
    return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state, JUMP_REPEAT,
 
2479
                                              self->ctx->pattern +
 
2480
                                              skip);
 
2481
}
2725
2482
 
2726
2483
Py_LOCAL_INLINE(Py_ssize_t)
2727
2484
SRE_MATCH_ON_REPEAT_ONE(SRE_MATCH_GLOBAL_CONTEXT *self,
2735
2492
       use the MAX_REPEAT operator */
2736
2493
 
2737
2494
    /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
 
2495
    /* <skip> points to tail */
2738
2496
    int skip = (int)self->ctx->pattern[0];
2739
2497
    int min = (int)self->ctx->pattern[1];
2740
2498
    int max = (int)self->ctx->pattern[2];
2775
2533
    self->ctx->ptr += self->ctx->count;
2776
2534
 
2777
2535
    /* when we arrive here, count contains the number of
2778
 
       matches, and self.ctx->ptr points to the tail of the target
 
2536
       matches, and self->ctx->ptr points to the tail of the target
2779
2537
       string.  check if the rest of the pattern matches,
2780
2538
       and backtrack if not. */
2781
2539
    if (self->ctx->pattern[skip] == SRE_OP_SUCCESS) {
2785
2543
        return SRE_MATCH_RETURN_SUCCESS(self);
2786
2544
    }
2787
2545
 
 
2546
    /* Store the previous Mark into the Current Context */
2788
2547
    SRE_MATCH_LASTMARK_SAVE(self, state);
2789
2548
 
 
2549
    /* Check for Simple Case */
2790
2550
    if (self->ctx->pattern[skip] == SRE_OP_LITERAL) {
2791
2551
        /* tail starts with a literal. skip positions where
2792
2552
           the rest of the pattern cannot possibly match */
2793
 
        self->ctx->u.chr = self->ctx->pattern[skip + 1];
2794
 
        for (;;) {
2795
 
            /* Roll back matched characters until the subsequent */
2796
 
            /* character literal can be matched */
2797
 
            while (self->ctx->count >= (Py_ssize_t)min &&
2798
 
                   (self->ctx->ptr >= self->end ||
2799
 
                    *self->ctx->ptr != self->ctx->u.chr)) {
2800
 
                self->ctx->ptr--;
2801
 
                self->ctx->count--;
2802
 
            }
2803
 
 
 
2553
 
 
2554
        /* Next op code is Literal, at <skip>, whose first parameter, */
 
2555
        /* at <skip> + 1, is the literal code to match; store it */
 
2556
        /* literal */
 
2557
        SRE_CHAR literal = (SRE_CHAR)self->ctx->pattern[skip + 1];
 
2558
 
 
2559
        /* Cache the literal in the context's repeat area */
 
2560
        self->ctx->u.chr = literal;
 
2561
 
 
2562
        /* Roll back matched characters until the subsequent */
 
2563
        /* character literal can be matched */
 
2564
        while (self->ctx->count >= (Py_ssize_t)min &&
 
2565
                (self->ctx->ptr >= self->end ||
 
2566
                *self->ctx->ptr != literal)) {
 
2567
            self->ctx->ptr--;
 
2568
            self->ctx->count--;
 
2569
        }
 
2570
 
 
2571
        /* Make sure we've matched at least min characters */
 
2572
        if (self->ctx->count >= (Py_ssize_t)min) {
 
2573
 
 
2574
            /* Update the current input offset */
 
2575
            state->ptr = self->ctx->ptr;
 
2576
 
 
2577
            /* This string matches so far, so add a new stack frame */
 
2578
            /* and continue to try and match */
 
2579
            /* Move the match pattern to the end of the */
 
2580
            /* Pseudo-Recursion group, just passed the corresponding */
 
2581
            /* Success op code and denoted by Repeat One's <skip> */
 
2582
            /* parameter and create a new parse sub-context */
 
2583
            /* Go to SRE_MATCH_ON_JUMP_REPEAT_ONE_1 when stack is */
 
2584
            /* popped */
 
2585
            return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2586
                                                      JUMP_REPEAT_ONE_1,
 
2587
                                                      self->ctx->pattern
 
2588
                                                      + skip);
 
2589
        }
 
2590
        else {
2804
2591
            /* Subsequent literal could not be matched */
2805
 
            if (self->ctx->count < (Py_ssize_t)min) {
2806
 
                break;
2807
 
            }
2808
 
 
2809
 
            /* Update the current input offset */
2810
 
            state->ptr = self->ctx->ptr;
2811
 
 
2812
 
            /* This string matches so far, so add a new stack frame */
2813
 
            /* and continue to try and match */
2814
 
            return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
2815
 
                                                      JUMP_REPEAT_ONE_1,
2816
 
                                                      self->ctx->pattern
2817
 
                                                      + skip);
 
2592
            return SRE_MATCH_RETURN_FAILURE(self);
2818
2593
        }
2819
2594
    }
2820
2595
    else {
2829
2604
 
2830
2605
            /* This string matches so far, so add a new stack frame */
2831
2606
            /* and continue to try and match */
 
2607
            /* Move the match pattern to the end of the */
 
2608
            /* Pseudo-Recursion group, just passed the corresponding */
 
2609
            /* Success op code and denoted by Repeat One's <skip> */
 
2610
            /* parameter and create a new parse sub-context */
 
2611
            /* Go to SRE_MATCH_ON_JUMP_REPEAT_ONE_2 when stack is */
 
2612
            /* popped */
2832
2613
            return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
2833
2614
                                                      JUMP_REPEAT_ONE_2,
2834
2615
                                                      self->ctx->pattern
2835
2616
                                                      + skip);
2836
 
       }
 
2617
        }
 
2618
        else {
 
2619
            /* Could not match */
 
2620
            return SRE_MATCH_RETURN_FAILURE(self);
 
2621
        }
2837
2622
    }
2838
 
 
2839
 
    /* Could not match */
2840
 
    return SRE_MATCH_RETURN_FAILURE(self);
2841
2623
}
2842
2624
 
2843
2625
/* TODO: SRE_MATCH_ON_SUBPATTERN */
2854
2636
       use the MIN_REPEAT operator */
2855
2637
 
2856
2638
    /* <MIN_REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
 
2639
    /* <skip> points to tail */
2857
2640
    int skip = (int)self->ctx->pattern[0];
2858
2641
    int min = (int)self->ctx->pattern[1];
2859
2642
    int max = (int)self->ctx->pattern[2];
2900
2683
    }
2901
2684
 
2902
2685
    /* when we arrive here, count contains the minimum number of
2903
 
       matches, and self.ctx->ptr points to the first character not
 
2686
       matches, and self->ctx->ptr points to the first character not
2904
2687
       required to match in the target string.  check if the rest of
2905
2688
       the pattern matches, and consume more matches if not. */
2906
2689
    if (self->ctx->pattern[skip] == SRE_OP_SUCCESS) {
2911
2694
    }
2912
2695
    else {
2913
2696
        /* general case */
 
2697
        /* Store the previous Mark into the Current Context */
2914
2698
        SRE_MATCH_LASTMARK_SAVE(self, state);
2915
2699
 
2916
2700
        /* This code will act like a while because it will spawn and */
2923
2707
 
2924
2708
            /* This string matches so far, so add a new stack frame */
2925
2709
            /* and continue to try and match */
 
2710
            /* Move the match pattern to the end of the */
 
2711
            /* Pseudo-Recursion group, just passed the corresponding */
 
2712
            /* Success op code and denoted by Min Repeat One's <skip> */
 
2713
            /* parameter and create a new parse sub-context */
 
2714
            /* Go to SRE_MATCH_ON_JUMP_MIN_REPEAT_ONE when stack is */
 
2715
            /* popped */
2926
2716
            return
2927
2717
                SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
2928
2718
                                                   JUMP_MIN_REPEAT_ONE,
2946
2736
    TRACE(("|%p|%p|UNKNOWN %d\n", self->ctx->pattern, self->ctx->ptr,
2947
2737
           self->op_code));
2948
2738
 
 
2739
    /* Set an Error code and return right away! */
2949
2740
    return SRE_MATCH_RETURN_ERROR(self, SRE_ERROR_ILLEGAL);
2950
 
    /* TODO: when this is called, should return right away! */
2951
2741
}
2952
2742
 
2953
2743
Py_LOCAL_INLINE(Py_ssize_t)
2962
2752
    return SRE_MATCH_PASS;
2963
2753
}
2964
2754
 
2965
 
/* TODO: SRE_MATCH_ON_JUMP_MAX_UNTIL_1 */
2966
 
/* TODO: SRE_MATCH_ON_JUMP_MAX_UNTIL_2 */
2967
 
/* TODO: SRE_MATCH_ON_JUMP_MAX_UNTIL_3 */
2968
 
/* TODO: SRE_MATCH_ON_JUMP_MIN_UNTIL_1 */
2969
 
/* TODO: SRE_MATCH_ON_JUMP_MIN_UNTIL_2 */
2970
 
/* TODO: SRE_MATCH_ON_JUMP_MIN_UNTIL_3 */
2971
 
/* TODO: SRE_MATCH_ON_JUMP_REPEAT */
 
2755
Py_LOCAL_INLINE(Py_ssize_t)
 
2756
SRE_MATCH_ON_JUMP_MAX_UNTIL_1(SRE_MATCH_GLOBAL_CONTEXT *self,
 
2757
                              SRE_STATE *state)
 
2758
{
 
2759
    /* TODO: This code is EXACTLY the same as SRE_MATCH_ON_JUMP_MIN_UNTIL_1; merge functions! */
 
2760
    /* maximizing repeat */
 
2761
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
 
2762
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2763
    /* skip is not used */
 
2764
    /* min is not used */
 
2765
    /* max is not used */
 
2766
    /* item is not used */
 
2767
 
 
2768
    TRACE(("|%p|%p|JUMP_MAX_UNTIL_1\n", self->ctx->pattern,
 
2769
           self->ctx->ptr));
 
2770
 
 
2771
    /* Check for Success or Error */
 
2772
    if (self->ret) {
 
2773
        if (self->ret < 0) {
 
2774
            /* Error, Return immediately */
 
2775
            return SRE_MATCH_FAIL;
 
2776
        }
 
2777
        else {
 
2778
            /* Pop stack with Success */
 
2779
            return SRE_MATCH_RETURN_SUCCESS(self);
 
2780
        }
 
2781
    }
 
2782
    else {
 
2783
        /* We did not find a match, so Decrement the Match count and */
 
2784
        /* Pop Stack with failure. */
 
2785
        /* Decrement Match Cont */
 
2786
        self->ctx->u.rep->count = self->ctx->count - 1;
 
2787
 
 
2788
        /* Restore Input Stream position to be the one saved in this */
 
2789
        /* Context; this will roll back the Input Stream to the last */
 
2790
        /* point that matched. */
 
2791
        state->ptr = self->ctx->ptr;
 
2792
 
 
2793
        /* Pop stack with Failure */
 
2794
        return SRE_MATCH_RETURN_FAILURE(self);
 
2795
    }
 
2796
}
 
2797
 
 
2798
Py_LOCAL_INLINE(Py_ssize_t)
 
2799
SRE_MATCH_ON_JUMP_MAX_UNTIL_2(SRE_MATCH_GLOBAL_CONTEXT *self,
 
2800
                              SRE_STATE *state)
 
2801
{
 
2802
    /* maximizing repeat */
 
2803
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
 
2804
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2805
    /* skip is not used */
 
2806
    /* min is not used */
 
2807
    /* max is not used */
 
2808
    /* item is not used */
 
2809
 
 
2810
    TRACE(("|%p|%p|JUMP_MAX_UNTIL_2\n", self->ctx->pattern,
 
2811
           self->ctx->ptr));
 
2812
 
 
2813
    /* Failed to match, roll back */
 
2814
    /* Restore the previous Input Stream position stored in the */
 
2815
    /* current State's Stack into the Context's Repeat Context */
 
2816
    SRE_MATCH_DATA_POP(state, &self->ctx->u.rep->last_ptr);
 
2817
 
 
2818
    /* Check for Success or Error */
 
2819
    if (self->ret) {
 
2820
        /* Remove the previously saved Mark from the current */
 
2821
        /* State's Stack */
 
2822
        SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
 
2823
 
 
2824
        if (self->ret < 0) {
 
2825
            /* Error, Return immediately */
 
2826
            return SRE_MATCH_FAIL;
 
2827
        }
 
2828
        else {
 
2829
            /* Pop stack with Success */
 
2830
            return SRE_MATCH_RETURN_SUCCESS(self);
 
2831
        }
 
2832
    }
 
2833
    else {
 
2834
        /* Failed to Match So Far... */
 
2835
 
 
2836
        /* Restore the current Context's previous Mark from the */
 
2837
        /* current State's Stack */
 
2838
        SRE_MATCH_MARK_POP(state, self->ctx->lastmark);
 
2839
 
 
2840
        /* Restore the state's current Mark */
 
2841
        SRE_MATCH_LASTMARK_RESTORE(self, state);
 
2842
 
 
2843
        /* No match, match one less pattern and store the new */
 
2844
        /* count in the Context's Repeat Context */
 
2845
        self->ctx->u.rep->count = self->ctx->count - 1;
 
2846
 
 
2847
        /* Update the current Input Stream position from the one */
 
2848
        /* saved in the current Context */
 
2849
        state->ptr = self->ctx->ptr;
 
2850
 
 
2851
        /* cannot match more repeated items here.  make sure the
 
2852
           tail matches */
 
2853
 
 
2854
        /* Restore the previous Repeat Context to be the current */
 
2855
        /* Repeat Context */
 
2856
        state->repeat = self->ctx->u.rep->prev;
 
2857
 
 
2858
        /* Parse the tail */
 
2859
        /* Move the match pattern to tail to verify that matches and */
 
2860
        /* create a new parse sub-context */
 
2861
        /* Go to SRE_MATCH_ON_JUMP_JUMP_MAX_UNTIL_3 when stack is */
 
2862
        /* popped */
 
2863
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
2864
                                                  JUMP_MAX_UNTIL_3,
 
2865
                                                  self->ctx->pattern);
 
2866
    }
 
2867
}
 
2868
 
 
2869
Py_LOCAL_INLINE(Py_ssize_t)
 
2870
SRE_MATCH_ON_JUMP_MAX_UNTIL_3(SRE_MATCH_GLOBAL_CONTEXT *self,
 
2871
                              SRE_STATE *state)
 
2872
{
 
2873
    /* maximizing repeat */
 
2874
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
 
2875
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2876
    /* skip is not used */
 
2877
    /* min is not used */
 
2878
    /* max is not used */
 
2879
    /* item is not used */
 
2880
 
 
2881
    TRACE(("|%p|%p|JUMP_MAX_UNTIL_3\n", self->ctx->pattern,
 
2882
           self->ctx->ptr));
 
2883
 
 
2884
    /* Done searching through the Input Stream, did we find a match? */
 
2885
    /* Check for Success or Error */
 
2886
    if (self->ret) {
 
2887
        if (self->ret < 0) {
 
2888
            /* Error, Return immediately */
 
2889
            return SRE_MATCH_FAIL;
 
2890
        }
 
2891
        else {
 
2892
            /* Pop stack with Success */
 
2893
            return SRE_MATCH_RETURN_SUCCESS(self);
 
2894
        }
 
2895
    }
 
2896
    else {
 
2897
        /* Failed to Match, Pop stack */
 
2898
 
 
2899
        /* Restore the current Context's Repeat Context to be the */
 
2900
        /* current Repeat Context */
 
2901
        state->repeat = self->ctx->u.rep;
 
2902
 
 
2903
        /* Restore Input Stream position to be the one saved in this */
 
2904
        /* Context; this will roll back the Input Stream to the last */
 
2905
        /* point that matched. */
 
2906
        state->ptr = self->ctx->ptr;
 
2907
 
 
2908
        /* Pop stack with Failure */
 
2909
        return SRE_MATCH_RETURN_FAILURE(self);
 
2910
    }
 
2911
}
 
2912
 
 
2913
Py_LOCAL_INLINE(Py_ssize_t)
 
2914
SRE_MATCH_ON_JUMP_MIN_UNTIL_1(SRE_MATCH_GLOBAL_CONTEXT *self,
 
2915
                              SRE_STATE *state)
 
2916
{
 
2917
    /* TODO: This code is EXACTLY the same as SRE_MATCH_ON_JUMP_MAX_UNTIL_1; merge functions! */
 
2918
    /* minimizing repeat */
 
2919
    /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
 
2920
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2921
    /* skip is not used */
 
2922
    /* min is not used */
 
2923
    /* max is not used */
 
2924
    /* item is not used */
 
2925
 
 
2926
    TRACE(("|%p|%p|JUMP_MIN_UNTIL_1\n", self->ctx->pattern,
 
2927
           self->ctx->ptr));
 
2928
 
 
2929
    /* Check for Success or Error */
 
2930
    if (self->ret) {
 
2931
        if (self->ret < 0) {
 
2932
            /* Error, Return immediately */
 
2933
            return SRE_MATCH_FAIL;
 
2934
        }
 
2935
        else {
 
2936
            /* Pop stack with Success */
 
2937
            return SRE_MATCH_RETURN_SUCCESS(self);
 
2938
        }
 
2939
    }
 
2940
    else {
 
2941
        /* We did not find a match, so Decrement the Match count and */
 
2942
        /* Pop Stack with failure. */
 
2943
        /* Decrement Match Cont */
 
2944
        self->ctx->u.rep->count = self->ctx->count - 1;
 
2945
 
 
2946
        /* Restore Input Stream position to be the one saved in this */
 
2947
        /* Context; this will roll back the Input Stream to the last */
 
2948
        /* point that matched. */
 
2949
        state->ptr = self->ctx->ptr;
 
2950
 
 
2951
        /* Pop stack with Failure */
 
2952
        return SRE_MATCH_RETURN_FAILURE(self);
 
2953
    }
 
2954
}
 
2955
 
 
2956
Py_LOCAL_INLINE(Py_ssize_t)
 
2957
SRE_MATCH_ON_JUMP_MIN_UNTIL_2(SRE_MATCH_GLOBAL_CONTEXT *self,
 
2958
                              SRE_STATE *state)
 
2959
{
 
2960
    /* minimizing repeat */
 
2961
    /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
 
2962
    /* <skip> points to <MAX/MIN_UNTIL> */
 
2963
    /* skip is not used */
 
2964
    /* min is not used */
 
2965
    int max; /* Initialized Later */
 
2966
    SRE_CODE *item; /* Initialized Later */
 
2967
 
 
2968
    TRACE(("|%p|%p|JUMP_MAX_UNTIL_2\n", self->ctx->pattern,
 
2969
           self->ctx->ptr));
 
2970
 
 
2971
    /* Check for Success or Error */
 
2972
    if (self->ret) {
 
2973
        if (self->ret < 0) {
 
2974
            /* Error, Return immediately */
 
2975
            return SRE_MATCH_FAIL;
 
2976
        }
 
2977
        else {
 
2978
            /* Pop stack with Success */
 
2979
            return SRE_MATCH_RETURN_SUCCESS(self);
 
2980
        }
 
2981
    }
 
2982
    else {
 
2983
        /* Failed to Match So Far... */
 
2984
 
 
2985
        /* The pattern in the Context's Repeat Context points to */
 
2986
        /* just past the corresponding REPEAT op code; set the name */
 
2987
        /* aliases based on this */
 
2988
        max = (int)self->ctx->u.rep->pattern[2];
 
2989
 
 
2990
        /* Restore the current Context's Repeat Context to be the */
 
2991
        /* current Repeat Context */
 
2992
        state->repeat = self->ctx->u.rep;
 
2993
 
 
2994
        /* Restore Input Stream position to be the one saved in this */
 
2995
        /* Context; this will roll back the Input Stream to the last */
 
2996
        /* point that matched. */
 
2997
        state->ptr = self->ctx->ptr;
 
2998
 
 
2999
        /* Restore the state's current Mark */
 
3000
        SRE_MATCH_LASTMARK_RESTORE(self, state);
 
3001
 
 
3002
        /* Check to see if we have too many matches and thus fail */
 
3003
        if (self->ctx->count >= max && max != SRE_MAX_REPEAT) {
 
3004
            /* Failed to Match, Pop stack */
 
3005
            return SRE_MATCH_RETURN_FAILURE(self);
 
3006
        }
 
3007
        else {
 
3008
            /* We have not reached our match limit, try to match */
 
3009
            /* another time */
 
3010
 
 
3011
            /* The pattern in the Context's Repeat Context points to */
 
3012
            /* just past the corresponding REPEAT op code; set the */
 
3013
            /* name aliases based on this */
 
3014
            item = &self->ctx->u.rep->pattern[3];
 
3015
 
 
3016
            /* Put the number of matches back in the Repeat Context */
 
3017
            self->ctx->u.rep->count = self->ctx->count;
 
3018
 
 
3019
            /* Parse the Repeated Pattern once again */
 
3020
            /* Move the match pattern to item to be repeatedly */
 
3021
            /* matched and create a new parse sub-context */
 
3022
            /* Go to SRE_MATCH_ON_JUMP_JUMP_MIN_UNTIL_3 when stack is */
 
3023
            /* popped */
 
3024
            return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
3025
                                                      JUMP_MIN_UNTIL_3,
 
3026
                                                      item);
 
3027
        }
 
3028
    }
 
3029
}
 
3030
 
 
3031
Py_LOCAL_INLINE(Py_ssize_t)
 
3032
SRE_MATCH_ON_JUMP_MIN_UNTIL_3(SRE_MATCH_GLOBAL_CONTEXT *self,
 
3033
                              SRE_STATE *state)
 
3034
{
 
3035
    /* minimizing repeat */
 
3036
    /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
 
3037
    /* <skip> points to <MAX/MIN_UNTIL> */
 
3038
    /* skip is not used */
 
3039
    /* min is not used */
 
3040
    /* max is not used */
 
3041
    /* item is not used */
 
3042
 
 
3043
    TRACE(("|%p|%p|JUMP_MAX_UNTIL_3\n", self->ctx->pattern,
 
3044
           self->ctx->ptr));
 
3045
 
 
3046
    /* If the tail matched or we encountered an unrecoverable error, */
 
3047
    /* we're done */
 
3048
    if (self->ret) {
 
3049
        if (self->ret < 0) {
 
3050
            /* Error, Return immediately */
 
3051
            return SRE_MATCH_FAIL;
 
3052
        }
 
3053
        else {
 
3054
            /* Pop stack with Success */
 
3055
            return SRE_MATCH_RETURN_SUCCESS(self);
 
3056
        }
 
3057
    }
 
3058
    else {
 
3059
        /* Tail did not Match, pop stack and see if we can try again */
 
3060
        /* with another Match of item */
 
3061
 
 
3062
        /* No match, match one less pattern and store the new */
 
3063
        /* count in the Context's Repeat Context */
 
3064
        self->ctx->u.rep->count = self->ctx->count - 1;
 
3065
 
 
3066
        /* Update the current Input Stream position from the one */
 
3067
        /* saved in the current Context */
 
3068
        state->ptr = self->ctx->ptr;
 
3069
 
 
3070
        /* Failed to Match, Pop stack */
 
3071
        return SRE_MATCH_RETURN_FAILURE(self);
 
3072
    }
 
3073
}
 
3074
 
 
3075
Py_LOCAL_INLINE(Py_ssize_t)
 
3076
SRE_MATCH_ON_JUMP_REPEAT(SRE_MATCH_GLOBAL_CONTEXT *self,
 
3077
                         SRE_STATE *state)
 
3078
{
 
3079
    /* create repeat context.  all the hard work is done
 
3080
       by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */
 
3081
    /* <REPEAT> <skip> <1=min> <2=max> item <MAX/MIN_UNTIL> tail */
 
3082
    /* <skip> points to <MAX/MIN_UNTIL> */
 
3083
    /* skip is not used */
 
3084
    /* min is not used */
 
3085
    /* max is not used */
 
3086
 
 
3087
    TRACE(("|%p|%p|JUMP_REPEAT\n", self->ctx->pattern, self->ctx->ptr));
 
3088
 
 
3089
    /* Roll back the Repeat State */
 
3090
    state->repeat = self->ctx->u.rep->prev;
 
3091
 
 
3092
    /* Free the memory used by the Repeat State */
 
3093
    PyObject_FREE(self->ctx->u.rep);
 
3094
 
 
3095
    /* Check for errors */
 
3096
    if (self->ret) {
 
3097
        if (self->ret < 0) {
 
3098
            return SRE_MATCH_FAIL;
 
3099
        }
 
3100
        else {
 
3101
            /* Successful Match */
 
3102
            return SRE_MATCH_RETURN_SUCCESS(self);
 
3103
        }
 
3104
    }
 
3105
    else {
 
3106
        /* Failed to match */
 
3107
        return SRE_MATCH_RETURN_FAILURE(self);
 
3108
    }
 
3109
}
2972
3110
 
2973
3111
Py_LOCAL_INLINE(Py_ssize_t)
2974
3112
SRE_MATCH_ON_JUMP_REPEAT_ONE_1(SRE_MATCH_GLOBAL_CONTEXT *self,
2977
3115
    /* Note: Requires the next operator after REPEAT_ONE be a literal */
2978
3116
    /* match repeated sequence (maximizing regexp) */
2979
3117
    /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
 
3118
    /* <skip> points to tail */
2980
3119
    int skip = (int)self->ctx->pattern[0];
2981
3120
    int min = (int)self->ctx->pattern[1];
2982
 
    /* max is not ised */
 
3121
    /* max is not used */
2983
3122
    /* item is not used */
2984
3123
 
 
3124
    /* self->ctx->u.chr contain the literal to match; set in the */
 
3125
    /* main function */
 
3126
    SRE_CHAR literal = (SRE_CHAR)self->ctx->u.chr;
 
3127
 
2985
3128
    TRACE(("|%p|%p|JUMP_REPEAT_ONE_1\n", self->ctx->pattern,
2986
3129
           self->ctx->ptr));
2987
3130
 
2996
3139
        }
2997
3140
    }
2998
3141
 
2999
 
    /* Did not match, remove a character from the match and try again */
3000
 
    self->ctx->ptr--;
3001
 
    self->ctx->count--;
3002
 
 
 
3142
    /* Restore the previous Mark from the Current Context */
3003
3143
    SRE_MATCH_LASTMARK_RESTORE(self, state);
3004
3144
 
3005
 
    for (;;) {
 
3145
    do {
 
3146
        /* Did not match, remove a character from the match and try */
 
3147
        /* again */
 
3148
        self->ctx->ptr--;
 
3149
        self->ctx->count--;
 
3150
 
3006
3151
        /* Roll back matched characters until the subsequent */
3007
3152
        /* character literal can be matched */
3008
 
        /* self->ctx->u.chr contain the literal to match; set in the */
3009
 
        /* main function */
3010
 
        while (self->ctx->count >= (Py_ssize_t)min &&
3011
 
               (self->ctx->ptr >= self->end ||
3012
 
                *self->ctx->ptr != self->ctx->u.chr)) {
3013
 
            self->ctx->ptr--;
3014
 
            self->ctx->count--;
3015
 
        }
3016
 
 
 
3153
    } while (self->ctx->count >= (Py_ssize_t)min &&
 
3154
             (self->ctx->ptr >= self->end ||
 
3155
              *self->ctx->ptr != literal));
 
3156
 
 
3157
    /* Make sure we've matched at least min characters */
 
3158
    if (self->ctx->count >= (Py_ssize_t)min) {
 
3159
 
 
3160
        /* Update the current input offset */
 
3161
        state->ptr = self->ctx->ptr;
 
3162
 
 
3163
        /* This string matches so far, so add a new stack frame and */
 
3164
        /* continue to try and match */
 
3165
        /* Move the match pattern to the end of the */
 
3166
        /* Pseudo-Recursion group, just passed the corresponding */
 
3167
        /* Success op code and denoted by Repeat One's <skip> */
 
3168
        /* parameter and create a new parse sub-context */
 
3169
        /* Go to this function (SRE_MATCH_ON_JUMP_REPEAT_ONE_1) when */
 
3170
        /* stack is popped */
 
3171
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
3172
                                                  JUMP_REPEAT_ONE_1,
 
3173
                                                  self->ctx->pattern +
 
3174
                                                  skip);
 
3175
    }
 
3176
    else {
3017
3177
        /* Subsequent literal could not be matched */
3018
 
        if (self->ctx->count < (Py_ssize_t)min) {
3019
 
            break;
3020
 
        }
3021
 
 
3022
 
        /* Update the current input offset */
3023
 
        state->ptr = self->ctx->ptr;
3024
 
 
3025
 
        /* This string matches so far, so add a new stack frame and */
3026
 
        /* continue to try and match */
3027
 
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
3028
 
                                                  JUMP_REPEAT_ONE_1,
3029
 
                                                  self->ctx->pattern +
3030
 
                                                  skip);
 
3178
        return SRE_MATCH_RETURN_FAILURE(self);
3031
3179
    }
3032
 
 
3033
 
    /* Could not match */
3034
 
    return SRE_MATCH_RETURN_FAILURE(self);
3035
3180
}
3036
3181
 
3037
3182
Py_LOCAL_INLINE(Py_ssize_t)
3042
3187
    /*                     literal) */
3043
3188
    /* match repeated sequence (maximizing regexp) */
3044
3189
    /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
 
3190
    /* <skip> points to tail */
3045
3191
    int skip = (int)self->ctx->pattern[0];
3046
3192
    int min = (int)self->ctx->pattern[1];
3047
3193
    /* max is not ised */
3065
3211
    self->ctx->ptr--;
3066
3212
    self->ctx->count--;
3067
3213
 
 
3214
    /* Restore the previous Mark from the Current Context */
3068
3215
    SRE_MATCH_LASTMARK_RESTORE(self, state);
3069
3216
 
3070
3217
    /* This code will act like a while because it will spawn and pop */
3076
3223
 
3077
3224
        /* This string matches so far, so add a new stack frame and */
3078
3225
        /* continue to try and match */
 
3226
        /* Move the match pattern to the end of the */
 
3227
        /* Pseudo-Recursion group, just passed the corresponding */
 
3228
        /* Success op code and denoted by Repeat One's <skip> */
 
3229
        /* parameter and create a new parse sub-context */
 
3230
        /* Go to this function (SRE_MATCH_ON_JUMP_REPEAT_ONE_2) when */
 
3231
        /* stack is popped */
3079
3232
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
3080
3233
                                                  JUMP_REPEAT_ONE_2,
3081
3234
                                                  self->ctx->pattern +
3091
3244
                                 SRE_STATE *state)
3092
3245
{
3093
3246
    /* <MIN_REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
 
3247
    /* <skip> points to tail */
3094
3248
    int skip = (int)self->ctx->pattern[0];
3095
3249
    /* min is not used */
3096
3250
    int max = (int)self->ctx->pattern[2];
3137
3291
    self->ctx->ptr++;
3138
3292
    self->ctx->count++;
3139
3293
 
 
3294
    /* Restore the previous Mark from the Current Context */
3140
3295
    SRE_MATCH_LASTMARK_RESTORE(self, state);
3141
3296
 
3142
3297
    /* This code will act like a while because it will spawn and push */
3149
3304
 
3150
3305
        /* This string matches so far, so add a new stack frame and */
3151
3306
        /* continue to try and match */
 
3307
        /* Move the match pattern to the end of the */
 
3308
        /* Pseudo-Recursion group, just passed the corresponding */
 
3309
        /* Success op code and denoted by Min Repeat One's <skip> */
 
3310
        /* parameter and create a new parse sub-context */
 
3311
        /* Go to this function (SRE_MATCH_ON_JUMP_MIN_REPEAT_ONE) */
 
3312
        /* when stack is popped */
3152
3313
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
3153
3314
                                                  JUMP_MIN_REPEAT_ONE,
3154
3315
                                                  self->ctx->pattern +
3165
3326
                         SRE_STATE *state)
3166
3327
{
3167
3328
    /* alternation */
3168
 
    /* <BRANCH> ... code <JUMP> ... <NULL> */
 
3329
    /* <BRANCH> <skip> code <JUMP> <skip-end> */
 
3330
    /*       (<0=skip> code <JUMP> <skip-end>)* <FAILURE> tail */
 
3331
    /* Each <skip> points to the one passed the next <skip-end>, */
 
3332
    /* i.e. the next <skip> or <FAILURE> if the last one */
 
3333
    /* Each <skip-end> always points to the end of the Branching, */
 
3334
    /* i.e. tail */
 
3335
    int skip = (int)self->ctx->pattern[0];
 
3336
    SRE_CODE *p_next_op; /* Initialized Later */
 
3337
    SRE_CHAR literal; /* Initialized Later */
 
3338
    SRE_CODE *set; /* Initialized Later */
3169
3339
 
3170
3340
    TRACE(("|%p|%p|JUMP_BRANCH\n", ctx->pattern, ctx->ptr));
3171
3341
 
 
3342
    /* Check for Success or unrecoverable Error */
3172
3343
    if (self->ret) {
3173
3344
        if (self->ctx->u.rep) {
 
3345
            /* A mark was left in the Context's Repeat Context; */
 
3346
            /* discard it */
3174
3347
            SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
3175
3348
        }
3176
3349
 
3179
3352
            return SRE_MATCH_FAIL;
3180
3353
        }
3181
3354
        else {
 
3355
            /* Pop Contect with a Success Condition */
3182
3356
            return SRE_MATCH_RETURN_SUCCESS(self);
3183
3357
        }
3184
3358
    }
3185
 
 
3186
 
    if (self->ctx->u.rep) {
3187
 
        SRE_MATCH_MARK_POP_KEEP(state, self->ctx->lastmark);
3188
 
    }
3189
 
 
3190
 
    SRE_MATCH_LASTMARK_RESTORE(self, state);
3191
 
 
3192
 
    for (; self->ctx->pattern[0];
3193
 
         self->ctx->pattern += self->ctx->pattern[0]) {
3194
 
        if (self->ctx->pattern[1] == SRE_OP_LITERAL &&
3195
 
            (self->ctx->ptr >= self->end ||
3196
 
             (SRE_CODE) *self->ctx->ptr != self->ctx->pattern[2])) {
3197
 
             /* Literal Miss-Match, continue */
3198
 
            continue;
3199
 
        }
3200
 
 
3201
 
        else if (self->ctx->pattern[1] == SRE_OP_IN &&
3202
 
                 (self->ctx->ptr >= self->end ||
3203
 
                  !SRE_CHARSET(self->ctx->pattern + 3,
3204
 
                               (SRE_CODE)*self->ctx->ptr))) {
3205
 
             /* Character Class Miss-Match, continue */
3206
 
            continue;
3207
 
        }
3208
 
 
3209
 
        state->ptr = self->ctx->ptr;
3210
 
 
3211
 
        return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
3212
 
                                                  JUMP_BRANCH,
3213
 
                                                  self->ctx->pattern +
3214
 
                                                  1);
3215
 
    }
3216
 
 
3217
 
    if (self->ctx->u.rep) {
3218
 
        SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
3219
 
    }
3220
 
 
3221
 
    return SRE_MATCH_RETURN_FAILURE(self);
3222
 
    /* TODO: Go to exit */
3223
 
}
3224
 
 
3225
 
/* TODO: SRE_MATCH_ON_JUMP_ASSERT */
3226
 
/* TODO: SRE_MATCH_ON_JUMP_ASSERT_NOT */
 
3359
    else {
 
3360
        /* If there is a Repeat Context stored in this Context */
 
3361
        if (self->ctx->u.rep) {
 
3362
            /* Preserve the Mark left there by the original Branch */
 
3363
            /* handler */
 
3364
            SRE_MATCH_MARK_POP_KEEP(state, self->ctx->lastmark);
 
3365
        }
 
3366
 
 
3367
        /* Restore the previous Mark stored in the Current Context to be */
 
3368
        /* the current last Mark. */
 
3369
        SRE_MATCH_LASTMARK_RESTORE(self, state);
 
3370
 
 
3371
        /* This is done as a do-while because it represnts the return */
 
3372
        /* to the for iteration, which would increment */
 
3373
        /* self->ctx->pattern by skip before continuing */
 
3374
        do {
 
3375
            /* The last Branch option would or has failed to match */
 
3376
            /* Increment the pattern to the next branch point */
 
3377
            self->ctx->pattern += skip;
 
3378
 
 
3379
            /* Update the named aliases list */
 
3380
            skip = (int)self->ctx->pattern[0];
 
3381
            p_next_op = &self->ctx->pattern[1];
 
3382
            literal = (SRE_CHAR)self->ctx->pattern[2];
 
3383
            set = &self->ctx->pattern[3];
 
3384
 
 
3385
        /* Skip simple match cases; e.g. Literal and In op codes */
 
3386
        /* If skip is the <FAILURE> op code, it will be zero and the */
 
3387
        /* loop will exit */
 
3388
        } while (skip &&
 
3389
 
 
3390
                  /* Check for Literal Miss-Match */
 
3391
                 ((*p_next_op == SRE_OP_LITERAL &&
 
3392
                    /* Check for End of Input Stream */
 
3393
                   (self->ctx->ptr >= self->end ||
 
3394
                    /* Check for Literal Miss-match */
 
3395
                    (SRE_CODE)*self->ctx->ptr != literal)) ||
 
3396
 
 
3397
                  /* Check for Character Class Miss-Match */
 
3398
                  (*p_next_op == SRE_OP_IN &&
 
3399
                    /* Check for End of Input Stream */
 
3400
                   (self->ctx->ptr >= self->end ||
 
3401
                    /* Check for Character not in Class */
 
3402
                    !SRE_CHARSET(set, (SRE_CODE)*self->ctx->ptr)))));
 
3403
 
 
3404
        /* If skip is the <FAILURE> op code, it will be zero and the */
 
3405
        /* pseudo-recursion will be skipped. */
 
3406
        if (skip) {
 
3407
            /* Set the current input buffer position to that stored */
 
3408
            /* in the Current Context */
 
3409
            state->ptr = self->ctx->ptr;
 
3410
 
 
3411
            /* Move the match pattern to the next code block's op */
 
3412
            /* code and create a new parse sub-context */
 
3413
            /* Go to this function (SRE_MATCH_ON_JUMP_BRANCH) when */
 
3414
            /* stack is popped */
 
3415
            /*** Prepare for Pseudo-Recursion ***/
 
3416
            /* Return non-zero on error */
 
3417
            if (SRE_MATCH_DATA_ALLOC(self, state, &nextctx)) {
 
3418
                return SRE_MATCH_FAIL;
 
3419
            }
 
3420
            nextctx->last_ctx_pos = self->ctx_pos;
 
3421
            nextctx->jump = JUMP_BRANCH;
 
3422
            nextctx->pattern = p_next_op;
 
3423
            self->ctx_pos = self->alloc_pos;
 
3424
            self->ctx = nextctx;
 
3425
            /* goto entrance; */
 
3426
            /* jump_branch: */
 
3427
            /*** Restore after Pseudo-Recursion ***/
 
3428
            self->good = SRE_MATCH_EXIT;
 
3429
            return SRE_MATCH_PASS;
 
3430
            return SRE_MATCH_ON_PUSH_CTX_AND_POSITION(self, state,
 
3431
                                                      JUMP_BRANCH,
 
3432
                                                      p_next_op);
 
3433
        }
 
3434
        else {
 
3435
            /* There are no more codes sections in the Branch, and */
 
3436
            /* none of the previous ones matched, so fail and pop */
 
3437
            /* stack. */
 
3438
 
 
3439
            if (self->ctx->u.rep) {
 
3440
                /* A mark was left in the Context's Repeat Context; */
 
3441
                /* discard it */
 
3442
                SRE_MATCH_MARK_POP_DISCARD(state, self->ctx->lastmark);
 
3443
            }
 
3444
 
 
3445
            /* Fail and Pop COntext */
 
3446
            return SRE_MATCH_RETURN_FAILURE(self);
 
3447
        }
 
3448
    }
 
3449
}
 
3450
 
 
3451
Py_LOCAL_INLINE(Py_ssize_t)
 
3452
SRE_MATCH_ON_JUMP_ASSERT(SRE_MATCH_GLOBAL_CONTEXT *self,
 
3453
                         SRE_STATE *state)
 
3454
{
 
3455
    /* assert subpattern */
 
3456
    /* <ASSERT> <skip> <back> <pattern> <SUCCESS> tail */
 
3457
    /* <skip> points to tail */ 
 
3458
    /* <back> is 0 for look-ahead */
 
3459
    int skip = (int)self->ctx->pattern[0];
 
3460
    /* back is not used */
 
3461
    /* pattern is not used */
 
3462
 
 
3463
    TRACE(("|%p|%p|JUMP_ASSERT\n", self->ctx->pattern, self->ctx->ptr));
 
3464
 
 
3465
    /* Check for failure */
 
3466
    if (self->ret < 0) {
 
3467
        return SRE_MATCH_FAIL;
 
3468
    }
 
3469
    else if (self->ret == 0) {
 
3470
        return SRE_MATCH_RETURN_FAILURE(self);
 
3471
    }
 
3472
    else {
 
3473
        /* Advance Pattern to Next Op Code */
 
3474
        self->ctx->pattern += skip;
 
3475
 
 
3476
        /* Successful Return */
 
3477
        return SRE_MATCH_PASS;
 
3478
    }
 
3479
}
 
3480
 
 
3481
Py_LOCAL_INLINE(Py_ssize_t)
 
3482
SRE_MATCH_ON_JUMP_ASSERT_NOT(SRE_MATCH_GLOBAL_CONTEXT *self,
 
3483
                             SRE_STATE *state)
 
3484
{
 
3485
    /* assert subpattern */
 
3486
    /* <ASSERT_NOT> <skip> <back> <pattern> <SUCCESS> tail */
 
3487
    /* <skip> points to tail */ 
 
3488
    /* <back> is 0 for look-ahead */
 
3489
    int skip = (int)self->ctx->pattern[0];
 
3490
    /* back is not used */
 
3491
    /* pattern is not used */
 
3492
 
 
3493
    TRACE(("|%p|%p|JUMP_ASSERT_NOT\n", self->ctx->pattern,
 
3494
           self->ctx->ptr));
 
3495
 
 
3496
    /* Check for Errors, and if successful, fail because this is */
 
3497
    /* Not Assert */
 
3498
    if (self->ret) {
 
3499
        if (self->ret < 0) {
 
3500
            return SRE_MATCH_FAIL;
 
3501
        }
 
3502
        else {
 
3503
            return SRE_MATCH_RETURN_FAILURE(self);
 
3504
        }
 
3505
    }
 
3506
    else {
 
3507
        /* Advance Pattern to Next Op Code */
 
3508
        self->ctx->pattern += skip;
 
3509
 
 
3510
        /* Successful Return */
 
3511
        return SRE_MATCH_PASS;
 
3512
    }
 
3513
}
3227
3514
 
3228
3515
Py_ssize_t (*SRE_MATCH_LOOKUP_TABLE[SRE_OP__COUNT])
3229
3516
           (SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state) = {
3231
3518
    SRE_MATCH_ON_SUCCESS, /* SRE_OP_SUCCESS */
3232
3519
    SRE_MATCH_ON_ANY, /* SRE_OP_ANY */
3233
3520
    SRE_MATCH_ON_ANY_ALL, /* SRE_OP_ANY_ALL */
3234
 
    0, /* SRE_OP_ASSERT */
3235
 
    0, /* SRE_OP_ASSERT_NOT */
 
3521
    SRE_MATCH_ON_ASSERT, /* SRE_OP_ASSERT */
 
3522
    SRE_MATCH_ON_ASSERT_NOT, /* SRE_OP_ASSERT_NOT */
3236
3523
    SRE_MATCH_ON_AT, /* SRE_OP_AT */
3237
3524
    SRE_MATCH_ON_BRANCH, /* SRE_OP_BRANCH */
3238
 
    0, /* SRE_OP_CALL */
 
3525
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_CALL */
3239
3526
    SRE_MATCH_ON_CATEGORY, /* SRE_OP_CATEGORY */
3240
 
    0, /* SRE_OP_CHARSET */
3241
 
    0, /* SRE_OP_BIGCHARSET */
3242
 
    0, /* SRE_OP_GROUPREF */
3243
 
    0, /* SRE_OP_GROUPREF_EXISTS */
3244
 
    0, /* SRE_OP_GROUPREF_IGNORE */
 
3527
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_CHARSET */
 
3528
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_BIGCHARSET */
 
3529
    SRE_MATCH_ON_GROUPREF, /* SRE_OP_GROUPREF */
 
3530
    SRE_MATCH_ON_GROUPREF_EXISTS, /* SRE_OP_GROUPREF_EXISTS */
 
3531
    SRE_MATCH_ON_GROUPREF_IGNORE, /* SRE_OP_GROUPREF_IGNORE */
3245
3532
    SRE_MATCH_ON_IN, /* SRE_OP_IN */
3246
3533
    SRE_MATCH_ON_IN_IGNORE, /* SRE_OP_IN_IGNORE */
3247
3534
    SRE_MATCH_ON_JUMP, /* SRE_OP_INFO (Ignore Info and Jump Pass it) */
3249
3536
    SRE_MATCH_ON_LITERAL, /* SRE_OP_LITERAL */
3250
3537
    SRE_MATCH_ON_LITERAL_IGNORE, /* SRE_OP_LITERAL_IGNORE */
3251
3538
    SRE_MATCH_ON_MARK, /* SRE_OP_MARK */
3252
 
    0, /* SRE_OP_MAX_UNTIL */
3253
 
    0, /* SRE_OP_MIN_UNTIL */
3254
 
    0, /* SRE_OP_NOT_LITERAL */
3255
 
    0, /* SRE_OP_NOT_LITERAL_IGNORE */
3256
 
    0, /* SRE_OP_NEGATE */
3257
 
    0, /* SRE_OP_RANGE */
3258
 
    0, /* SRE_OP_REPEAT */
 
3539
    SRE_MATCH_ON_MAX_UNTIL, /* SRE_OP_MAX_UNTIL */
 
3540
    SRE_MATCH_ON_MIN_UNTIL, /* SRE_OP_MIN_UNTIL */
 
3541
    SRE_MATCH_ON_NOT_LITERAL, /* SRE_OP_NOT_LITERAL */
 
3542
    SRE_MATCH_ON_NOT_LITERAL_IGNORE, /* SRE_OP_NOT_LITERAL_IGNORE */
 
3543
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_NEGATE */
 
3544
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_RANGE */
 
3545
    SRE_MATCH_ON_REPEAT, /* SRE_OP_REPEAT */
3259
3546
    SRE_MATCH_ON_REPEAT_ONE, /* SRE_OP_REPEAT_ONE */
3260
 
    0, /* SRE_OP_SUBPATTERN */
3261
 
    0, /* SRE_OP_MIN_REPEAT_ONE */
 
3547
    SRE_MATCH_ON_DEFAULT, /* (not used) SRE_OP_SUBPATTERN */
 
3548
    SRE_MATCH_ON_MIN_REPEAT_ONE, /* SRE_OP_MIN_REPEAT_ONE */
3262
3549
    0, /* SRE_OP_ATOMIC_START */
3263
3550
    0, /* SRE_OP_ATOMIC_END */
3264
3551
    0 /* SRE_OP_POSSESSIVE */
3267
3554
Py_ssize_t (*SRE_MATCH_UNWIND_LOOKUP_TABLE[JUMP__COUNT])
3268
3555
           (SRE_MATCH_GLOBAL_CONTEXT *self, SRE_STATE *state) = {
3269
3556
    SRE_MATCH_ON_JUMP_NONE, /* JUMP_NONE */
3270
 
    0, /* JUMP_MAX_UNTIL_1 */
3271
 
    0, /* JUMP_MAX_UNTIL_2 */
3272
 
    0, /* JUMP_MAX_UNTIL_3 */
3273
 
    0, /* JUMP_MIN_UNTIL_1 */
3274
 
    0, /* JUMP_MIN_UNTIL_2 */
3275
 
    0, /* JUMP_MIN_UNTIL_3 */
3276
 
    0, /* JUMP_REPEAT */
 
3557
    SRE_MATCH_ON_JUMP_MAX_UNTIL_1, /* JUMP_MAX_UNTIL_1 */
 
3558
    SRE_MATCH_ON_JUMP_MAX_UNTIL_2, /* JUMP_MAX_UNTIL_2 */
 
3559
    SRE_MATCH_ON_JUMP_MAX_UNTIL_3, /* JUMP_MAX_UNTIL_3 */
 
3560
    SRE_MATCH_ON_JUMP_MIN_UNTIL_1, /* JUMP_MIN_UNTIL_1 */
 
3561
    SRE_MATCH_ON_JUMP_MIN_UNTIL_2, /* JUMP_MIN_UNTIL_2 */
 
3562
    SRE_MATCH_ON_JUMP_MIN_UNTIL_3, /* JUMP_MIN_UNTIL_3 */
 
3563
    SRE_MATCH_ON_JUMP_REPEAT, /* JUMP_REPEAT */
3277
3564
    SRE_MATCH_ON_JUMP_REPEAT_ONE_1, /* JUMP_REPEAT_ONE_1 */
3278
3565
    SRE_MATCH_ON_JUMP_REPEAT_ONE_2, /* JUMP_REPEAT_ONE_2 */
3279
 
    0, /* JUMP_MIN_REPEAT_ONE */
 
3566
    SRE_MATCH_ON_JUMP_MIN_REPEAT_ONE, /* JUMP_MIN_REPEAT_ONE */
3280
3567
    SRE_MATCH_ON_JUMP_BRANCH, /* JUMP_BRANCH */
3281
 
    0, /* JUMP_ASSERT */
3282
 
    0 /* JUMP_ASSERT_NOT */
 
3568
    SRE_MATCH_ON_JUMP_ASSERT, /* JUMP_ASSERT */
 
3569
    SRE_MATCH_ON_JUMP_ASSERT_NOT /* JUMP_ASSERT_NOT */
3283
3570
};
3284
3571
 
 
3572
/* check if string matches the given pattern.  returns <0 for
 
3573
   error, 0 for failure, and 1 for success */
3285
3574
Py_LOCAL_INLINE(Py_ssize_t)
3286
3575
SRE_MATCH_ON_PUSH_CTX_AND_POSITION(SRE_MATCH_GLOBAL_CONTEXT *self,
3287
3576
                                   SRE_STATE *state, Py_ssize_t jump,
3303
3592
 
3304
3593
    if (self->ctx->pattern[0] == SRE_OP_INFO) {
3305
3594
        /* optimization info block */
3306
 
        /* <INFO> <1=skip> <2=flags> <3=min> ... */
 
3595
        /* <INFO> <1=skip> <2=flags> <3=min> ... tail */
3307
3596
        /* Info gives the minimum charaters needed to match in */
3308
3597
        /* *OP + 3; So if the input string is less than that, fail. */
 
3598
        /* <skip> points to tail */
3309
3599
        int skip = (int)self->ctx->pattern[1];
3310
3600
        /* Flags not used */
3311
3601
        int min = (int)self->ctx->pattern[3];
3352
3642
    }
3353
3643
}
3354
3644
 
3355
 
/* check if string matches the given pattern.  returns <0 for
3356
 
   error, 0 for failure, and 1 for success */
3357
3645
Py_LOCAL_INLINE(Py_ssize_t)
3358
3646
SRE_MATCH(SRE_STATE* state, SRE_CODE* pattern)
3359
3647
{
3427
3715
}
3428
3716
 
3429
3717
LOCAL(Py_ssize_t)
3430
 
SRE_MATCHa(SRE_STATE* state, SRE_CODE* pattern)
3431
 
{
3432
 
    Py_ssize_t i;
3433
 
    unsigned int sigcount; /* Iteration Counter; used for signalling */ 
3434
 
    SRE_MATCH_CONTEXT *nextctx; /* Next Context */
3435
 
 
3436
 
    SRE_MATCH_GLOBAL_CONTEXT self = {
3437
 
        /* Member Initialization */
3438
 
        0, /* end (init below) */
3439
 
        0, /* alloc_pos */
3440
 
        -1, /* ctx_pos */
3441
 
        0, /* ret (default to success) */
3442
 
        JUMP_NONE, /* jump */
3443
 
        0, /* ctx (pointer) */
3444
 
        (unsigned int)-1 /* op_code */
3445
 
    };
3446
 
    self.end = (SRE_CHAR *)state->end;
3447
 
 
3448
 
    TRACE(("|%p|%p|ENTER\n", pattern, state->ptr));
3449
 
 
3450
 
    SRE_MATCH_DATA_ALLOC(&self, state, &self.ctx);
3451
 
    self.ctx->last_ctx_pos = -1;
3452
 
    self.ctx->jump = JUMP_NONE;
3453
 
    self.ctx->pattern = pattern;
3454
 
    self.ctx_pos = self.alloc_pos;
3455
 
 
3456
 
entrance:
3457
 
 
3458
 
    SRE_MATCH_PARSE_HEADER(&self, state);
3459
 
    /* TODO: Go to exit on !self.good */
3460
 
 
3461
 
    for (;;) {
3462
 
        ++sigcount;
3463
 
        /* Every 1024 iterations, accept an interrupt from the user */
3464
 
        if ((0 == (sigcount & 0xfff)) && PyErr_CheckSignals())
3465
 
            return SRE_MATCH_RETURN_ERROR(&self, SRE_ERROR_INTERRUPTED);
3466
 
            /* TODO: when this is called, should return right away! */
3467
 
 
3468
 
        switch (*self.ctx->pattern++) {
3469
 
 
3470
 
        case SRE_OP_MARK:
3471
 
            SRE_MATCH_ON_MARK(&self, state);
3472
 
            break;
3473
 
 
3474
 
        case SRE_OP_LITERAL:
3475
 
            if (!SRE_MATCH_ON_LITERAL(&self, state)) {
3476
 
                /* TODO: Check for ret < 0 and if so return */
3477
 
                goto exit;
3478
 
            }
3479
 
            break;
3480
 
 
3481
 
        case SRE_OP_NOT_LITERAL:
3482
 
            if (!SRE_MATCH_ON_NOT_LITERAL(&self, state)) {
3483
 
                /* TODO: Check for ret < 0 and if so return */
3484
 
                goto exit;
3485
 
            }
3486
 
            break;
3487
 
 
3488
 
        case SRE_OP_SUCCESS:
3489
 
            if (!SRE_MATCH_ON_SUCCESS(&self, state)) {
3490
 
                /* TODO: Check for ret < 0 and if so return */
3491
 
                goto exit;
3492
 
            }
3493
 
            /* Should never get here; always sets self.good to false */
3494
 
 
3495
 
        case SRE_OP_AT:
3496
 
            if (!SRE_MATCH_ON_AT(&self, state)) {
3497
 
                /* TODO: Check for ret < 0 and if so return */
3498
 
                goto exit;
3499
 
            }
3500
 
            break;
3501
 
 
3502
 
        case SRE_OP_CATEGORY:
3503
 
            if (!SRE_MATCH_ON_CATEGORY(&self, state)) {
3504
 
                /* TODO: Check for ret < 0 and if so return */
3505
 
                goto exit;
3506
 
            }
3507
 
            break;
3508
 
 
3509
 
        case SRE_OP_ANY:
3510
 
            if (!SRE_MATCH_ON_ANY(&self, state)) {
3511
 
                /* TODO: Check for ret < 0 and if so return */
3512
 
                goto exit;
3513
 
            }
3514
 
            break;
3515
 
 
3516
 
        case SRE_OP_ANY_ALL:
3517
 
            if (!SRE_MATCH_ON_ANY_ALL(&self, state)) {
3518
 
                /* TODO: Check for ret < 0 and if so return */
3519
 
                goto exit;
3520
 
            }
3521
 
            break;
3522
 
 
3523
 
        case SRE_OP_IN:
3524
 
            if (!SRE_MATCH_ON_IN(&self, state)) {
3525
 
                /* TODO: Check for ret < 0 and if so return */
3526
 
                goto exit;
3527
 
            }
3528
 
            break;
3529
 
 
3530
 
        case SRE_OP_LITERAL_IGNORE:
3531
 
            if (!SRE_MATCH_ON_LITERAL_IGNORE(&self, state)) {
3532
 
                /* TODO: Check for ret < 0 and if so return */
3533
 
                goto exit;
3534
 
            }
3535
 
            break;
3536
 
 
3537
 
        case SRE_OP_NOT_LITERAL_IGNORE:
3538
 
            if (!SRE_MATCH_ON_NOT_LITERAL_IGNORE(&self, state)) {
3539
 
                /* TODO: Check for ret < 0 and if so return */
3540
 
                goto exit;
3541
 
            }
3542
 
            break;
3543
 
 
3544
 
        case SRE_OP_IN_IGNORE:
3545
 
            if (!SRE_MATCH_ON_IN_IGNORE(&self, state)) {
3546
 
                /* TODO: Check for ret < 0 and if so return */
3547
 
                goto exit;
3548
 
            }
3549
 
            break;
3550
 
 
3551
 
        case SRE_OP_JUMP:
3552
 
        case SRE_OP_INFO:
3553
 
            SRE_MATCH_ON_JUMP(&self, state);
3554
 
            break;
3555
 
 
3556
 
        case SRE_OP_BRANCH:
3557
 
            /* alternation */
3558
 
            /* <BRANCH> <0=skip> code <JUMP> ... <NULL> */
3559
 
            TRACE(("|%p|%p|BRANCH\n", self.ctx->pattern, self.ctx->ptr));
3560
 
            SRE_MATCH_LASTMARK_SAVE(&self, state);
3561
 
            self.ctx->u.rep = state->repeat;
3562
 
            if (self.ctx->u.rep)
3563
 
                SRE_MATCH_MARK_PUSH(&self, state, self.ctx->lastmark);
3564
 
            for (; self.ctx->pattern[0]; self.ctx->pattern += self.ctx->pattern[0]) {
3565
 
                if (self.ctx->pattern[1] == SRE_OP_LITERAL &&
3566
 
                    (self.ctx->ptr >= self.end ||
3567
 
                     (SRE_CODE) *self.ctx->ptr != self.ctx->pattern[2]))
3568
 
                    continue;
3569
 
                if (self.ctx->pattern[1] == SRE_OP_IN &&
3570
 
                    (self.ctx->ptr >= self.end ||
3571
 
                     !SRE_CHARSET(self.ctx->pattern + 3, (SRE_CODE) *self.ctx->ptr)))
3572
 
                    continue;
3573
 
                state->ptr = self.ctx->ptr;
3574
 
                /*** Prepare for Pseudo-Recursion ***/
3575
 
                SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3576
 
                nextctx->last_ctx_pos = self.ctx_pos;
3577
 
                nextctx->jump = JUMP_BRANCH;
3578
 
                nextctx->pattern = self.ctx->pattern + 1;
3579
 
                self.ctx_pos = self.alloc_pos;
3580
 
                self.ctx = nextctx;
3581
 
                goto entrance;
3582
 
                jump_branch:
3583
 
                /*** Restore after Pseudo-Recursion ***/
3584
 
                if (self.ret) {
3585
 
                    if (self.ctx->u.rep)
3586
 
                        SRE_MATCH_MARK_POP_DISCARD(state, self.ctx->lastmark);
3587
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3588
 
                    /* TODO: Return if error */
3589
 
                    SRE_MATCH_RETURN_SUCCESS(&self);
3590
 
                    /* TODO: Go to exit */
3591
 
                }
3592
 
                if (self.ctx->u.rep)
3593
 
                    SRE_MATCH_MARK_POP_KEEP(state, self.ctx->lastmark);
3594
 
                SRE_MATCH_LASTMARK_RESTORE(&self, state);
3595
 
            }
3596
 
            if (self.ctx->u.rep)
3597
 
                SRE_MATCH_MARK_POP_DISCARD(state, self.ctx->lastmark);
3598
 
            SRE_MATCH_RETURN_FAILURE(&self);
3599
 
            /* TODO: Go to exit */
3600
 
 
3601
 
        case SRE_OP_REPEAT_ONE:
3602
 
            /* match repeated sequence (maximizing regexp) */
3603
 
 
3604
 
            /* this operator only works if the repeated item is
3605
 
               exactly one character wide, and we're not already
3606
 
               collecting backtracking points.  for other cases,
3607
 
               use the MAX_REPEAT operator */
3608
 
 
3609
 
            /* <REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
3610
 
 
3611
 
            TRACE(("|%p|%p|REPEAT_ONE %d %d\n", self.ctx->pattern, self.ctx->ptr,
3612
 
                   self.ctx->pattern[1], self.ctx->pattern[2]));
3613
 
 
3614
 
            if (self.ctx->ptr + self.ctx->pattern[1] > self.end)
3615
 
                SRE_MATCH_RETURN_FAILURE(&self); /* cannot match */
3616
 
                /* TODO: Go to exit */
3617
 
 
3618
 
            state->ptr = self.ctx->ptr;
3619
 
 
3620
 
            self.ret = SRE_COUNT(state, self.ctx->pattern+3, self.ctx->pattern[2]);
3621
 
            SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3622
 
            /* TODO: Return if error */
3623
 
            SRE_MATCH_DATA_LOOKUP_AT(state, &self.ctx, self.ctx_pos);
3624
 
            self.ctx->count = self.ret;
3625
 
            self.ctx->ptr += self.ctx->count;
3626
 
 
3627
 
            /* when we arrive here, count contains the number of
3628
 
               matches, and self.ctx->ptr points to the tail of the target
3629
 
               string.  check if the rest of the pattern matches,
3630
 
               and backtrack if not. */
3631
 
 
3632
 
            if (self.ctx->count < (Py_ssize_t) self.ctx->pattern[1])
3633
 
                SRE_MATCH_RETURN_FAILURE(&self);
3634
 
                /* TODO: Go to exit */
3635
 
 
3636
 
            if (self.ctx->pattern[self.ctx->pattern[0]] == SRE_OP_SUCCESS) {
3637
 
                /* tail is empty.  we're finished */
3638
 
                state->ptr = self.ctx->ptr;
3639
 
                SRE_MATCH_RETURN_SUCCESS(&self);
3640
 
                /* TODO: Go to exit */
3641
 
            }
3642
 
 
3643
 
            SRE_MATCH_LASTMARK_SAVE(&self, state);
3644
 
 
3645
 
            if (self.ctx->pattern[self.ctx->pattern[0]] == SRE_OP_LITERAL) {
3646
 
                /* tail starts with a literal. skip positions where
3647
 
                   the rest of the pattern cannot possibly match */
3648
 
                self.ctx->u.chr = self.ctx->pattern[self.ctx->pattern[0]+1];
3649
 
                for (;;) {
3650
 
                    while (self.ctx->count >= (Py_ssize_t) self.ctx->pattern[1] &&
3651
 
                           (self.ctx->ptr >= self.end || *self.ctx->ptr != self.ctx->u.chr)) {
3652
 
                        self.ctx->ptr--;
3653
 
                        self.ctx->count--;
3654
 
                    }
3655
 
                    if (self.ctx->count < (Py_ssize_t) self.ctx->pattern[1])
3656
 
                        break;
3657
 
                    state->ptr = self.ctx->ptr;
3658
 
                    /*** Prepare for Pseudo-Recursion ***/
3659
 
                    SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3660
 
                    nextctx->last_ctx_pos = self.ctx_pos;
3661
 
                    nextctx->jump = JUMP_REPEAT_ONE_1;
3662
 
                    nextctx->pattern = self.ctx->pattern +
3663
 
                                       self.ctx->pattern[0];
3664
 
                    self.ctx_pos = self.alloc_pos;
3665
 
                    self.ctx = nextctx;
3666
 
                    goto entrance;
3667
 
                    jump_repeat_one_1:
3668
 
                    /*** Restore after Pseudo-Recursion ***/
3669
 
                    if (self.ret) {
3670
 
                        SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3671
 
                        /* TODO: Return if error */
3672
 
                        SRE_MATCH_RETURN_SUCCESS(&self);
3673
 
                        /* TODO: Go to exit */
3674
 
                    }
3675
 
 
3676
 
                    SRE_MATCH_LASTMARK_RESTORE(&self, state);
3677
 
 
3678
 
                    self.ctx->ptr--;
3679
 
                    self.ctx->count--;
3680
 
                }
3681
 
 
3682
 
            } else {
3683
 
                /* general case */
3684
 
                while (self.ctx->count >= (Py_ssize_t) self.ctx->pattern[1]) {
3685
 
                    state->ptr = self.ctx->ptr;
3686
 
                    /*** Prepare for Pseudo-Recursion ***/
3687
 
                    SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3688
 
                    nextctx->last_ctx_pos = self.ctx_pos;
3689
 
                    nextctx->jump = JUMP_REPEAT_ONE_2;
3690
 
                    nextctx->pattern = self.ctx->pattern +
3691
 
                                       self.ctx->pattern[0];
3692
 
                    self.ctx_pos = self.alloc_pos;
3693
 
                    self.ctx = nextctx;
3694
 
                    goto entrance;
3695
 
                    jump_repeat_one_2:
3696
 
                    /*** Restore after Pseudo-Recursion ***/
3697
 
                    if (self.ret) {
3698
 
                        SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3699
 
                        /* TODO: Return if error */
3700
 
                        SRE_MATCH_RETURN_SUCCESS(&self);
3701
 
                        /* TODO: Go to exit */
3702
 
                    }
3703
 
                    self.ctx->ptr--;
3704
 
                    self.ctx->count--;
3705
 
                    SRE_MATCH_LASTMARK_RESTORE(&self, state);
3706
 
                }
3707
 
            }
3708
 
            SRE_MATCH_RETURN_FAILURE(&self);
3709
 
            /* TODO: Go to exit */
3710
 
 
3711
 
        case SRE_OP_MIN_REPEAT_ONE:
3712
 
            /* match repeated sequence (minimizing regexp) */
3713
 
 
3714
 
            /* this operator only works if the repeated item is
3715
 
               exactly one character wide, and we're not already
3716
 
               collecting backtracking points.  for other cases,
3717
 
               use the MIN_REPEAT operator */
3718
 
 
3719
 
            /* <MIN_REPEAT_ONE> <skip> <1=min> <2=max> item <SUCCESS> tail */
3720
 
 
3721
 
            TRACE(("|%p|%p|MIN_REPEAT_ONE %d %d\n", self.ctx->pattern, self.ctx->ptr,
3722
 
                   self.ctx->pattern[1], self.ctx->pattern[2]));
3723
 
 
3724
 
            if (self.ctx->ptr + self.ctx->pattern[1] > self.end)
3725
 
                SRE_MATCH_RETURN_FAILURE(&self); /* cannot match */
3726
 
                /* TODO: Go to exit */
3727
 
 
3728
 
            state->ptr = self.ctx->ptr;
3729
 
 
3730
 
            if (self.ctx->pattern[1] == 0)
3731
 
                self.ctx->count = 0;
3732
 
            else {
3733
 
                /* count using pattern min as the maximum */
3734
 
                self.ret = SRE_COUNT(state, self.ctx->pattern+3, self.ctx->pattern[1]);
3735
 
                SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3736
 
                /* TODO: Return if error */
3737
 
                SRE_MATCH_DATA_LOOKUP_AT(state, &self.ctx, self.ctx_pos);
3738
 
                if (self.ret < (Py_ssize_t) self.ctx->pattern[1])
3739
 
                    /* didn't match minimum number of times */
3740
 
                    SRE_MATCH_RETURN_FAILURE(&self);
3741
 
                    /* TODO: Go to exit */
3742
 
                /* advance past minimum matches of repeat */
3743
 
                self.ctx->count = self.ret;
3744
 
                self.ctx->ptr += self.ctx->count;
3745
 
            }
3746
 
 
3747
 
            if (self.ctx->pattern[self.ctx->pattern[0]] == SRE_OP_SUCCESS) {
3748
 
                /* tail is empty.  we're finished */
3749
 
                state->ptr = self.ctx->ptr;
3750
 
                SRE_MATCH_RETURN_SUCCESS(&self);
3751
 
                /* TODO: Go to exit */
3752
 
 
3753
 
            } else {
3754
 
                /* general case */
3755
 
                SRE_MATCH_LASTMARK_SAVE(&self, state);
3756
 
                while ((Py_ssize_t)self.ctx->pattern[2] == 65535
3757
 
                       || self.ctx->count <= (Py_ssize_t)self.ctx->pattern[2]) {
3758
 
                    state->ptr = self.ctx->ptr;
3759
 
                    /*** Prepare for Pseudo-Recursion ***/
3760
 
                    SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3761
 
                    nextctx->last_ctx_pos = self.ctx_pos;
3762
 
                    nextctx->jump = JUMP_MIN_REPEAT_ONE;
3763
 
                    nextctx->pattern = self.ctx->pattern +
3764
 
                                       self.ctx->pattern[0];
3765
 
                    self.ctx_pos = self.alloc_pos;
3766
 
                    self.ctx = nextctx;
3767
 
                    goto entrance;
3768
 
                    jump_min_repeat_one:
3769
 
                    /*** Restore after Pseudo-Recursion ***/
3770
 
                    if (self.ret) {
3771
 
                        SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3772
 
                        /* TODO: Return if error */
3773
 
                        SRE_MATCH_RETURN_SUCCESS(&self);
3774
 
                        /* TODO: Go to exit */
3775
 
                    }
3776
 
                    state->ptr = self.ctx->ptr;
3777
 
                    self.ret = SRE_COUNT(state, self.ctx->pattern+3, 1);
3778
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3779
 
                    /* TODO: Return if error */
3780
 
                    SRE_MATCH_DATA_LOOKUP_AT(state, &self.ctx, self.ctx_pos);
3781
 
                    if (self.ret == 0)
3782
 
                        break;
3783
 
                    assert(self.ret == 1);
3784
 
                    self.ctx->ptr++;
3785
 
                    self.ctx->count++;
3786
 
                    SRE_MATCH_LASTMARK_RESTORE(&self, state);
3787
 
                }
3788
 
            }
3789
 
            SRE_MATCH_RETURN_FAILURE(&self);
3790
 
            /* TODO: Go to exit */
3791
 
 
3792
 
        case SRE_OP_REPEAT:
3793
 
            /* create repeat context.  all the hard work is done
3794
 
               by the UNTIL operator (MAX_UNTIL, MIN_UNTIL) */
3795
 
            /* <REPEAT> <skip> <1=min> <2=max> item <UNTIL> tail */
3796
 
            TRACE(("|%p|%p|REPEAT %d %d\n", self.ctx->pattern, self.ctx->ptr,
3797
 
                   self.ctx->pattern[1], self.ctx->pattern[2]));
3798
 
 
3799
 
            /* install new repeat context */
3800
 
            self.ctx->u.rep = (SRE_REPEAT*) PyObject_MALLOC(sizeof(*self.ctx->u.rep));
3801
 
            if (!self.ctx->u.rep) {
3802
 
                PyErr_NoMemory();
3803
 
                SRE_MATCH_RETURN_FAILURE(&self);
3804
 
                /* TODO: Go to exit */
3805
 
            }
3806
 
            self.ctx->u.rep->count = -1;
3807
 
            self.ctx->u.rep->pattern = self.ctx->pattern;
3808
 
            self.ctx->u.rep->prev = state->repeat;
3809
 
            self.ctx->u.rep->last_ptr = NULL;
3810
 
            state->repeat = self.ctx->u.rep;
3811
 
 
3812
 
            state->ptr = self.ctx->ptr;
3813
 
            /*** Prepare for Pseudo-Recursion ***/
3814
 
            SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3815
 
            nextctx->last_ctx_pos = self.ctx_pos;
3816
 
            nextctx->jump = JUMP_REPEAT;
3817
 
            nextctx->pattern = self.ctx->pattern +
3818
 
                               self.ctx->pattern[0];
3819
 
            self.ctx_pos = self.alloc_pos;
3820
 
            self.ctx = nextctx;
3821
 
            goto entrance;
3822
 
            jump_repeat:
3823
 
            /*** Restore after Pseudo-Recursion ***/
3824
 
            state->repeat = self.ctx->u.rep->prev;
3825
 
            PyObject_FREE(self.ctx->u.rep);
3826
 
 
3827
 
            if (self.ret) {
3828
 
                SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3829
 
                /* TODO: Return if error */
3830
 
                SRE_MATCH_RETURN_SUCCESS(&self);
3831
 
                /* TODO: Go to exit */
3832
 
            }
3833
 
            SRE_MATCH_RETURN_FAILURE(&self);
3834
 
            /* TODO: Go to exit */
3835
 
 
3836
 
        case SRE_OP_MAX_UNTIL:
3837
 
            /* maximizing repeat */
3838
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MAX_UNTIL> tail */
3839
 
 
3840
 
            /* FIXME: we probably need to deal with zero-width
3841
 
               matches in here... */
3842
 
 
3843
 
            self.ctx->u.rep = state->repeat;
3844
 
            if (!self.ctx->u.rep)
3845
 
                SRE_MATCH_RETURN_ERROR(&self, SRE_ERROR_STATE);
3846
 
                /* TODO: when this is called, should return right away! */
3847
 
 
3848
 
            state->ptr = self.ctx->ptr;
3849
 
 
3850
 
            self.ctx->count = self.ctx->u.rep->count+1;
3851
 
 
3852
 
            TRACE(("|%p|%p|MAX_UNTIL %d\n", self.ctx->pattern,
3853
 
                   self.ctx->ptr, self.ctx->count));
3854
 
 
3855
 
            if (self.ctx->count < self.ctx->u.rep->pattern[1]) {
3856
 
                /* not enough matches */
3857
 
                self.ctx->u.rep->count = self.ctx->count;
3858
 
                /*** Prepare for Pseudo-Recursion ***/
3859
 
                SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3860
 
                nextctx->last_ctx_pos = self.ctx_pos;
3861
 
                nextctx->jump = JUMP_MAX_UNTIL_1;
3862
 
                nextctx->pattern = self.ctx->u.rep->pattern + 3;
3863
 
                self.ctx_pos = self.alloc_pos;
3864
 
                self.ctx = nextctx;
3865
 
                goto entrance;
3866
 
                jump_max_until_1:
3867
 
                /*** Restore after Pseudo-Recursion ***/
3868
 
                if (self.ret) {
3869
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3870
 
                    /* TODO: Return if error */
3871
 
                    SRE_MATCH_RETURN_SUCCESS(&self);
3872
 
                    /* TODO: Go to exit */
3873
 
                }
3874
 
                self.ctx->u.rep->count = self.ctx->count-1;
3875
 
                state->ptr = self.ctx->ptr;
3876
 
                SRE_MATCH_RETURN_FAILURE(&self);
3877
 
                /* TODO: Go to exit */
3878
 
            }
3879
 
 
3880
 
            if ((self.ctx->count < self.ctx->u.rep->pattern[2] ||
3881
 
                self.ctx->u.rep->pattern[2] == 65535) &&
3882
 
                state->ptr != self.ctx->u.rep->last_ptr) {
3883
 
                /* we may have enough matches, but if we can
3884
 
                   match another item, do so */
3885
 
                self.ctx->u.rep->count = self.ctx->count;
3886
 
                SRE_MATCH_LASTMARK_SAVE(&self, state);
3887
 
                SRE_MATCH_MARK_PUSH(&self, state, self.ctx->lastmark);
3888
 
                /* zero-width match protection */
3889
 
                SRE_MATCH_DATA_PUSH(&self, state, &self.ctx->u.rep->last_ptr);
3890
 
                self.ctx->u.rep->last_ptr = state->ptr;
3891
 
                /*** Prepare for Pseudo-Recursion ***/
3892
 
                SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3893
 
                nextctx->last_ctx_pos = self.ctx_pos;
3894
 
                nextctx->jump = JUMP_MAX_UNTIL_2;
3895
 
                nextctx->pattern = self.ctx->u.rep->pattern + 3;
3896
 
                self.ctx_pos = self.alloc_pos;
3897
 
                self.ctx = nextctx;
3898
 
                goto entrance;
3899
 
                jump_max_until_2:
3900
 
                /*** Restore after Pseudo-Recursion ***/
3901
 
                SRE_MATCH_DATA_POP(state, &self.ctx->u.rep->last_ptr);
3902
 
                if (self.ret) {
3903
 
                    SRE_MATCH_MARK_POP_DISCARD(state, self.ctx->lastmark);
3904
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3905
 
                    /* TODO: Return if error */
3906
 
                    SRE_MATCH_RETURN_SUCCESS(&self);
3907
 
                    /* TODO: Go to exit */
3908
 
                }
3909
 
                SRE_MATCH_MARK_POP(state, self.ctx->lastmark);
3910
 
                SRE_MATCH_LASTMARK_RESTORE(&self, state);
3911
 
                self.ctx->u.rep->count = self.ctx->count-1;
3912
 
                state->ptr = self.ctx->ptr;
3913
 
            }
3914
 
 
3915
 
            /* cannot match more repeated items here.  make sure the
3916
 
               tail matches */
3917
 
            state->repeat = self.ctx->u.rep->prev;
3918
 
            /*** Prepare for Pseudo-Recursion ***/
3919
 
            SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3920
 
            nextctx->last_ctx_pos = self.ctx_pos;
3921
 
            nextctx->jump = JUMP_MAX_UNTIL_3;
3922
 
            nextctx->pattern = self.ctx->pattern;
3923
 
            self.ctx_pos = self.alloc_pos;
3924
 
            self.ctx = nextctx;
3925
 
            goto entrance;
3926
 
            jump_max_until_3:
3927
 
            /*** Restore after Pseudo-Recursion ***/
3928
 
            SRE_MATCH_RETURN_ON_SUCCESS(&self, self.ret);
3929
 
            /* TODO: Return if error; else Go to exit */
3930
 
            state->repeat = self.ctx->u.rep;
3931
 
            state->ptr = self.ctx->ptr;
3932
 
            SRE_MATCH_RETURN_FAILURE(&self);
3933
 
            /* TODO: Go to exit */
3934
 
 
3935
 
        case SRE_OP_MIN_UNTIL:
3936
 
            /* minimizing repeat */
3937
 
            /* <REPEAT> <skip> <1=min> <2=max> item <MIN_UNTIL> tail */
3938
 
 
3939
 
            self.ctx->u.rep = state->repeat;
3940
 
            if (!self.ctx->u.rep)
3941
 
                SRE_MATCH_RETURN_ERROR(&self, SRE_ERROR_STATE);
3942
 
                /* TODO: when this is called, should return right away! */
3943
 
 
3944
 
            state->ptr = self.ctx->ptr;
3945
 
 
3946
 
            self.ctx->count = self.ctx->u.rep->count+1;
3947
 
 
3948
 
            TRACE(("|%p|%p|MIN_UNTIL %d %p\n", self.ctx->pattern,
3949
 
                   self.ctx->ptr, self.ctx->count, self.ctx->u.rep->pattern));
3950
 
 
3951
 
            if (self.ctx->count < self.ctx->u.rep->pattern[1]) {
3952
 
                /* not enough matches */
3953
 
                self.ctx->u.rep->count = self.ctx->count;
3954
 
                /*** Prepare for Pseudo-Recursion ***/
3955
 
                SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3956
 
                nextctx->last_ctx_pos = self.ctx_pos;
3957
 
                nextctx->jump = JUMP_MIN_UNTIL_1;
3958
 
                nextctx->pattern = self.ctx->u.rep->pattern + 3;
3959
 
                self.ctx_pos = self.alloc_pos;
3960
 
                self.ctx = nextctx;
3961
 
                goto entrance;
3962
 
                jump_min_until_1:
3963
 
                /*** Restore after Pseudo-Recursion ***/
3964
 
                if (self.ret) {
3965
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3966
 
                    /* TODO: Return if error */
3967
 
                    SRE_MATCH_RETURN_SUCCESS(&self);
3968
 
                    /* TODO: Go to exit */
3969
 
                }
3970
 
                self.ctx->u.rep->count = self.ctx->count-1;
3971
 
                state->ptr = self.ctx->ptr;
3972
 
                SRE_MATCH_RETURN_FAILURE(&self);
3973
 
                /* TODO: Go to exit */
3974
 
            }
3975
 
 
3976
 
            SRE_MATCH_LASTMARK_SAVE(&self, state);
3977
 
 
3978
 
            /* see if the tail matches */
3979
 
            state->repeat = self.ctx->u.rep->prev;
3980
 
            /*** Prepare for Pseudo-Recursion ***/
3981
 
            SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
3982
 
            nextctx->last_ctx_pos = self.ctx_pos;
3983
 
            nextctx->jump = JUMP_MIN_UNTIL_2;
3984
 
            nextctx->pattern = self.ctx->pattern;
3985
 
            self.ctx_pos = self.alloc_pos;
3986
 
            self.ctx = nextctx;
3987
 
            goto entrance;
3988
 
            jump_min_until_2:
3989
 
            /*** Restore after Pseudo-Recursion ***/
3990
 
            if (self.ret) {
3991
 
                SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
3992
 
                /* TODO: Return if error */
3993
 
                SRE_MATCH_RETURN_SUCCESS(&self);
3994
 
                /* TODO: Go to exit */
3995
 
            }
3996
 
 
3997
 
            state->repeat = self.ctx->u.rep;
3998
 
            state->ptr = self.ctx->ptr;
3999
 
 
4000
 
            SRE_MATCH_LASTMARK_RESTORE(&self, state);
4001
 
 
4002
 
            if (self.ctx->count >= self.ctx->u.rep->pattern[2]
4003
 
                && self.ctx->u.rep->pattern[2] != 65535)
4004
 
                SRE_MATCH_RETURN_FAILURE(&self);
4005
 
                /* TODO: Go to exit */
4006
 
 
4007
 
            self.ctx->u.rep->count = self.ctx->count;
4008
 
            /*** Prepare for Pseudo-Recursion ***/
4009
 
            SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
4010
 
            nextctx->last_ctx_pos = self.ctx_pos;
4011
 
            nextctx->jump = JUMP_MIN_UNTIL_3;
4012
 
            nextctx->pattern = self.ctx->u.rep->pattern + 3;
4013
 
            self.ctx_pos = self.alloc_pos;
4014
 
            self.ctx = nextctx;
4015
 
            goto entrance;
4016
 
            jump_min_until_3:
4017
 
            /*** Restore after Pseudo-Recursion ***/
4018
 
            if (self.ret) {
4019
 
                SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
4020
 
                /* TODO: Return if error */
4021
 
                SRE_MATCH_RETURN_SUCCESS(&self);
4022
 
                /* TODO: Go to exit */
4023
 
            }
4024
 
            self.ctx->u.rep->count = self.ctx->count-1;
4025
 
            state->ptr = self.ctx->ptr;
4026
 
            SRE_MATCH_RETURN_FAILURE(&self);
4027
 
            /* TODO: Go to exit */
4028
 
 
4029
 
        case SRE_OP_GROUPREF:
4030
 
            /* match backreference */
4031
 
            TRACE(("|%p|%p|GROUPREF %d\n", self.ctx->pattern,
4032
 
                   self.ctx->ptr, self.ctx->pattern[0]));
4033
 
            i = self.ctx->pattern[0];
4034
 
            {
4035
 
                Py_ssize_t groupref = i+i;
4036
 
                if (groupref >= state->lastmark) {
4037
 
                    SRE_MATCH_RETURN_FAILURE(&self);
4038
 
                    /* TODO: Go to exit */
4039
 
                } else {
4040
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
4041
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
4042
 
                    if (!p || !e || e < p)
4043
 
                        SRE_MATCH_RETURN_FAILURE(&self);
4044
 
                        /* TODO: Go to exit */
4045
 
                    while (p < e) {
4046
 
                        if (self.ctx->ptr >= self.end || *self.ctx->ptr != *p)
4047
 
                            SRE_MATCH_RETURN_FAILURE(&self);
4048
 
                            /* TODO: Go to exit */
4049
 
                        p++; self.ctx->ptr++;
4050
 
                    }
4051
 
                }
4052
 
            }
4053
 
            self.ctx->pattern++;
4054
 
            break;
4055
 
 
4056
 
        case SRE_OP_GROUPREF_IGNORE:
4057
 
            /* match backreference */
4058
 
            TRACE(("|%p|%p|GROUPREF_IGNORE %d\n", self.ctx->pattern,
4059
 
                   self.ctx->ptr, self.ctx->pattern[0]));
4060
 
            i = self.ctx->pattern[0];
4061
 
            {
4062
 
                Py_ssize_t groupref = i+i;
4063
 
                if (groupref >= state->lastmark) {
4064
 
                    SRE_MATCH_RETURN_FAILURE(&self);
4065
 
                    /* TODO: Go to exit */
4066
 
                } else {
4067
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
4068
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
4069
 
                    if (!p || !e || e < p)
4070
 
                        SRE_MATCH_RETURN_FAILURE(&self);
4071
 
                        /* TODO: Go to exit */
4072
 
                    while (p < e) {
4073
 
                        if (self.ctx->ptr >= self.end ||
4074
 
                            state->lower(*self.ctx->ptr) != state->lower(*p))
4075
 
                            SRE_MATCH_RETURN_FAILURE(&self);
4076
 
                            /* TODO: Go to exit */
4077
 
                        p++; self.ctx->ptr++;
4078
 
                    }
4079
 
                }
4080
 
            }
4081
 
            self.ctx->pattern++;
4082
 
            break;
4083
 
 
4084
 
        case SRE_OP_GROUPREF_EXISTS:
4085
 
            TRACE(("|%p|%p|GROUPREF_EXISTS %d\n", self.ctx->pattern,
4086
 
                   self.ctx->ptr, self.ctx->pattern[0]));
4087
 
            /* <GROUPREF_EXISTS> <group> <skip> codeyes <JUMP> codeno ... */
4088
 
            i = self.ctx->pattern[0];
4089
 
            {
4090
 
                Py_ssize_t groupref = i+i;
4091
 
                if (groupref >= state->lastmark) {
4092
 
                    self.ctx->pattern += self.ctx->pattern[1];
4093
 
                    break;
4094
 
                } else {
4095
 
                    SRE_CHAR* p = (SRE_CHAR*) state->mark[groupref];
4096
 
                    SRE_CHAR* e = (SRE_CHAR*) state->mark[groupref+1];
4097
 
                    if (!p || !e || e < p) {
4098
 
                        self.ctx->pattern += self.ctx->pattern[1];
4099
 
                        break;
4100
 
                    }
4101
 
                }
4102
 
            }
4103
 
            self.ctx->pattern += 2;
4104
 
            break;
4105
 
 
4106
 
        case SRE_OP_ASSERT:
4107
 
            /* assert subpattern */
4108
 
            /* <ASSERT> <skip> <back> <pattern> */
4109
 
            TRACE(("|%p|%p|ASSERT %d\n", self.ctx->pattern,
4110
 
                   self.ctx->ptr, self.ctx->pattern[1]));
4111
 
            state->ptr = self.ctx->ptr - self.ctx->pattern[1];
4112
 
            if (state->ptr < state->beginning)
4113
 
                SRE_MATCH_RETURN_FAILURE(&self);
4114
 
                /* TODO: Go to exit */
4115
 
            /*** Prepare for Pseudo-Recursion ***/
4116
 
            SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
4117
 
            nextctx->last_ctx_pos = self.ctx_pos;
4118
 
            nextctx->jump = JUMP_ASSERT;
4119
 
            nextctx->pattern = self.ctx->pattern + 2;
4120
 
            self.ctx_pos = self.alloc_pos;
4121
 
            self.ctx = nextctx;
4122
 
            goto entrance;
4123
 
            jump_assert:
4124
 
            /*** Restore after Pseudo-Recursion ***/
4125
 
            SRE_MATCH_RETURN_ON_FAILURE(&self, self.ret);
4126
 
            /* TODO: Return if error; else Go to exit */
4127
 
            self.ctx->pattern += self.ctx->pattern[0];
4128
 
            break;
4129
 
 
4130
 
        case SRE_OP_ASSERT_NOT:
4131
 
            /* assert not subpattern */
4132
 
            /* <ASSERT_NOT> <skip> <back> <pattern> */
4133
 
            TRACE(("|%p|%p|ASSERT_NOT %d\n", self.ctx->pattern,
4134
 
                   self.ctx->ptr, self.ctx->pattern[1]));
4135
 
            state->ptr = self.ctx->ptr - self.ctx->pattern[1];
4136
 
            if (state->ptr >= state->beginning) {
4137
 
                /*** Prepare for Pseudo-Recursion ***/
4138
 
                SRE_MATCH_DATA_ALLOC(&self, state, &nextctx);
4139
 
                nextctx->last_ctx_pos = self.ctx_pos;
4140
 
                nextctx->jump = JUMP_ASSERT_NOT;
4141
 
                nextctx->pattern = self.ctx->pattern + 2;
4142
 
                self.ctx_pos = self.alloc_pos;
4143
 
                self.ctx = nextctx;
4144
 
                goto entrance;
4145
 
                jump_assert_not:
4146
 
                /*** Restore after Pseudo-Recursion ***/
4147
 
                if (self.ret) {
4148
 
                    SRE_MATCH_RETURN_ON_ERROR(&self, self.ret);
4149
 
                    /* TODO: Return if error */
4150
 
                    SRE_MATCH_RETURN_FAILURE(&self);
4151
 
                    /* TODO: Go to exit */
4152
 
                }
4153
 
            }
4154
 
            self.ctx->pattern += self.ctx->pattern[0];
4155
 
            break;
4156
 
 
4157
 
        case SRE_OP_FAILURE:
4158
 
            if (!SRE_MATCH_ON_FAILURE(&self, state)) {
4159
 
                /* TODO: Check for ret < 0 and if so return */
4160
 
                goto exit;
4161
 
            }
4162
 
            break;
4163
 
 
4164
 
        default:
4165
 
            TRACE(("|%p|%p|UNKNOWN %d\n", self.ctx->pattern, self.ctx->ptr,
4166
 
                   self.ctx->pattern[-1]));
4167
 
            SRE_MATCH_RETURN_ERROR(&self, SRE_ERROR_ILLEGAL);
4168
 
            /* TODO: when this is called, should return right away! */
4169
 
        }
4170
 
    }
4171
 
 
4172
 
exit:
4173
 
    self.ctx_pos = self.ctx->last_ctx_pos;
4174
 
    self.jump = self.ctx->jump;
4175
 
    SRE_MATCH_DATA_POP_DISCARD(state);
4176
 
    if (self.ctx_pos == -1)
4177
 
        return self.ret;
4178
 
    SRE_MATCH_DATA_LOOKUP_AT(state, &self.ctx, self.ctx_pos);
4179
 
 
4180
 
    switch (self.jump) {
4181
 
        case JUMP_MAX_UNTIL_2:
4182
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_2\n", self.ctx->pattern, self.ctx->ptr));
4183
 
            goto jump_max_until_2;
4184
 
        case JUMP_MAX_UNTIL_3:
4185
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_3\n", self.ctx->pattern, self.ctx->ptr));
4186
 
            goto jump_max_until_3;
4187
 
        case JUMP_MIN_UNTIL_2:
4188
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_2\n", self.ctx->pattern, self.ctx->ptr));
4189
 
            goto jump_min_until_2;
4190
 
        case JUMP_MIN_UNTIL_3:
4191
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_3\n", self.ctx->pattern, self.ctx->ptr));
4192
 
            goto jump_min_until_3;
4193
 
        case JUMP_BRANCH:
4194
 
            TRACE(("|%p|%p|JUMP_BRANCH\n", self.ctx->pattern, self.ctx->ptr));
4195
 
            goto jump_branch;
4196
 
        case JUMP_MAX_UNTIL_1:
4197
 
            TRACE(("|%p|%p|JUMP_MAX_UNTIL_1\n", self.ctx->pattern, self.ctx->ptr));
4198
 
            goto jump_max_until_1;
4199
 
        case JUMP_MIN_UNTIL_1:
4200
 
            TRACE(("|%p|%p|JUMP_MIN_UNTIL_1\n", self.ctx->pattern, self.ctx->ptr));
4201
 
            goto jump_min_until_1;
4202
 
        case JUMP_REPEAT:
4203
 
            TRACE(("|%p|%p|JUMP_REPEAT\n", self.ctx->pattern, self.ctx->ptr));
4204
 
            goto jump_repeat;
4205
 
        case JUMP_REPEAT_ONE_1:
4206
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_1\n", self.ctx->pattern, self.ctx->ptr));
4207
 
            goto jump_repeat_one_1;
4208
 
        case JUMP_REPEAT_ONE_2:
4209
 
            TRACE(("|%p|%p|JUMP_REPEAT_ONE_2\n", self.ctx->pattern, self.ctx->ptr));
4210
 
            goto jump_repeat_one_2;
4211
 
        case JUMP_MIN_REPEAT_ONE:
4212
 
            TRACE(("|%p|%p|JUMP_MIN_REPEAT_ONE\n", self.ctx->pattern, self.ctx->ptr));
4213
 
            goto jump_min_repeat_one;
4214
 
        case JUMP_ASSERT:
4215
 
            TRACE(("|%p|%p|JUMP_ASSERT\n", self.ctx->pattern, self.ctx->ptr));
4216
 
            goto jump_assert;
4217
 
        case JUMP_ASSERT_NOT:
4218
 
            TRACE(("|%p|%p|JUMP_ASSERT_NOT\n", self.ctx->pattern, self.ctx->ptr));
4219
 
            goto jump_assert_not;
4220
 
        case JUMP_NONE:
4221
 
            TRACE(("|%p|%p|RETURN %d\n", self.ctx->pattern, self.ctx->ptr, self.ret));
4222
 
            break;
4223
 
    }
4224
 
 
4225
 
    return self.ret; /* should never get here */
4226
 
}
4227
 
 
4228
 
#endif /* !REMOVE_SRE_MATCH_MACROS */
4229
 
LOCAL(Py_ssize_t)
4230
3718
SRE_SEARCH(SRE_STATE* state, SRE_CODE* pattern)
4231
3719
{
4232
3720
    SRE_CHAR* ptr = (SRE_CHAR *)state->start;