| 613 | offset_width = len(str(len(code) - 1)) |
| 614 | |
| 615 | def dis_(start, end): |
| 616 | def print_(*args, to=None): |
| 617 | if to is not None: |
| 618 | labels.add(to) |
| 619 | args += ('(to %d)' % (to,),) |
| 620 | print('%*d%s ' % (offset_width, start, ':' if start in labels else '.'), |
| 621 | end=' '*(level-1)) |
| 622 | print(*args) |
| 623 | |
| 624 | def print_2(*args): |
| 625 | print(end=' '*(offset_width + 2*level)) |
| 626 | print(*args) |
| 627 | |
| 628 | nonlocal level |
| 629 | level += 1 |
| 630 | i = start |
| 631 | while i < end: |
| 632 | start = i |
| 633 | op = code[i] |
| 634 | i += 1 |
| 635 | op = OPCODES[op] |
| 636 | if op in (SUCCESS, FAILURE, ANY, ANY_ALL, |
| 637 | MAX_UNTIL, MIN_UNTIL, NEGATE): |
| 638 | print_(op) |
| 639 | elif op in (LITERAL, NOT_LITERAL, |
| 640 | LITERAL_IGNORE, NOT_LITERAL_IGNORE, |
| 641 | LITERAL_UNI_IGNORE, NOT_LITERAL_UNI_IGNORE, |
| 642 | LITERAL_LOC_IGNORE, NOT_LITERAL_LOC_IGNORE): |
| 643 | arg = code[i] |
| 644 | i += 1 |
| 645 | print_(op, '%#02x (%r)' % (arg, chr(arg))) |
| 646 | elif op is AT: |
| 647 | arg = code[i] |
| 648 | i += 1 |
| 649 | arg = str(ATCODES[arg]) |
| 650 | assert arg[:3] == 'AT_' |
| 651 | print_(op, arg[3:]) |
| 652 | elif op is CATEGORY: |
| 653 | arg = code[i] |
| 654 | i += 1 |
| 655 | arg = str(CHCODES[arg]) |
| 656 | assert arg[:9] == 'CATEGORY_' |
| 657 | print_(op, arg[9:]) |
| 658 | elif op in (IN, IN_IGNORE, IN_UNI_IGNORE, IN_LOC_IGNORE): |
| 659 | skip = code[i] |
| 660 | print_(op, skip, to=i+skip) |
| 661 | dis_(i+1, i+skip) |
| 662 | i += skip |
| 663 | elif op in (RANGE, RANGE_UNI_IGNORE): |
| 664 | lo, hi = code[i: i+2] |
| 665 | i += 2 |
| 666 | print_(op, '%#02x %#02x (%r-%r)' % (lo, hi, chr(lo), chr(hi))) |
| 667 | elif op is CHARSET: |
| 668 | print_(op, _hex_code(code[i: i + 256//_CODEBITS])) |
| 669 | i += 256//_CODEBITS |
| 670 | elif op is BIGCHARSET: |
| 671 | arg = code[i] |
| 672 | i += 1 |